Commit Graph
23587 Commits
Author SHA1 Message Date
J. Nick Koston 9151383f7d Merge remote-tracking branch 'upstream/socket-lwip-bugfix' into integration 2026-03-01 08:17:27 -10:00
J. Nick Koston 3246662a09 [socket] Remove invalid tcp_err on listen PCB
tcp_listen_with_backlog() converts the full tcp_pcb to a smaller
tcp_pcb_listen struct that lacks the errf field. Calling tcp_err()
on a listen PCB writes past the struct boundary, causing memory
corruption and crashes (confirmed on RP2040).

LWIP itself asserts pcb->state != LISTEN in tcp_err().
2026-03-01 08:16:23 -10:00
J. Nick Koston 6564c46c79 Merge branch 'socket-lwip-bugfix' into integration 2026-03-01 07:51:40 -10:00
J. Nick Koston d1b1090f93 [socket] Fix send() const-correctness to match POSIX
send() takes void* but should be const void* to match POSIX and
the class's own write()/sendto() signatures.
2026-03-01 07:46:32 -10:00
J. Nick Koston fe89d7c701 [socket] Free rx_buf_ in LWIPRawImpl destructor
The destructor relies solely on tcp_abort() for cleanup, but LWIP
considers ownership of pbufs transferred once the recv callback
accepts them. If rx_buf_ is non-null when the socket is destroyed,
those pbufs are leaked. Free them explicitly before the base class
destructor calls tcp_abort().
2026-03-01 07:41:38 -10:00
J. Nick Koston cce95ff58c [socket] Fix pre-existing bugs in LWIP raw TCP socket
Fix two pre-existing bugs found during review of #14398:

1. bind() returns 0 on nullptr name instead of -1, inconsistent with
   POSIX bind() semantics and can mask invalid calls.

2. listen() doesn't re-register tcp_err after tcp_listen_with_backlog
   reallocates the PCB. The error callback was set during init() on
   the original PCB which is now freed, leaving the new listen PCB
   without an error handler.
2026-03-01 07:22:27 -10:00
J. Nick Koston 5d9c3a0e71 Fix clang-tidy: use make_unique and fix include order
- Replace std::unique_ptr{new ...} with make_unique
- Fix include order to satisfy clang-format
2026-03-01 00:23:05 -10:00
J. Nick Koston 529c79a8a9 Add NOLINT for redundant socket_ready_fd forward declaration
clang-tidy flags the forward declaration in application.h as redundant
since socket.h (included earlier via esphome.h) already declares it.
The forward declaration is needed here for the friend declaration.
2026-02-28 23:30:35 -10:00
J. Nick Koston 8cedf8f882 Restore comments from original code to minimize diff 2026-02-28 23:03:53 -10:00
J. Nick Koston 164001b50c Revert unnecessary socket_ip_loop_monitored rename
Keep the original function name since all callers already use it for
listening sockets. Only the return type changes to ListenSocket.
2026-02-28 23:00:32 -10:00
J. Nick Koston 7e119b1cbd Fix clang-tidy naming violations in lwip_raw_tcp_impl
- Rename internal_write/internal_output to internal_write_/internal_output_
  (protected methods require trailing underscore)
- Fix getpeername/getsockname parameter name mismatch between .h and .cpp
2026-02-28 22:56:48 -10:00
J. Nick Koston 39bbdbbfce Revert unrelated IRAM_ATTR change that leaked in from stash 2026-02-28 22:47:32 -10:00
J. Nick KostonandJ. Nick Koston 7a2452b3a2 Move LWIP_LOG and inline methods from header to cpp
The CI lint rule disallows ESP_LOG* references in header files.
Move LWIP_LOG macro definition and all methods that use it
(destructors, init(), static callbacks) to the .cpp file.

Co-Authored-By: J. Nick Koston <nick@koston.org>
2026-02-28 22:43:24 -10:00
J. Nick KostonandJ. Nick Koston 807e786fac [socket] Devirtualize socket abstraction layer
Replace the virtual Socket base class with compile-time type aliases.
Since only one socket implementation is active per build (selected via
#ifdef), virtual dispatch was unnecessary overhead.

Each implementation (BSDSocketImpl, LwIPSocketImpl, LWIPRawImpl) is now
a concrete class in its own header with no virtual methods. socket::Socket
and socket::ListenSocket are type aliases to the active implementation.

For LWIP_TCP (ESP8266/RP2040), the listen socket is a separate type
(LWIPRawListenImpl) sharing a non-virtual LWIPRawCommon base with the
connected socket type (LWIPRawImpl). On BSD/LWIP_SOCKETS, both aliases
resolve to the same type.

This eliminates all vtable overhead, virtual destructors, and indirect
call overhead across all platforms.

Co-Authored-By: J. Nick Koston <nick@koston.org>
2026-02-28 22:39:25 -10:00
J. Nick Koston 7b645ef736 Merge branch 'controller-registry-shared-notify' into integration 2026-02-28 21:42:30 -10:00
J. Nick Koston 8e4c54cc38 lint 2026-02-28 21:42:18 -10:00
J. Nick Koston 4799b217a5 Merge remote-tracking branch 'upstream/dev' into integration 2026-02-28 17:31:51 -10:00
J. Nick Koston 68818a535c Merge branch 'controller-registry-shared-notify' into integration 2026-02-28 17:10:46 -10:00
J. Nick Koston b4e0c917eb bot comments 2026-02-28 17:10:36 -10:00
J. Nick Koston 8c45791eeb Merge branch 'controller-registry-shared-notify' into integration 2026-02-28 17:08:39 -10:00
J. Nick Koston 19bbd39e33 [uart] Enable wake-on-RX by default on ESP32 (#14391) 2026-02-28 21:06:46 -06:00
J. Nick Koston 8f24e12bf9 fix merge 2026-02-28 16:50:50 -10:00
J. Nick Koston f3377e22b8 fix mege 2026-02-28 16:47:54 -10:00
J. Nick Koston c2a6295b37 Merge remote-tracking branch 'upstream/remove-virtual-destructor-proto-message' into integration 2026-02-28 16:40:48 -10:00
J. Nick Koston 29b6017ea3 Merge remote-tracking branch 'upstream/esp8266-wake-loop-any-context' into integration 2026-02-28 16:40:43 -10:00
J. Nick Koston 28178b8c1c fixes 2026-02-28 16:39:13 -10:00
J. Nick Koston 04010664ce [core] Add ESP8266 support to wake_loop_any_context()
Wire Application::wake_loop_any_context() to socket::socket_wake()
on ESP8266. This allows any component calling wake_loop_any_context()
from an ISR or callback to immediately wake the main loop from
esp_delay() sleep, instead of waiting up to 16ms for the timeout.

Changes:
- Add IRAM_ATTR to socket_wake() so it's safe to call from ISR context
- Add ESP8266 wake_loop_any_context() backed by socket::socket_wake()
- Extend enable_loop_soon_any_context() to wake the loop on ESP8266
2026-02-28 16:35:44 -10:00
J. Nick Koston a632a7e644 [core] Deduplicate ControllerRegistry notify dispatch loop
Each notify_*_update method had an identical loop that only differed
in the vtable offset for the virtual call. Extract the shared loop
into a single noinline notify() function and have each wrapper pass
a small trampoline lambda that dispatches to the correct Controller
virtual method.

Before: 8 copies of the loop at ~56 bytes each = ~448 bytes
After:  1 shared loop (56 B) + 8 wrappers (16 B) + 8 trampolines (8 B) = ~248 bytes

Saves ~200 bytes of flash.
2026-02-28 16:35:27 -10:00
J. Nick Koston fde32555dc Restrict wake_loop_any_context to ESP32 only
LibreTiny lacks IRAM_ATTR support needed for ISR-safe paths,
and BK72xx doesn't support the mrs ipsr instruction in Thumb mode.
The existing fast select functionality on LibreTiny is unaffected.
2026-02-28 16:32:05 -10:00
J. Nick Koston f3c175ab39 [api] Remove virtual destructor from ProtoMessage
API protobuf messages are never deleted through base class pointers —
they are always stack-allocated and passed by reference. The virtual
destructor occupies 2 vtable slots (complete + deleting destructor)
on 32-bit platforms using the Itanium ABI, costing 8 bytes per vtable.

With 122 message classes, removing the virtual destructor saves
~976 bytes of flash. Each vtable shrinks from 24 bytes to 16 bytes.
2026-02-28 16:29:19 -10:00
J. Nick Koston 50dd56c59d Merge remote-tracking branch 'origin/esp8266-wake-loop-any-context' into integration 2026-02-28 15:46:49 -10:00
J. Nick Koston e36b0d09a7 [core] Add ESP8266 support to wake_loop_any_context()
Wire Application::wake_loop_any_context() to socket::socket_wake()
on ESP8266. This allows any component calling wake_loop_any_context()
from an ISR or callback to immediately wake the main loop from
esp_delay() sleep, instead of waiting up to 16ms for the timeout.

Changes:
- Add IRAM_ATTR to socket_wake() so it's safe to call from ISR context
- Add ESP8266 wake_loop_any_context() backed by socket::socket_wake()
- Extend enable_loop_soon_any_context() to wake the loop on ESP8266
2026-02-28 15:46:38 -10:00
J. Nick Koston 6e4e9ddeb5 Merge remote-tracking branch 'origin/esp8266-wake-loop-any-context' into integration 2026-02-28 15:41:28 -10:00
J. Nick Koston e04568cb83 [core] Add ESP8266 support to wake_loop_any_context()
Wire Application::wake_loop_any_context() to socket::socket_wake()
on ESP8266. This allows any component calling wake_loop_any_context()
from an ISR or callback to immediately wake the main loop from
esp_delay() sleep, instead of waiting up to 16ms for the timeout.

Changes:
- Add IRAM_ATTR to socket_wake() so it's safe to call from ISR context
- Add ESP8266 wake_loop_any_context() backed by socket::socket_wake()
- Extend enable_loop_soon_any_context() to wake the loop on ESP8266
2026-02-28 15:41:12 -10:00
J. Nick Koston 1034b559de Merge remote-tracking branch 'origin/uart-isr-wake-on-rx-default' into integration 2026-02-28 15:36:20 -10:00
J. Nick Koston bf180724a8 Merge remote-tracking branch 'origin/esp8266-wake-loop-any-context' into integration 2026-02-28 15:36:17 -10:00
J. Nick Koston fcb21998f8 Guard portYIELD_FROM_ISR with USE_ESP32
LibreTiny's FreeRTOS port does not provide portYIELD_FROM_ISR.
On ARM Cortex-M, FreeRTOS internally sets the PendSV bit when
vTaskNotifyGiveFromISR wakes a higher-priority task, so the
context switch happens automatically when the ISR returns.
2026-02-28 15:35:48 -10:00
J. Nick Koston bbb870594e [core] Add ESP8266 support to wake_loop_any_context()
Wire Application::wake_loop_any_context() to socket::socket_wake()
on ESP8266. This allows any component calling wake_loop_any_context()
from an ISR or callback to immediately wake the main loop from
esp_delay() sleep, instead of waiting up to 16ms for the timeout.

Changes:
- Add IRAM_ATTR to socket_wake() so it's safe to call from ISR context
- Add ESP8266 wake_loop_any_context() backed by socket::socket_wake()
- Extend enable_loop_soon_any_context() to wake the loop on ESP8266
2026-02-28 15:25:23 -10:00
J. Nick Koston bf7982a7b9 Merge remote-tracking branch 'upstream/isr-wake-enable-loop-soon' into integration 2026-02-28 15:14:11 -10:00
J. Nick Koston d570137d2b [uart] Enable wake-on-RX by default on ESP32
Now that the ISR callback mechanism (from #14382) costs essentially
zero — just a function pointer registration, no task or queue — enable
wake-on-RX by default for all ESP32 UART instances.

This reduces RX buffer overflow risk by waking the main loop
immediately when data arrives instead of waiting for the ~16ms
select timeout.

Remove the opt-in request_wake_loop_on_rx() API since all ESP32
UART instances now get this automatically.
2026-02-28 15:10:35 -10:00
J. Nick Koston 54126fef36 Only set USE_LWIP_FAST_SELECT when select support is available
The fast select code paths and wake_loop_any_context() require
USE_SOCKET_SELECT_SUPPORT. Gate USE_LWIP_FAST_SELECT on not using
lwip_tcp implementation which does not provide select() support.
2026-02-28 15:08:30 -10:00
J. Nick Koston 9f7508e50b Add IRAM_ATTR to esphome_get_ipsr for future-proofing
Currently a no-op on LibreTiny but ensures the function stays
in IRAM if the platform later defines IRAM_ATTR.
2026-02-28 15:01:52 -10:00
J. Nick Koston fb998468b5 Fix comment about function calls and initialize ipsr
- Update ISR safety comment: point 3 now reflects that
  wake_loop_any_context() is called (ISR-safe)
- Initialize ipsr = 0 as safety net before inline asm
2026-02-28 15:01:37 -10:00
J. Nick Koston 3ff8cde1cf Fix comment about function calls and initialize ipsr
- Update ISR safety comment: point 3 now reflects that
  wake_loop_any_context() is called (ISR-safe)
- Initialize ipsr = 0 as safety net before inline asm
2026-02-28 15:01:12 -10:00
J. Nick Koston 9b8fe6230c Merge remote-tracking branch 'upstream/isr-wake-enable-loop-soon' into integration 2026-02-28 14:56:19 -10:00
J. Nick Koston bdeba1710e Address review feedback for ISR wake support
- Replace __get_IPSR() with inline asm to avoid CMSIS header dependency
  on LibreTiny chip families that may not declare it (e.g. beken-72xx)
- Pass local variable to wake_from_isr and call portYIELD_FROM_ISR for
  immediate context switch instead of passing NULL
- Update comment in component.cpp to mention both ESP32 and LibreTiny
  platform-specific context detection
- Switch USE_LWIP_FAST_SELECT from cg.add_define to cg.add_build_flag
  so it is visible in .c translation units, aligning guards across all
  source files
2026-02-28 14:54:05 -10:00
J. Nick Koston 6017ce2c74 Merge branch 'isr-wake-enable-loop-soon' into integration 2026-02-28 14:35:03 -10:00
J. Nick Koston ec8d2b5f0d Merge remote-tracking branch 'upstream/dev' into isr-wake-enable-loop-soon 2026-02-28 14:29:15 -10:00
J. Nick KostonandCopilot 3f97b3b706 [core] Extract set_status_flag_ helper to deduplicate status_set methods (#14384)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-28 14:27:06 -10:00
J. Nick Koston 82e620bcf5 [ld2450] Single-pass zone target counting (#14387) 2026-02-28 14:26:55 -10:00