Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lwip2 updates: no more git sub-sub-module deps, faster checksum, backlog limitation and other fixes #6887

Merged
merged 24 commits into from
Feb 18, 2020
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 33 additions & 11 deletions libraries/ESP8266WiFi/src/WiFiServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <include/ClientContext.h>

#ifndef MAX_DEFAULT_SIMULTANEOUS_CLIENTS_PER_PORT
#define MAX_DEFAULT_SIMULTANEOUS_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)
{
Expand All @@ -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)
{
Expand All @@ -59,7 +64,7 @@ void WiFiServer::begin() {
begin(_port);
}

void WiFiServer::begin(uint16_t port) {
void WiFiServer::begin(uint16_t port, uint8_t backlog) {
close();
_port = port;
err_t err;
Expand All @@ -77,13 +82,21 @@ void WiFiServer::begin(uint16_t port) {
return;
}

#if LWIP_VERSION_MAJOR == 1
(void)backlog;
tcp_pcb* listen_pcb = tcp_listen(pcb);
#else
if (backlog == 0)
devyte marked this conversation as resolved.
Show resolved Hide resolved
backlog = MAX_DEFAULT_SIMULTANEOUS_CLIENTS_PER_PORT;
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);
}
Expand Down Expand Up @@ -122,21 +135,21 @@ 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 {
return _port;
}

void WiFiServer::close() {
if (!_pcb) {
if (!_listen_pcb) {
return;
}
tcp_close(_pcb);
_pcb = nullptr;
tcp_close(_listen_pcb);
_listen_pcb = nullptr;
}

void WiFiServer::stop() {
Expand Down Expand Up @@ -171,7 +184,16 @@ long WiFiServer::_accept(tcp_pcb* apcb, long err) {
DEBUGV("WS:ac\r\n");
ClientContext* client = new ClientContext(apcb, &WiFiServer::_s_discard, this);
_unclaimed = slist_append_tail(_unclaimed, client);
tcp_accepted(_pcb);
#if LWIP_VERSION_MAJOR == 1
tcp_accepted(_listen_pcb);
#else
tcp_backlog_delayed(apcb);
// tcp_backlog_accepted() has to be called on this ClientContext's pcb (here = acpb)
// just before tcp_close() (but not needed before tcp_abort()).
// 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
client->write((const uint8_t*)"gotit",5);
#endif
return ERR_OK;
}

Expand Down
41 changes: 39 additions & 2 deletions libraries/ESP8266WiFi/src/WiFiServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,42 @@ extern "C" {
#include "Server.h"
#include "IPAddress.h"

// lwIP-v2 backlog facility allows to keep memory safe by limiting the
// maximum number of simultaneously accepted clients. Default number of
// possibly simultaneously accepted client is defined in WiFiServer.cpp,
// user can overide it at runtime from sketch:
// WiFiServer::begin(port, max-simultaneous-clients-per-port);
// New incoming clients to this server will be delayed until an already
// connected one leaves.
// By "delayed", it is meant that WiFiServer will not answer to the SYN
// packet until there is room for a new one: The server (tcp on that port)
// will be invisible. When a connected client leaves, the server will
// accept a newcomer at the moment when one of them retries to connect by
// sending another SYN (which will not immediately happen), and before it
// times-out trying to connect.
//
// Back to Arduino scenario:
//
// Usually only one client is used at a time: The client (like a http
// browser) is accepted, served then closed. The ESP8266WebServer cannot
// answer to another client during that time even if it is tcp-accepted
// (syn-acked), until the current one has been served.
//
// Now that backlog is enabled, at most
// MAX_DEFAULT_SIMULTANEOUS_CLIENTS_PER_PORT clients will be tcp-accepted by
// a WiFiServer even if it is currently busy serving one client (ie: busy
// and not checking WiFiServer::available()/hasClient()). But next clients
// will be kept out and will have to tcp-retry (as if they were trying to
// connect through a mute firewall):
// - Then eventually one of the connected clients leaves
// - Then a while *after* that moment a waiting/potential client say hello
// if it has not given up waiting (72 seconds on windows for the connect
// timeout).
//
// Note that ESPAsync servers may serve more than one client at a time so
// the default setting is not 1 or 2. It was 0xff by default. It can be
// overriden at runtime in WiFiServer::begin().

class ClientContext;
class WiFiClient;

Expand All @@ -39,7 +75,7 @@ class WiFiServer : public Server {
protected:
uint16_t _port;
IPAddress _addr;
tcp_pcb* _pcb;
tcp_pcb* _listen_pcb;

ClientContext* _unclaimed;
ClientContext* _discarded;
Expand All @@ -52,7 +88,8 @@ class WiFiServer : public Server {
WiFiClient available(uint8_t* status = NULL);
bool hasClient();
void begin();
void begin(uint16_t port);
void begin(uint16_t port) { begin(port, 0); }
void begin(uint16_t port, uint8_t backlog);
void setNoDelay(bool nodelay);
bool getNoDelay();
virtual size_t write(uint8_t);
Expand Down
5 changes: 5 additions & 0 deletions libraries/ESP8266WiFi/src/include/ClientContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ class ClientContext
tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL);
tcp_poll(_pcb, NULL, 0);
#if LWIP_VERSION_MAJOR != 1
// needed for clients from WiFiServer
// harmless for other clients
tcp_backlog_accepted(_pcb);
#endif
err = tcp_close(_pcb);
if(err != ERR_OK) {
DEBUGV(":tc err %d\r\n", (int) err);
Expand Down
2 changes: 1 addition & 1 deletion tests/host/common/MockWiFiServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down
13 changes: 7 additions & 6 deletions tests/host/common/MockWiFiServerSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@ int serverAccept (int srvsock)
return mockSockSetup(clisock);
}

void WiFiServer::begin (uint16_t port)
void WiFiServer::begin (uint16_t port, uint8_t backlog)
{
(void)backlog;
_port = port;
return begin();
}
Expand Down Expand Up @@ -109,13 +110,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;
}
Expand All @@ -134,7 +135,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);
}
Binary file modified tools/sdk/lib/liblwip2-1460-feat.a
Binary file not shown.
Binary file modified tools/sdk/lib/liblwip2-1460.a
Binary file not shown.
Binary file modified tools/sdk/lib/liblwip2-536-feat.a
Binary file not shown.
Binary file modified tools/sdk/lib/liblwip2-536.a
Binary file not shown.
Binary file modified tools/sdk/lib/liblwip6-1460-feat.a
Binary file not shown.
Binary file modified tools/sdk/lib/liblwip6-536-feat.a
Binary file not shown.
2 changes: 1 addition & 1 deletion tools/sdk/lwip2/include/lwip-git-hash.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion tools/sdk/lwip2/include/lwip/priv/tcp_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS];
#if TCP_DEBUG_PCB_LISTS
#define TCP_REG(pcbs, npcb) do {\
struct tcp_pcb *tcp_tmp_pcb; \
LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %"U16_F"\n", (void *)(npcb), (npcb)->local_port)); \
LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %" U16_F "\n", (void *)(npcb), (npcb)->local_port)); \
for (tcp_tmp_pcb = *(pcbs); \
tcp_tmp_pcb != NULL; \
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
Expand Down
14 changes: 10 additions & 4 deletions tools/sdk/lwip2/include/lwipopts.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

/**
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand All @@ -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;

/*
--------------------------------------------------
Expand All @@ -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);

/*
--------------------------------------------------
Expand Down