mirror of
https://github.com/esphome/esphome.git
synced 2026-09-11 15:27:33 +00:00
[socket] Apply SO_REUSEADDR to the pcb and unmap IPv4-mapped IPv6 destinations
This commit is contained in:
@@ -68,6 +68,11 @@ bool sockaddr_to_lwip(const struct sockaddr *addr, socklen_t addrlen, ip_addr_t
|
||||
*port = ntohs(addr6->sin6_port);
|
||||
IP_SET_TYPE_VAL(*ip, IPADDR_TYPE_V6);
|
||||
memcpy(&ip_2_ip6(ip)->addr, &addr6->sin6_addr.un.u8_addr, 16);
|
||||
// Unmap ::ffff:a.b.c.d so replies to recvfrom addresses route as IPv4
|
||||
if (ip6_addr_isipv4mappedipv6(ip_2_ip6(ip))) {
|
||||
unmap_ipv4_mapped_ipv6(ip_2_ip4(ip), ip_2_ip6(ip));
|
||||
IP_SET_TYPE_VAL(*ip, IPADDR_TYPE_V4);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -291,7 +291,7 @@ int LWIPRawCommon::setsockopt(int level, int optname, const void *optval, sockle
|
||||
}
|
||||
|
||||
int LWIPRawCommon::ip2sockaddr_(ip_addr_t *ip, uint16_t port, struct sockaddr *name, socklen_t *addrlen) {
|
||||
// TCP pcb stores port in network byte order; convert to host order for the shared helper
|
||||
// lwip pcb ports are host order; ntohs preserves historical byte-swapped sin_port output
|
||||
return lwip_ip_to_sockaddr(this->family_, ip, ntohs(port), name, addrlen);
|
||||
}
|
||||
|
||||
|
||||
@@ -122,8 +122,16 @@ int LWIPRawUDPSendImpl::setsockopt(int level, int optname, const void *optval, s
|
||||
return -1;
|
||||
}
|
||||
if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
|
||||
// lwip raw UDP doesn't enforce port exclusivity the same way,
|
||||
// but we accept this silently for compatibility
|
||||
if (optval == nullptr || optlen < sizeof(int)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
// Effective only where lwip is built with SO_REUSE=1 (ESP8266 yes, RP2040 currently no)
|
||||
if (*reinterpret_cast<const int *>(optval)) {
|
||||
ip_set_option(this->pcb_, SOF_REUSEADDR);
|
||||
} else {
|
||||
ip_reset_option(this->pcb_, SOF_REUSEADDR);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (level == SOL_SOCKET && optname == SO_BROADCAST) {
|
||||
@@ -170,7 +178,7 @@ int LWIPRawUDPSendImpl::getsockopt(int level, int optname, void *optval, socklen
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
*reinterpret_cast<int *>(optval) = 1;
|
||||
*reinterpret_cast<int *>(optval) = ip_get_option(this->pcb_, SOF_REUSEADDR) ? 1 : 0;
|
||||
*optlen = sizeof(int);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -96,8 +96,7 @@ class LWIPRawUDPImpl : private LWIPRawUDPSendImpl {
|
||||
static constexpr uint8_t UDP_RX_QUEUE_SIZE = 4;
|
||||
static constexpr uint8_t UDP_RX_MASK = UDP_RX_QUEUE_SIZE - 1;
|
||||
static_assert((UDP_RX_QUEUE_SIZE & UDP_RX_MASK) == 0, "UDP_RX_QUEUE_SIZE must be power of 2");
|
||||
// Fields are written by recv_fn_ before rx_count_ makes a slot visible,
|
||||
// so per-member initializers would only add dead zeroing of the array.
|
||||
// Fields are written by recv_fn_ before rx_count_ makes a slot visible
|
||||
struct UDPRxPacket {
|
||||
ip_addr_t src_addr;
|
||||
struct pbuf *pb;
|
||||
|
||||
Reference in New Issue
Block a user