4#ifdef USE_SOCKET_IMPL_LWIP_TCP
23#define LWIP_LOCK() esphome::LwIPLock lwip_lock_guard
29 if (this->
pcb_ !=
nullptr)
35 if (this->
pcb_ ==
nullptr) {
39 if (name ==
nullptr) {
49 err_t err = udp_bind(this->
pcb_, &ip, port);
64 if (this->
pcb_ ==
nullptr) {
68 udp_remove(this->
pcb_);
81 if (buf ==
nullptr || dest_addr ==
nullptr) {
87 if (
len > UINT16_MAX) {
100 if (this->
pcb_ ==
nullptr) {
106 struct pbuf *pb = pbuf_alloc(PBUF_TRANSPORT, (uint16_t)
len, PBUF_RAM);
111 memcpy(pb->payload, buf,
len);
113 err_t err = udp_sendto(this->
pcb_, pb, &dst_ip, dst_port);
125 if (this->
pcb_ ==
nullptr) {
129 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
130 if (optval ==
nullptr || optlen <
sizeof(
int)) {
135 if (*
reinterpret_cast<const int *
>(optval)) {
136 ip_set_option(this->
pcb_, SOF_REUSEADDR);
138 ip_reset_option(this->
pcb_, SOF_REUSEADDR);
142 if (level == SOL_SOCKET && optname == SO_BROADCAST) {
143 if (optval ==
nullptr || optlen <
sizeof(
int)) {
147 int val = *
reinterpret_cast<const int *
>(optval);
149 ip_set_option(this->
pcb_, SOF_BROADCAST);
151 ip_reset_option(this->
pcb_, SOF_BROADCAST);
155 if (level == IPPROTO_IP && (optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP)) {
156 if (optval ==
nullptr || optlen <
sizeof(
struct ip_mreq)) {
160 auto *mreq =
reinterpret_cast<const struct
ip_mreq *
>(optval);
161 ip4_addr_t multiaddr{mreq->imr_multiaddr.s_addr};
162 ip4_addr_t ifaddr{mreq->imr_interface.s_addr};
164 optname == IP_ADD_MEMBERSHIP ? igmp_joingroup(&ifaddr, &multiaddr) : igmp_leavegroup(&ifaddr, &multiaddr);
177 if (this->
pcb_ ==
nullptr) {
181 if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
182 if (optval ==
nullptr || optlen ==
nullptr || *optlen <
sizeof(
int)) {
186 *
reinterpret_cast<int *
>(optval) = ip_get_option(this->
pcb_, SOF_REUSEADDR) ? 1 : 0;
187 *optlen =
sizeof(int);
212 if (this->
pcb_ !=
nullptr)
219 if (this->
pcb_ !=
nullptr) {
220 udp_recv(this->
pcb_,
nullptr,
nullptr);
234 if (buf ==
nullptr &&
len > 0) {
239 if (this->
pcb_ ==
nullptr) {
252 if (src_addr ==
nullptr || addrlen ==
nullptr ||
253 this->
ip2sockaddr_(&pkt.src_addr, pkt.src_port, src_addr, addrlen) == 0) {
255 pbuf_copy_partial(pkt.pb, buf,
ret, 0);
289 slot.src_addr = *addr;
290 slot.src_port = port;
298static struct udp_pcb *new_udp_pcb(
int domain) {
300 return udp_new_ip_type(domain == AF_INET6 ? IPADDR_TYPE_ANY :
IPADDR_TYPE_V4);
309 auto *pcb = new_udp_pcb(domain);
310 if (pcb ==
nullptr) {
314 return make_unique<LWIPRawUDPSendImpl>((
sa_family_t) domain, pcb);
317std::unique_ptr<UDPSocket>
socket_udp(
int domain,
int protocol) {
320 auto *pcb = new_udp_pcb(domain);
321 if (pcb ==
nullptr) {
326 return make_unique<LWIPRawUDPImpl>((
sa_family_t) domain, pcb);
UDP socket with receive support for LWIP raw API.
static constexpr uint8_t UDP_RX_MASK
LWIPRawUDPImpl(sa_family_t family, struct udp_pcb *pcb)
Caller (the factory) must hold the lwip lock; registers the recv callback.
ssize_t recvfrom(void *buf, size_t len, struct sockaddr *src_addr, socklen_t *addrlen)
Read the next queued packet and return the source address.
int close()
Close the socket, flushing any queued rx packets first.
ssize_t read(void *buf, size_t len)
Read the next queued packet, discarding source address info.
void recv_fn_(struct pbuf *p, const ip_addr_t *addr, u16_t port)
static void s_recv_fn(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
static constexpr uint8_t UDP_RX_QUEUE_SIZE
Ring buffer for received UDP packets.
std::array< UDPRxPacket, UDP_RX_QUEUE_SIZE > rx_queue_
Send-only UDP socket implementation for LWIP raw API.
int getsockopt(int level, int optname, void *optval, socklen_t *optlen)
int setblocking(bool blocking)
int bind(const struct sockaddr *name, socklen_t addrlen)
int setsockopt(int level, int optname, const void *optval, socklen_t optlen)
int ip2sockaddr_(const ip_addr_t *ip, uint16_t port, struct sockaddr *name, socklen_t *addrlen)
Convert lwip ip_addr_t and port to sockaddr.
int close_internal_locked_()
Shared close logic — removes the udp pcb. Caller must hold LWIP_LOCK.
ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
Send a UDP packet to the specified destination.
struct in_addr ip4_addr_t
std::unique_ptr< UDPSendSocket > socket_udp_send(int domain, int protocol)
Create a send-only UDP socket (socket_udp_send), a UDP socket with receive support (socket_udp),...
bool sockaddr_to_lwip(const struct sockaddr *addr, socklen_t addrlen, ip_addr_t *ip, uint16_t *port)
Convert sockaddr to lwip ip_addr_t and host-order port.
int lwip_err_to_errno(err_t err)
errno for a failed lwip call
bool sockaddr_to_lwip_bind(sa_family_t family, const struct sockaddr *addr, socklen_t addrlen, ip_addr_t *ip, uint16_t *port)
sockaddr_to_lwip variant for bind: promotes AF_INET6 sockets to IPADDR_TYPE_ANY so they accept both I...
std::unique_ptr< UDPSocket > socket_udp(int domain, int protocol)
int lwip_ip_to_sockaddr(sa_family_t family, const ip_addr_t *ip, uint16_t port_host, struct sockaddr *name, socklen_t *addrlen)
Convert lwip ip_addr_t + host-order port to sockaddr, based on the socket's address family.
void IRAM_ATTR wake_loop_any_context()
IRAM_ATTR entry point for ISR callers — defined in wake_esp8266.cpp.
Platform-specific main loop wake primitives.