ESPHome 2025.12.5
Loading...
Searching...
No Matches
socket.cpp
Go to the documentation of this file.
1#include "socket.h"
2#if defined(USE_SOCKET_IMPL_LWIP_TCP) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) || defined(USE_SOCKET_IMPL_BSD_SOCKETS)
3#include <cerrno>
4#include <cstring>
5#include <string>
6#include "esphome/core/log.h"
8
9namespace esphome {
10namespace socket {
11
13
14bool Socket::ready() const {
15#ifdef USE_SOCKET_SELECT_SUPPORT
16 if (!loop_monitored_) {
17 // Non-monitored sockets always return true (assume data may be available)
18 return true;
19 }
20
21 // For loop-monitored sockets, check with the Application's select() results
22 int fd = this->get_fd();
23 if (fd < 0) {
24 // No valid file descriptor, assume ready (fallback behavior)
25 return true;
26 }
27
28 return App.is_socket_ready(fd);
29#else
30 // Without select() support, we can't monitor sockets in the loop
31 // Always return true (assume data may be available)
32 return true;
33#endif
34}
35
36std::unique_ptr<Socket> socket_ip(int type, int protocol) {
37#if USE_NETWORK_IPV6
38 return socket(AF_INET6, type, protocol);
39#else
40 return socket(AF_INET, type, protocol);
41#endif /* USE_NETWORK_IPV6 */
42}
43
44std::unique_ptr<Socket> socket_ip_loop_monitored(int type, int protocol) {
45#if USE_NETWORK_IPV6
46 return socket_loop_monitored(AF_INET6, type, protocol);
47#else
48 return socket_loop_monitored(AF_INET, type, protocol);
49#endif /* USE_NETWORK_IPV6 */
50}
51
52socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port) {
53#if USE_NETWORK_IPV6
54 if (ip_address.find(':') != std::string::npos) {
55 if (addrlen < sizeof(sockaddr_in6)) {
56 errno = EINVAL;
57 return 0;
58 }
59 auto *server = reinterpret_cast<sockaddr_in6 *>(addr);
60 memset(server, 0, sizeof(sockaddr_in6));
61 server->sin6_family = AF_INET6;
62 server->sin6_port = htons(port);
63
64#ifdef USE_SOCKET_IMPL_BSD_SOCKETS
65 // Use standard inet_pton for BSD sockets
66 if (inet_pton(AF_INET6, ip_address.c_str(), &server->sin6_addr) != 1) {
67 errno = EINVAL;
68 return 0;
69 }
70#else
71 // Use LWIP-specific functions
72 ip6_addr_t ip6;
73 inet6_aton(ip_address.c_str(), &ip6);
74 memcpy(server->sin6_addr.un.u32_addr, ip6.addr, sizeof(ip6.addr));
75#endif
76 return sizeof(sockaddr_in6);
77 }
78#endif /* USE_NETWORK_IPV6 */
79 if (addrlen < sizeof(sockaddr_in)) {
80 errno = EINVAL;
81 return 0;
82 }
83 auto *server = reinterpret_cast<sockaddr_in *>(addr);
84 memset(server, 0, sizeof(sockaddr_in));
85 server->sin_family = AF_INET;
86 server->sin_addr.s_addr = inet_addr(ip_address.c_str());
87 server->sin_port = htons(port);
88 return sizeof(sockaddr_in);
89}
90
91socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port) {
92#if USE_NETWORK_IPV6
93 if (addrlen < sizeof(sockaddr_in6)) {
94 errno = EINVAL;
95 return 0;
96 }
97 auto *server = reinterpret_cast<sockaddr_in6 *>(addr);
98 memset(server, 0, sizeof(sockaddr_in6));
99 server->sin6_family = AF_INET6;
100 server->sin6_port = htons(port);
101 server->sin6_addr = IN6ADDR_ANY_INIT;
102 return sizeof(sockaddr_in6);
103#else
104 if (addrlen < sizeof(sockaddr_in)) {
105 errno = EINVAL;
106 return 0;
107 }
108 auto *server = reinterpret_cast<sockaddr_in *>(addr);
109 memset(server, 0, sizeof(sockaddr_in));
110 server->sin_family = AF_INET;
111 server->sin_addr.s_addr = ESPHOME_INADDR_ANY;
112 server->sin_port = htons(port);
113 return sizeof(sockaddr_in);
114#endif /* USE_NETWORK_IPV6 */
115}
116} // namespace socket
117} // namespace esphome
118#endif
bool is_socket_ready(int fd) const
Check if there's data available on a socket without blocking This function is thread-safe for reading...
bool ready() const
Check if socket has data ready to read For loop-monitored sockets, checks with the Application's sele...
Definition socket.cpp:14
virtual int get_fd() const
Get the underlying file descriptor (returns -1 if not supported)
Definition socket.h:52
bool loop_monitored_
Whether this socket is monitored by the event loop.
Definition socket.h:61
uint16_t type
uint32_t socklen_t
Definition headers.h:97
std::unique_ptr< Socket > socket_ip(int type, int protocol)
Create a socket in the newest available IP domain (IPv6 or IPv4) of the given type and protocol.
Definition socket.cpp:36
std::unique_ptr< Socket > socket(int domain, int type, int protocol)
Create a socket of the given domain, type and protocol.
std::unique_ptr< Socket > socket_ip_loop_monitored(int type, int protocol)
Definition socket.cpp:44
socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port)
Set a sockaddr to the specified address and port for the IP version used by socket_ip().
Definition socket.cpp:52
socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port)
Set a sockaddr to the any address and specified port for the IP version used by socket_ip().
Definition socket.cpp:91
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.
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
Application App
Global storage of Application pointer - only one Application can exist.