[socket] Return SocketCounts dataclass from get_socket_counts()

Replace the unwieldy 6-tuple with a frozen dataclass for clarity
and named attribute access at call sites.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
J. Nick Koston
2026-02-21 20:03:08 -06:00
parent 623bbc0dbe
commit d5efbfde5c
3 changed files with 38 additions and 34 deletions

View File

@@ -1265,15 +1265,8 @@ def _configure_lwip_max_sockets(conf: dict) -> None:
# CONFIG_LWIP_MAX_SOCKETS is a single VFS socket pool shared by all socket
# types (TCP clients, TCP listeners, and UDP). Include all three counts.
(
tcp_sockets,
udp_sockets,
tcp_listen,
tcp_details,
udp_details,
tcp_listen_details,
) = get_socket_counts()
total_sockets = tcp_sockets + udp_sockets + tcp_listen
sc = get_socket_counts()
total_sockets = sc.tcp + sc.udp + sc.tcp_listen
# User specified their own value - respect it but warn if insufficient
if user_max_sockets is not None:
@@ -1294,9 +1287,9 @@ def _configure_lwip_max_sockets(conf: dict) -> None:
"at least %d.",
user_sockets_int,
total_sockets,
tcp_sockets,
udp_sockets,
tcp_listen,
sc.tcp,
sc.udp,
sc.tcp_listen,
total_sockets,
)
# User's value already added via sdkconfig_options processing
@@ -1314,12 +1307,12 @@ def _configure_lwip_max_sockets(conf: dict) -> None:
"(TCP=%d [%s], UDP=%d [%s], TCP_LISTEN=%d [%s])",
max_sockets,
sock_min,
tcp_sockets,
tcp_details,
udp_sockets,
udp_details,
tcp_listen,
tcp_listen_details,
sc.tcp,
sc.tcp_details,
sc.udp,
sc.udp_details,
sc.tcp_listen,
sc.tcp_listen_details,
)
add_idf_sdkconfig_option("CONFIG_LWIP_MAX_SOCKETS", max_sockets)

View File

@@ -322,15 +322,13 @@ def _configure_lwip(config: dict) -> None:
get_socket_counts,
)
raw_tcp, raw_udp, raw_tcp_listen, tcp_details, udp_details, tcp_listen_details = (
get_socket_counts()
)
sc = get_socket_counts()
# Apply platform minimums — ensure headroom for ESPHome's needs
tcp_sockets = max(MIN_TCP_SOCKETS, raw_tcp)
udp_sockets = max(MIN_UDP_SOCKETS, raw_udp)
tcp_sockets = max(MIN_TCP_SOCKETS, sc.tcp)
udp_sockets = max(MIN_UDP_SOCKETS, sc.udp)
# Listening sockets — registered by components (api, ota, web_server_base, etc.)
# Not all components register yet, so ensure a minimum for baseline operation.
listening_tcp = max(MIN_TCP_LISTEN_SOCKETS, raw_tcp_listen)
listening_tcp = max(MIN_TCP_LISTEN_SOCKETS, sc.tcp_listen)
# TCP_SND_BUF: ESPAsyncWebServer allocates malloc(tcp_sndbuf()) per
# response chunk. At 10×MSS=14.6KB (BK default) this causes OOM (#14095).
@@ -399,20 +397,20 @@ def _configure_lwip(config: dict) -> None:
if CORE.is_bk72xx:
lwip_opts.append("PBUF_POOL_SIZE=10")
tcp_min = " (min)" if tcp_sockets > raw_tcp else ""
udp_min = " (min)" if udp_sockets > raw_udp else ""
listen_min = " (min)" if listening_tcp > raw_tcp_listen else ""
tcp_min = " (min)" if tcp_sockets > sc.tcp else ""
udp_min = " (min)" if udp_sockets > sc.udp else ""
listen_min = " (min)" if listening_tcp > sc.tcp_listen else ""
_LOGGER.info(
"Configuring lwIP: TCP=%d%s [%s], UDP=%d%s [%s], TCP_LISTEN=%d%s [%s]",
tcp_sockets,
tcp_min,
tcp_details,
sc.tcp_details,
udp_sockets,
udp_min,
udp_details,
sc.udp_details,
listening_tcp,
listen_min,
tcp_listen_details,
sc.tcp_listen_details,
)
cg.add_platformio_option("custom_options.lwip", lwip_opts)

View File

@@ -1,4 +1,5 @@
from collections.abc import Callable, MutableMapping
from dataclasses import dataclass
from enum import StrEnum
import logging
@@ -77,10 +78,20 @@ def _format_consumers(consumers: dict[str, int]) -> str:
return ", ".join(f"{name}={count}" for name, count in sorted(consumers.items()))
def get_socket_counts() -> tuple[int, int, int, str, str, str]:
"""Return socket counts and component details for platform configuration.
@dataclass(frozen=True)
class SocketCounts:
"""Socket counts and component details for platform configuration."""
Returns (tcp, udp, tcp_listen, tcp_details, udp_details, tcp_listen_details).
tcp: int
udp: int
tcp_listen: int
tcp_details: str
udp_details: str
tcp_listen_details: str
def get_socket_counts() -> SocketCounts:
"""Return socket counts and component details for platform configuration.
Platforms call this during code generation to configure lwIP socket limits.
All components will have registered their needs by then.
@@ -106,7 +117,9 @@ def get_socket_counts() -> tuple[int, int, int, str, str, str]:
tcp_listen,
tcp_listen_details,
)
return tcp, udp, tcp_listen, tcp_details, udp_details, tcp_listen_details
return SocketCounts(
tcp, udp, tcp_listen, tcp_details, udp_details, tcp_listen_details
)
def require_wake_loop_threadsafe() -> None: