mirror of
https://github.com/esphome/esphome.git
synced 2026-09-11 15:27:33 +00:00
Adopt the shared connect poll in async_tcp and name the refused implementation
This commit is contained in:
@@ -480,11 +480,10 @@ def _validate_outgoing_socket_implementation(config: ConfigType) -> ConfigType:
|
||||
|
||||
socket_conf = fv.full_config.get().get("socket") or {}
|
||||
if (
|
||||
socket_conf.get(socket.CONF_IMPLEMENTATION)
|
||||
in socket.IMPLEMENTATIONS_WITHOUT_CONNECT
|
||||
):
|
||||
impl := socket_conf.get(socket.CONF_IMPLEMENTATION)
|
||||
) in socket.IMPLEMENTATIONS_WITHOUT_CONNECT:
|
||||
raise cv.Invalid(
|
||||
"outgoing_connection is not supported with the lwip_tcp socket "
|
||||
f"outgoing_connection is not supported with the {impl} socket "
|
||||
"implementation because it cannot make outgoing connections",
|
||||
path=[CONF_OUTGOING_CONNECTION],
|
||||
)
|
||||
|
||||
@@ -97,45 +97,22 @@ void AsyncClient::loop() {
|
||||
return;
|
||||
|
||||
if (connecting_) {
|
||||
// For connecting, we need to check writability, not readability
|
||||
// The Application's select() only monitors read FDs, so we do our own check here
|
||||
// For ESP platforms lwip_select() might be faster, but this code isn't used
|
||||
// on those platforms anyway. If it was, we'd fix the Application select()
|
||||
// to report writability instead of doing it this way.
|
||||
int fd = socket_->get_fd();
|
||||
if (fd < 0) {
|
||||
ESP_LOGW(TAG, "Invalid socket fd");
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
fd_set writefds;
|
||||
FD_ZERO(&writefds);
|
||||
FD_SET(fd, &writefds);
|
||||
|
||||
struct timeval tv = {0, 0};
|
||||
int ret = select(fd + 1, nullptr, &writefds, nullptr, &tv);
|
||||
|
||||
if (ret > 0 && FD_ISSET(fd, &writefds)) {
|
||||
int error = 0;
|
||||
socklen_t len = sizeof(error);
|
||||
if (socket_->getsockopt(SOL_SOCKET, SO_ERROR, &error, &len) == 0 && error == 0) {
|
||||
int err = 0;
|
||||
switch (socket::poll_connect(*socket_, err)) {
|
||||
case socket::ConnectPollResult::CONNECT_POLL_PENDING:
|
||||
break;
|
||||
case socket::ConnectPollResult::CONNECT_POLL_CONNECTED:
|
||||
connecting_ = false;
|
||||
connected_ = true;
|
||||
if (connect_cb_)
|
||||
connect_cb_(connect_arg_, this);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Connection failed: %d", error);
|
||||
break;
|
||||
case socket::ConnectPollResult::CONNECT_POLL_ERROR:
|
||||
ESP_LOGW(TAG, "Connection failed: %d", err);
|
||||
close();
|
||||
if (error_cb_)
|
||||
error_cb_(error_arg_, this, error);
|
||||
}
|
||||
} else if (ret < 0) {
|
||||
const int err = errno;
|
||||
ESP_LOGE(TAG, "Select error: %d", err);
|
||||
close();
|
||||
if (error_cb_)
|
||||
error_cb_(error_arg_, this, err);
|
||||
error_cb_(error_arg_, this, err);
|
||||
break;
|
||||
}
|
||||
} else if (connected_) {
|
||||
// For connected sockets, use the Application's select() results
|
||||
|
||||
@@ -15,10 +15,10 @@ CODEOWNERS = ["@esphome/core"]
|
||||
|
||||
CONF_IMPLEMENTATION = "implementation"
|
||||
IMPLEMENTATION_LWIP_TCP = "lwip_tcp"
|
||||
# Implementations whose sockets cannot make outgoing connections
|
||||
IMPLEMENTATIONS_WITHOUT_CONNECT = frozenset({IMPLEMENTATION_LWIP_TCP})
|
||||
IMPLEMENTATION_LWIP_SOCKETS = "lwip_sockets"
|
||||
IMPLEMENTATION_BSD_SOCKETS = "bsd_sockets"
|
||||
# Implementations whose sockets cannot make outgoing connections
|
||||
IMPLEMENTATIONS_WITHOUT_CONNECT = frozenset({IMPLEMENTATION_LWIP_TCP})
|
||||
|
||||
# Socket tracking infrastructure
|
||||
# Components register their socket needs and platforms read this to configure appropriately
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import binary_sensor, sensor
|
||||
from esphome.components.const import CONF_HOST
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_BINARY_SENSORS,
|
||||
@@ -14,7 +15,6 @@ AUTO_LOAD = ["socket"]
|
||||
CODEOWNERS = ["@Links2004"]
|
||||
DEPENDENCIES = ["network"]
|
||||
|
||||
CONF_HOST = "host"
|
||||
CONF_PREFIX = "prefix"
|
||||
|
||||
statsd_component_ns = cg.esphome_ns.namespace("statsd")
|
||||
|
||||
@@ -16,9 +16,9 @@ async def test_api_reboot_timeout(
|
||||
"""Test that the device reboots when no API clients connect within the timeout."""
|
||||
loop = asyncio.get_running_loop()
|
||||
reboot_future = loop.create_future()
|
||||
# The harness port probe counts as an unauthenticated client, so the
|
||||
# reboot may report either form
|
||||
reboot_pattern = re.compile(r"(No clients|none authenticated); rebooting")
|
||||
# The harness port probe always connects without authenticating, so the
|
||||
# reboot deterministically reports the unauthenticated form
|
||||
reboot_pattern = re.compile(r"none authenticated; rebooting")
|
||||
|
||||
def check_output(line: str) -> None:
|
||||
"""Check output for reboot message."""
|
||||
|
||||
Reference in New Issue
Block a user