ESPHome 2026.5.1
Loading...
Searching...
No Matches
bsd_sockets_impl.cpp
Go to the documentation of this file.
3#include "socket.h"
4
5#ifdef USE_SOCKET_IMPL_BSD_SOCKETS
6
7#include <cstring>
9#ifdef USE_HOST
10#include "esphome/core/wake.h"
11#endif
12
13namespace esphome::socket {
14
15BSDSocketImpl::BSDSocketImpl(int fd, bool monitor_loop) {
16 this->fd_ = fd;
17 if (this->fd_ < 0)
18 return;
19#ifdef USE_HOST
20 // Release listening ports on OTA re-exec.
21 int flags = ::fcntl(this->fd_, F_GETFD, 0);
22 if (flags >= 0)
23 ::fcntl(this->fd_, F_SETFD, flags | FD_CLOEXEC);
24#endif
25 if (!monitor_loop)
26 return;
27#ifdef USE_LWIP_FAST_SELECT
29#else
31#endif
32}
33
35
37 if (this->fd_ < 0) {
38 // Already closed, or never opened.
39 return 0;
40 }
41#ifdef USE_LWIP_FAST_SELECT
42 // Null the cached lwip_sock pointer before closing. The underlying lwip slot can be
43 // recycled for a new connection as soon as ::close() returns, so anything that might
44 // dereference cached_sock_ post-close (e.g. setsockopt(TCP_NODELAY)) would otherwise
45 // touch an unrelated socket's pcb. No per-socket callback unhook is needed —
46 // all LwIP sockets share the same static event_callback.
47 this->cached_sock_ = nullptr;
48#else
49 if (this->loop_monitored_) {
51 }
52#endif
53 int ret = ::close(this->fd_);
54 this->fd_ = -1; // Sentinel for "closed" — prevents double-close and makes use-after-close visible.
55 return ret;
56}
57
58int BSDSocketImpl::setblocking(bool blocking) {
59 int fl = ::fcntl(this->fd_, F_GETFL, 0);
60 if (blocking) {
61 fl &= ~O_NONBLOCK;
62 } else {
63 fl |= O_NONBLOCK;
64 }
65 ::fcntl(this->fd_, F_SETFL, fl);
66 return 0;
67}
68
69size_t BSDSocketImpl::getpeername_to(std::span<char, SOCKADDR_STR_LEN> buf) {
70 struct sockaddr_storage storage;
71 socklen_t len = sizeof(storage);
72 if (this->getpeername(reinterpret_cast<struct sockaddr *>(&storage), &len) != 0) {
73 buf[0] = '\0';
74 return 0;
75 }
76 return format_sockaddr_to(reinterpret_cast<struct sockaddr *>(&storage), len, buf);
77}
78
79size_t BSDSocketImpl::getsockname_to(std::span<char, SOCKADDR_STR_LEN> buf) {
80 struct sockaddr_storage storage;
81 socklen_t len = sizeof(storage);
82 if (this->getsockname(reinterpret_cast<struct sockaddr *>(&storage), &len) != 0) {
83 buf[0] = '\0';
84 return 0;
85 }
86 return format_sockaddr_to(reinterpret_cast<struct sockaddr *>(&storage), len, buf);
87}
88
89// Helper to create a socket with optional monitoring
90static std::unique_ptr<BSDSocketImpl> create_socket(int domain, int type, int protocol, bool loop_monitored = false) {
91 int ret = ::socket(domain, type, protocol);
92 if (ret == -1)
93 return nullptr;
94 return make_unique<BSDSocketImpl>(ret, loop_monitored);
95}
96
97std::unique_ptr<Socket> socket(int domain, int type, int protocol) {
98 return create_socket(domain, type, protocol, false);
99}
100
101std::unique_ptr<Socket> socket_loop_monitored(int domain, int type, int protocol) {
102 return create_socket(domain, type, protocol, true);
103}
104
105} // namespace esphome::socket
106
107#endif // USE_SOCKET_IMPL_BSD_SOCKETS
int getpeername(struct sockaddr *addr, socklen_t *addrlen)
size_t getpeername_to(std::span< char, SOCKADDR_STR_LEN > buf)
Format peer address into a fixed-size buffer (no heap allocation)
size_t getsockname_to(std::span< char, SOCKADDR_STR_LEN > buf)
Format local address into a fixed-size buffer (no heap allocation)
int getsockname(struct sockaddr *addr, socklen_t *addrlen)
BSDSocketImpl(int fd, bool monitor_loop=false)
uint16_t type
uint16_t flags
uint32_t socklen_t
Definition headers.h:99
size_t format_sockaddr_to(const struct sockaddr *addr_ptr, socklen_t len, std::span< char, SOCKADDR_STR_LEN > buf)
Format sockaddr into caller-provided buffer, returns length written (excluding null)
Definition socket.cpp:56
std::unique_ptr< Socket > socket(int domain, int type, int protocol)
Create a socket of the given domain, type and protocol.
struct lwip_sock * hook_fd_for_fast_select(int fd)
Resolve an fd to its lwip_sock and install the netconn event-callback hook so the main loop is woken ...
Definition socket.h:56
std::unique_ptr< Socket > socket_loop_monitored(int domain, int type, int protocol)
Create a socket and monitor it for data in the main loop.
std::string size_t len
bool wake_register_fd(int fd)
Register a socket file descriptor with the host select() loop.
Definition wake_host.cpp:46
void wake_unregister_fd(int fd)
Unregister a socket file descriptor. Not thread-safe — main loop only.
Definition wake_host.cpp:65
Platform-specific main loop wake primitives.