mirror of
https://github.com/esphome/esphome.git
synced 2026-09-11 15:27:33 +00:00
[socket] Rename UDP socket types so UDPSocket is the full send+recv type
Swap the UDP type naming so the unsuffixed UDPSocket is the full send+recv socket and the send-only variant becomes UDPSendSocket. The previous naming inverted reader expectations (UDPSocket sounded complete but was send-only, UDPRecvSocket sounded limited but was the full one). Public: UDPSocket (was UDPRecvSocket) UDPSendSocket (was UDPSocket) socket_udp (was socket_udp_recv) socket_ip_udp (was socket_ip_udp_recv) socket_udp_loop_monitored (was socket_udp_recv_loop_monitored) socket_ip_udp_loop_monitored (was socket_ip_udp_recv_loop_monitored) socket_udp_send (was socket_udp) socket_ip_udp_send (was socket_ip_udp) Internal: LWIPRawUDPImpl (was LWIPRawUDPRecvImpl) LWIPRawUDPSendImpl (was LWIPRawUDPImpl) No consumers exist yet, so this is a clean rename with no migration.
This commit is contained in:
@@ -796,7 +796,7 @@ std::unique_ptr<Socket> socket_loop_monitored(int domain, int type, int protocol
|
||||
|
||||
std::unique_ptr<ListenSocket> socket_listen(int domain, int type, int protocol) {
|
||||
if (type != SOCK_STREAM) {
|
||||
ESP_LOGE(TAG, "Use socket_udp_recv() for UDP sockets on this platform");
|
||||
ESP_LOGE(TAG, "Use socket_udp() for UDP sockets on this platform");
|
||||
errno = EPROTOTYPE;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ namespace esphome::socket {
|
||||
|
||||
static const char *const TAG = "socket.lwip_udp";
|
||||
|
||||
// ---- LWIPRawUDPImpl (send-only) methods ----
|
||||
// ---- LWIPRawUDPSendImpl (send-only) methods ----
|
||||
|
||||
LWIPRawUDPImpl::LWIPRawUDPImpl(sa_family_t family) : family_(family) {
|
||||
LWIPRawUDPSendImpl::LWIPRawUDPSendImpl(sa_family_t family) : family_(family) {
|
||||
LWIP_LOCK();
|
||||
#if LWIP_IPV6
|
||||
this->pcb_ = udp_new_ip_type(family == AF_INET6 ? IPADDR_TYPE_ANY : IPADDR_TYPE_V4);
|
||||
@@ -35,9 +35,9 @@ LWIPRawUDPImpl::LWIPRawUDPImpl(sa_family_t family) : family_(family) {
|
||||
#endif
|
||||
}
|
||||
|
||||
LWIPRawUDPImpl::~LWIPRawUDPImpl() {
|
||||
LWIPRawUDPSendImpl::~LWIPRawUDPSendImpl() {
|
||||
// Early return avoids acquiring the lwip lock when pcb_ is already null
|
||||
// (e.g., after LWIPRawUDPRecvImpl::close() already cleaned up).
|
||||
// (e.g., after LWIPRawUDPImpl::close() already cleaned up).
|
||||
if (this->pcb_ == nullptr)
|
||||
return;
|
||||
LWIP_LOCK();
|
||||
@@ -45,7 +45,7 @@ LWIPRawUDPImpl::~LWIPRawUDPImpl() {
|
||||
this->pcb_ = nullptr;
|
||||
}
|
||||
|
||||
int LWIPRawUDPImpl::bind_internal_locked_(const struct sockaddr *name, socklen_t addrlen) {
|
||||
int LWIPRawUDPSendImpl::bind_internal_locked_(const struct sockaddr *name, socklen_t addrlen) {
|
||||
// Caller must hold LWIP_LOCK
|
||||
if (this->pcb_ == nullptr) {
|
||||
errno = EBADF;
|
||||
@@ -72,17 +72,17 @@ int LWIPRawUDPImpl::bind_internal_locked_(const struct sockaddr *name, socklen_t
|
||||
return lwip_bind_err(udp_bind(this->pcb_, &ip, port));
|
||||
}
|
||||
|
||||
int LWIPRawUDPImpl::bind(const struct sockaddr *name, socklen_t addrlen) {
|
||||
int LWIPRawUDPSendImpl::bind(const struct sockaddr *name, socklen_t addrlen) {
|
||||
LWIP_LOCK();
|
||||
return this->bind_internal_locked_(name, addrlen);
|
||||
}
|
||||
|
||||
int LWIPRawUDPImpl::close() {
|
||||
int LWIPRawUDPSendImpl::close() {
|
||||
LWIP_LOCK();
|
||||
return this->close_internal_locked_();
|
||||
}
|
||||
|
||||
int LWIPRawUDPImpl::close_internal_locked_() {
|
||||
int LWIPRawUDPSendImpl::close_internal_locked_() {
|
||||
// Caller must hold LWIP_LOCK
|
||||
if (this->pcb_ == nullptr) {
|
||||
errno = EBADF;
|
||||
@@ -93,13 +93,13 @@ int LWIPRawUDPImpl::close_internal_locked_() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LWIPRawUDPImpl::ip2sockaddr_(const ip_addr_t *ip, uint16_t port, struct sockaddr *name, socklen_t *addrlen) {
|
||||
int LWIPRawUDPSendImpl::ip2sockaddr_(const ip_addr_t *ip, uint16_t port, struct sockaddr *name, socklen_t *addrlen) {
|
||||
// UDP recv callback provides port in host byte order
|
||||
return lwip_ip_to_sockaddr(this->family_, ip, port, name, addrlen);
|
||||
}
|
||||
|
||||
ssize_t LWIPRawUDPImpl::sendto(const void *buf, size_t len, int flags, const struct sockaddr *dest_addr,
|
||||
socklen_t addrlen) {
|
||||
ssize_t LWIPRawUDPSendImpl::sendto(const void *buf, size_t len, int flags, const struct sockaddr *dest_addr,
|
||||
socklen_t addrlen) {
|
||||
(void) flags; // Flags (MSG_DONTWAIT, etc.) are ignored; raw lwip is always non-blocking
|
||||
LWIP_LOCK();
|
||||
if (this->pcb_ == nullptr) {
|
||||
@@ -142,7 +142,7 @@ ssize_t LWIPRawUDPImpl::sendto(const void *buf, size_t len, int flags, const str
|
||||
return (ssize_t) len;
|
||||
}
|
||||
|
||||
int LWIPRawUDPImpl::setsockopt(int level, int optname, const void *optval, socklen_t optlen) {
|
||||
int LWIPRawUDPSendImpl::setsockopt(int level, int optname, const void *optval, socklen_t optlen) {
|
||||
LWIP_LOCK();
|
||||
if (this->pcb_ == nullptr) {
|
||||
errno = EBADF;
|
||||
@@ -204,7 +204,7 @@ int LWIPRawUDPImpl::setsockopt(int level, int optname, const void *optval, sockl
|
||||
return -1;
|
||||
}
|
||||
|
||||
int LWIPRawUDPImpl::getsockopt(int level, int optname, void *optval, socklen_t *optlen) {
|
||||
int LWIPRawUDPSendImpl::getsockopt(int level, int optname, void *optval, socklen_t *optlen) {
|
||||
LWIP_LOCK();
|
||||
if (this->pcb_ == nullptr) {
|
||||
errno = EBADF;
|
||||
@@ -223,7 +223,7 @@ int LWIPRawUDPImpl::getsockopt(int level, int optname, void *optval, socklen_t *
|
||||
return -1;
|
||||
}
|
||||
|
||||
int LWIPRawUDPImpl::setblocking(bool blocking) {
|
||||
int LWIPRawUDPSendImpl::setblocking(bool blocking) {
|
||||
if (blocking) {
|
||||
// blocking operation not supported on raw lwip
|
||||
errno = EINVAL;
|
||||
@@ -232,15 +232,15 @@ int LWIPRawUDPImpl::setblocking(bool blocking) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ---- LWIPRawUDPRecvImpl methods ----
|
||||
// ---- LWIPRawUDPImpl methods ----
|
||||
|
||||
LWIPRawUDPRecvImpl::~LWIPRawUDPRecvImpl() {
|
||||
LWIPRawUDPImpl::~LWIPRawUDPImpl() {
|
||||
// Flush rx queue and unregister callback before base destructor removes pcb
|
||||
if (this->pcb_ != nullptr)
|
||||
this->close();
|
||||
}
|
||||
|
||||
int LWIPRawUDPRecvImpl::close() {
|
||||
int LWIPRawUDPImpl::close() {
|
||||
LWIP_LOCK();
|
||||
// Unregister recv callback before removing pcb
|
||||
if (this->pcb_ != nullptr) {
|
||||
@@ -260,19 +260,19 @@ int LWIPRawUDPRecvImpl::close() {
|
||||
return this->close_internal_locked_();
|
||||
}
|
||||
|
||||
int LWIPRawUDPRecvImpl::bind(const struct sockaddr *name, socklen_t addrlen) {
|
||||
int LWIPRawUDPImpl::bind(const struct sockaddr *name, socklen_t addrlen) {
|
||||
LWIP_LOCK();
|
||||
int ret = this->bind_internal_locked_(name, addrlen);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
// Register recv callback now that we're bound and ready to receive
|
||||
udp_recv(this->pcb_, LWIPRawUDPRecvImpl::s_recv_fn, this);
|
||||
udp_recv(this->pcb_, LWIPRawUDPImpl::s_recv_fn, this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t LWIPRawUDPRecvImpl::read(void *buf, size_t len) { return this->recvfrom(buf, len, nullptr, nullptr); }
|
||||
ssize_t LWIPRawUDPImpl::read(void *buf, size_t len) { return this->recvfrom(buf, len, nullptr, nullptr); }
|
||||
|
||||
ssize_t LWIPRawUDPRecvImpl::recvfrom(void *buf, size_t len, struct sockaddr *src_addr, socklen_t *addrlen) {
|
||||
ssize_t LWIPRawUDPImpl::recvfrom(void *buf, size_t len, struct sockaddr *src_addr, socklen_t *addrlen) {
|
||||
if (buf == nullptr && len > 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
@@ -313,15 +313,15 @@ ssize_t LWIPRawUDPRecvImpl::recvfrom(void *buf, size_t len, struct sockaddr *src
|
||||
return (ssize_t) copy_len;
|
||||
}
|
||||
|
||||
void LWIPRawUDPRecvImpl::s_recv_fn(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) {
|
||||
auto *self = reinterpret_cast<LWIPRawUDPRecvImpl *>(arg);
|
||||
void LWIPRawUDPImpl::s_recv_fn(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) {
|
||||
auto *self = reinterpret_cast<LWIPRawUDPImpl *>(arg);
|
||||
self->recv_fn_(p, addr, port);
|
||||
}
|
||||
|
||||
// LWIP CALLBACK — runs from IRQ context on RP2040 (low-priority user IRQ).
|
||||
// No heap allocation allowed — malloc is not IRQ-safe (see #14687).
|
||||
// No LWIP_LOCK() needed — lwip core already holds the async_context lock.
|
||||
void LWIPRawUDPRecvImpl::recv_fn_(struct pbuf *p, const ip_addr_t *addr, u16_t port) {
|
||||
void LWIPRawUDPImpl::recv_fn_(struct pbuf *p, const ip_addr_t *addr, u16_t port) {
|
||||
if (p == nullptr)
|
||||
return;
|
||||
|
||||
@@ -347,6 +347,16 @@ void LWIPRawUDPRecvImpl::recv_fn_(struct pbuf *p, const ip_addr_t *addr, u16_t p
|
||||
|
||||
// ---- UDP Factory functions ----
|
||||
|
||||
std::unique_ptr<UDPSendSocket> socket_udp_send(int domain, int protocol) {
|
||||
(void) protocol; // Raw lwip UDP ignores protocol; kept for API compatibility
|
||||
auto sock = make_unique<LWIPRawUDPSendImpl>((sa_family_t) domain);
|
||||
if (!sock->is_valid()) {
|
||||
errno = ENOMEM;
|
||||
return nullptr;
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
|
||||
std::unique_ptr<UDPSocket> socket_udp(int domain, int protocol) {
|
||||
(void) protocol; // Raw lwip UDP ignores protocol; kept for API compatibility
|
||||
auto sock = make_unique<LWIPRawUDPImpl>((sa_family_t) domain);
|
||||
@@ -357,19 +367,9 @@ std::unique_ptr<UDPSocket> socket_udp(int domain, int protocol) {
|
||||
return sock;
|
||||
}
|
||||
|
||||
std::unique_ptr<UDPRecvSocket> socket_udp_recv(int domain, int protocol) {
|
||||
(void) protocol; // Raw lwip UDP ignores protocol; kept for API compatibility
|
||||
auto sock = make_unique<LWIPRawUDPRecvImpl>((sa_family_t) domain);
|
||||
if (!sock->is_valid()) {
|
||||
errno = ENOMEM;
|
||||
return nullptr;
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
|
||||
std::unique_ptr<UDPRecvSocket> socket_udp_recv_loop_monitored(int domain, int protocol) {
|
||||
// LWIPRawUDPRecvImpl has wake built into the recv callback, so no extra monitoring needed
|
||||
return socket_udp_recv(domain, protocol);
|
||||
std::unique_ptr<UDPSocket> socket_udp_loop_monitored(int domain, int protocol) {
|
||||
// LWIPRawUDPImpl has wake built into the recv callback, so no extra monitoring needed
|
||||
return socket_udp(domain, protocol);
|
||||
}
|
||||
|
||||
#undef LWIP_LOCK
|
||||
|
||||
@@ -16,13 +16,13 @@ namespace esphome::socket {
|
||||
|
||||
/// Send-only UDP socket implementation for LWIP raw API.
|
||||
/// Non-virtual, concrete type. Uses lwip/udp.h raw API.
|
||||
/// No receive capability — use LWIPRawUDPRecvImpl for sockets that need to receive.
|
||||
class LWIPRawUDPImpl {
|
||||
/// No receive capability — use LWIPRawUDPImpl for sockets that need to receive.
|
||||
class LWIPRawUDPSendImpl {
|
||||
public:
|
||||
LWIPRawUDPImpl(sa_family_t family);
|
||||
~LWIPRawUDPImpl();
|
||||
LWIPRawUDPImpl(const LWIPRawUDPImpl &) = delete;
|
||||
LWIPRawUDPImpl &operator=(const LWIPRawUDPImpl &) = delete;
|
||||
LWIPRawUDPSendImpl(sa_family_t family);
|
||||
~LWIPRawUDPSendImpl();
|
||||
LWIPRawUDPSendImpl(const LWIPRawUDPSendImpl &) = delete;
|
||||
LWIPRawUDPSendImpl &operator=(const LWIPRawUDPSendImpl &) = delete;
|
||||
|
||||
int bind(const struct sockaddr *name, socklen_t addrlen);
|
||||
int close();
|
||||
@@ -54,17 +54,17 @@ class LWIPRawUDPImpl {
|
||||
};
|
||||
|
||||
/// UDP socket with receive support for LWIP raw API.
|
||||
/// Extends LWIPRawUDPImpl with a fixed-size ring buffer for incoming packets.
|
||||
/// Extends LWIPRawUDPSendImpl with a fixed-size ring buffer for incoming packets.
|
||||
/// The recv callback is registered on bind().
|
||||
///
|
||||
/// Note: close() and bind() intentionally hide the base class methods to add
|
||||
/// recv callback registration/cleanup. This is safe because these classes are
|
||||
/// never used polymorphically (no virtual dispatch) — callers always use the
|
||||
/// concrete LWIPRawUDPRecvImpl type via the UDPRecvSocket alias.
|
||||
class LWIPRawUDPRecvImpl : public LWIPRawUDPImpl {
|
||||
/// concrete LWIPRawUDPImpl type via the UDPSocket alias.
|
||||
class LWIPRawUDPImpl : public LWIPRawUDPSendImpl {
|
||||
public:
|
||||
using LWIPRawUDPImpl::LWIPRawUDPImpl;
|
||||
~LWIPRawUDPRecvImpl();
|
||||
using LWIPRawUDPSendImpl::LWIPRawUDPSendImpl;
|
||||
~LWIPRawUDPImpl();
|
||||
|
||||
/// Close the socket, flushing any queued rx packets first.
|
||||
int close();
|
||||
|
||||
@@ -27,24 +27,25 @@ namespace esphome::socket {
|
||||
// Type aliases — only one implementation is active per build.
|
||||
// Socket is the concrete type for connected sockets.
|
||||
// ListenSocket is the concrete type for listening/server sockets.
|
||||
// UDPSocket is the concrete type for UDP sockets.
|
||||
// UDPSocket is the concrete type for UDP sockets (send + receive).
|
||||
// UDPSendSocket is the concrete type for send-only UDP sockets.
|
||||
// On BSD and LWIP_SOCKETS, all aliases resolve to the same type.
|
||||
// On LWIP_TCP, they are different types (no virtual dispatch between them).
|
||||
#ifdef USE_SOCKET_IMPL_BSD_SOCKETS
|
||||
using Socket = BSDSocketImpl;
|
||||
using ListenSocket = BSDSocketImpl;
|
||||
using UDPSendSocket = BSDSocketImpl;
|
||||
using UDPSocket = BSDSocketImpl;
|
||||
using UDPRecvSocket = BSDSocketImpl;
|
||||
#elif defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
|
||||
using Socket = LwIPSocketImpl;
|
||||
using ListenSocket = LwIPSocketImpl;
|
||||
using UDPSendSocket = LwIPSocketImpl;
|
||||
using UDPSocket = LwIPSocketImpl;
|
||||
using UDPRecvSocket = LwIPSocketImpl;
|
||||
#elif defined(USE_SOCKET_IMPL_LWIP_TCP)
|
||||
using Socket = LWIPRawImpl;
|
||||
using ListenSocket = LWIPRawListenImpl;
|
||||
using UDPSendSocket = LWIPRawUDPSendImpl;
|
||||
using UDPSocket = LWIPRawUDPImpl;
|
||||
using UDPRecvSocket = LWIPRawUDPRecvImpl;
|
||||
#endif
|
||||
|
||||
#ifdef USE_LWIP_FAST_SELECT
|
||||
@@ -98,13 +99,30 @@ std::unique_ptr<Socket> socket_loop_monitored(int domain, int type, int protocol
|
||||
|
||||
/// Create a send-only UDP socket of the given domain and protocol.
|
||||
#ifdef USE_SOCKET_IMPL_LWIP_TCP
|
||||
std::unique_ptr<UDPSendSocket> socket_udp_send(int domain, int protocol);
|
||||
#else
|
||||
inline std::unique_ptr<UDPSendSocket> socket_udp_send(int domain, int protocol) {
|
||||
return esphome::socket::socket(domain, SOCK_DGRAM, protocol);
|
||||
}
|
||||
#endif
|
||||
/// Create a send-only UDP socket in the newest available IP domain.
|
||||
inline std::unique_ptr<UDPSendSocket> socket_ip_udp_send(int protocol) {
|
||||
#if USE_NETWORK_IPV6
|
||||
return socket_udp_send(AF_INET6, protocol);
|
||||
#else
|
||||
return socket_udp_send(AF_INET, protocol);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Create a UDP socket (send + receive) of the given domain and protocol.
|
||||
#ifdef USE_SOCKET_IMPL_LWIP_TCP
|
||||
std::unique_ptr<UDPSocket> socket_udp(int domain, int protocol);
|
||||
#else
|
||||
inline std::unique_ptr<UDPSocket> socket_udp(int domain, int protocol) {
|
||||
return esphome::socket::socket(domain, SOCK_DGRAM, protocol);
|
||||
}
|
||||
#endif
|
||||
/// Create a send-only UDP socket in the newest available IP domain.
|
||||
/// Create a UDP socket (send + receive) in the newest available IP domain.
|
||||
inline std::unique_ptr<UDPSocket> socket_ip_udp(int protocol) {
|
||||
#if USE_NETWORK_IPV6
|
||||
return socket_udp(AF_INET6, protocol);
|
||||
@@ -113,38 +131,21 @@ inline std::unique_ptr<UDPSocket> socket_ip_udp(int protocol) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Create a UDP socket with receive support of the given domain and protocol.
|
||||
#ifdef USE_SOCKET_IMPL_LWIP_TCP
|
||||
std::unique_ptr<UDPRecvSocket> socket_udp_recv(int domain, int protocol);
|
||||
#else
|
||||
inline std::unique_ptr<UDPRecvSocket> socket_udp_recv(int domain, int protocol) {
|
||||
return esphome::socket::socket(domain, SOCK_DGRAM, protocol);
|
||||
}
|
||||
#endif
|
||||
/// Create a UDP socket with receive support in the newest available IP domain.
|
||||
inline std::unique_ptr<UDPRecvSocket> socket_ip_udp_recv(int protocol) {
|
||||
#if USE_NETWORK_IPV6
|
||||
return socket_udp_recv(AF_INET6, protocol);
|
||||
#else
|
||||
return socket_udp_recv(AF_INET, protocol);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Create a UDP recv socket and monitor it for data in the main loop.
|
||||
/// On LWIP_TCP platforms, wake is built into the recv callback so this just delegates to socket_udp_recv().
|
||||
/// Create a UDP socket and monitor it for data in the main loop.
|
||||
/// On LWIP_TCP platforms, wake is built into the recv callback so this just delegates to socket_udp().
|
||||
/// On BSD/LWIP_SOCKETS platforms, this registers the socket with the Application's select() loop.
|
||||
#ifdef USE_SOCKET_IMPL_LWIP_TCP
|
||||
std::unique_ptr<UDPRecvSocket> socket_udp_recv_loop_monitored(int domain, int protocol);
|
||||
std::unique_ptr<UDPSocket> socket_udp_loop_monitored(int domain, int protocol);
|
||||
#else
|
||||
inline std::unique_ptr<UDPRecvSocket> socket_udp_recv_loop_monitored(int domain, int protocol) {
|
||||
inline std::unique_ptr<UDPSocket> socket_udp_loop_monitored(int domain, int protocol) {
|
||||
return socket_loop_monitored(domain, SOCK_DGRAM, protocol);
|
||||
}
|
||||
#endif
|
||||
inline std::unique_ptr<UDPRecvSocket> socket_ip_udp_recv_loop_monitored(int protocol) {
|
||||
inline std::unique_ptr<UDPSocket> socket_ip_udp_loop_monitored(int protocol) {
|
||||
#if USE_NETWORK_IPV6
|
||||
return socket_udp_recv_loop_monitored(AF_INET6, protocol);
|
||||
return socket_udp_loop_monitored(AF_INET6, protocol);
|
||||
#else
|
||||
return socket_udp_recv_loop_monitored(AF_INET, protocol);
|
||||
return socket_udp_loop_monitored(AF_INET, protocol);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user