3#if defined(USE_SOCKET_IMPL_LWIP_TCP) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) || defined(USE_SOCKET_IMPL_BSD_SOCKETS)
11#if !defined(USE_HOST) && !defined(USE_ZEPHYR)
22#if defined(IPV4_RESOLVE_ATOMIC_STATE)
24 return this->state_word_.compare_exchange_strong(expected,
STATE_IDLE);
35#if defined(IPV4_RESOLVE_VOLATILE_EPOCH)
38 this->epoch_ = this->epoch_ + 1;
43#elif defined(IPV4_RESOLVE_ATOMIC_STATE)
47 if (this->state_word_.compare_exchange_strong(expected,
STATE_IDLE)) {
68 in->sin_family = AF_INET;
69 in->sin_port = htons(port);
70 in->sin_addr.s_addr = this->addr_();
74#if !defined(USE_HOST) && !defined(USE_ZEPHYR)
75#if defined(IPV4_RESOLVE_VOLATILE_EPOCH)
76bool Ipv4Resolve::drop_stale_(
uint32_t expected) {
77 if (this->epoch_ == expected) {
86void Ipv4Resolve::dns_found(
const char *name,
const ip_addr_t *addr,
void *arg) {
87 auto *self =
static_cast<Ipv4Resolve *
>(arg);
88#if defined(IPV4_RESOLVE_VOLATILE_EPOCH)
89 const uint32_t expected = self->pending_epoch_;
90 if (self->drop_stale_(expected)) {
94 if (addr !=
nullptr && IP_IS_V4(addr)) {
95#if defined(IPV4_RESOLVE_ATOMIC_STATE)
98 if (!self->state_word_.compare_exchange_strong(expected,
STATE_PUBLISHING)) {
101 self->set_addr_(ip4_addr_get_u32(ip_2_ip4(addr)));
104 if (!self->state_word_.compare_exchange_strong(expected,
STATE_RESOLVED)) {
107#elif defined(IPV4_RESOLVE_VOLATILE_EPOCH)
108 self->addr_word_ = ip4_addr_get_u32(ip_2_ip4(addr));
110 if (self->drop_stale_(expected)) {
118 self->set_addr_(ip4_addr_get_u32(ip_2_ip4(addr)));
122 ESP_LOGW(self->tag_ !=
nullptr ? self->tag_ : TAG,
"DNS failed for %s", name);
123#if defined(IPV4_RESOLVE_ATOMIC_STATE)
125 self->state_word_.compare_exchange_strong(expected,
STATE_FAILED);
126#elif defined(IPV4_RESOLVE_VOLATILE_EPOCH)
128 if (self->drop_stale_(expected)) {
142 const uint8_t
state = this->state_();
149 if (
set_sockaddr(
reinterpret_cast<struct
sockaddr *
>(&literal),
sizeof(literal), host, port) != 0) {
151 auto *in =
reinterpret_cast<sockaddr_in *
>(&literal);
152 this->set_addr_(in->sin_addr.s_addr);
157 ESP_LOGW(tag,
"Not an IPv4 address: %s", host);
160#if !defined(USE_HOST) && !defined(USE_ZEPHYR)
165#if defined(IPV4_RESOLVE_VOLATILE_EPOCH)
166 this->pending_epoch_ = this->epoch_;
169 err = dns_gethostbyname_addrtype(host, &cached, &Ipv4Resolve::dns_found,
this, LWIP_DNS_ADDRTYPE_IPV4);
174 if (err == ERR_OK && IP_IS_V4(&cached)) {
175 this->set_addr_(ip4_addr_get_u32(ip_2_ip4(&cached)));
183 struct addrinfo hints {};
184 hints.ai_family = AF_INET;
185 hints.ai_socktype = SOCK_STREAM;
186 struct addrinfo *res =
nullptr;
187 if (getaddrinfo(host,
nullptr, &hints, &res) == 0 && res !=
nullptr) {
188 auto *in =
reinterpret_cast<struct
sockaddr_in *
>(res->ai_addr);
189 if (res->ai_family == AF_INET) {
190 this->set_addr_(in->sin_addr.s_addr);
200 ESP_LOGW(tag,
"Could not resolve %s", host);
Helper class to lock the lwIP TCPIP core when making lwIP API calls from non-TCPIP threads.
void start(const char *host, uint16_t port, const char *tag)
Resolve host; tag names the failure log.
bool consume_failure()
Drop a failed lookup so the next start() tries again.
static constexpr uint8_t STATE_RESOLVED
static constexpr uint8_t STATE_RESOLVING
socklen_t to_sockaddr(struct sockaddr *dest, socklen_t destlen, uint16_t port) const
Write the stored address into dest. Returns 0 until ready() is true.
static constexpr uint8_t STATE_IDLE
static constexpr uint8_t STATE_FAILED
static constexpr uint8_t STATE_PUBLISHING
void forget()
Drop the stored address so the next start() resolves again.
socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const char *ip_address, uint16_t port)
Set a sockaddr to the specified address and port for the IP version used by socket_ip().
ESPHOME_LOG_TAG(TAG, "socket")