From 0aa1ba251f325c79f4b0dc1662c49d5c1c56d2a2 Mon Sep 17 00:00:00 2001 From: agessaman Date: Wed, 11 Nov 2026 17:15:32 -0800 Subject: [PATCH] fix(webconfig): rebind port 80 right after a stop A closed HTTP connection holds port 80 in TIME_WAIT for 2*MSL, so the next listen fails with ERR_USE. Set SOF_REUSEADDR on the new pcb before tcp_bind, and only for port 80, via a linker wrap. --- platformio.ini | 2 ++ src/helpers/ESP32TcpBindReuse.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/helpers/ESP32TcpBindReuse.cpp diff --git a/platformio.ini b/platformio.ini index ea86a1f73d..197500a2dc 100644 --- a/platformio.ini +++ b/platformio.ini @@ -75,6 +75,8 @@ build_flags = ${arduino_base.build_flags} -Wl,--wrap=esp_transport_ws_init ; Run dns_gethostbyname on the lwIP thread; see src/helpers/ESP32DnsThreadFix.cpp. -Wl,--wrap=dns_gethostbyname + ; Rebind port 80 during TIME_WAIT; see src/helpers/ESP32TcpBindReuse.cpp. + -Wl,--wrap=tcp_bind ; -D ESP32_CPU_FREQ=80 ; change it to your need build_src_filter = ${arduino_base.build_src_filter} + ; empty TU unless WITH_MQTT_BRIDGE diff --git a/src/helpers/ESP32TcpBindReuse.cpp b/src/helpers/ESP32TcpBindReuse.cpp new file mode 100644 index 0000000000..e61571b218 --- /dev/null +++ b/src/helpers/ESP32TcpBindReuse.cpp @@ -0,0 +1,29 @@ +// Lets a new port-80 listener bind while an old HTTP connection is still in TIME_WAIT. + +#ifdef ESP_PLATFORM + +#include +#include +#include + +// Arduino 2.0.17 names the switch SO_REUSE; later cores name it LWIP_SO_REUSE. +#ifndef LWIP_SO_REUSE +#ifdef SO_REUSE +#define LWIP_SO_REUSE SO_REUSE +#else +#define LWIP_SO_REUSE 0 +#endif +#endif + +extern "C" err_t __real_tcp_bind(struct tcp_pcb* pcb, const ip_addr_t* ipaddr, u16_t port); + +extern "C" err_t __wrap_tcp_bind(struct tcp_pcb* pcb, const ip_addr_t* ipaddr, u16_t port) { +#if LWIP_SO_REUSE + if (pcb != NULL && port == 80) { + ip_set_option(pcb, SOF_REUSEADDR); + } +#endif + return __real_tcp_bind(pcb, ipaddr, port); +} + +#endif // ESP_PLATFORM