ESPHome  2025.3.3
bsd_sockets_impl.cpp
Go to the documentation of this file.
1 #include "socket.h"
2 #include "esphome/core/defines.h"
3 #include "esphome/core/helpers.h"
4 
5 #ifdef USE_SOCKET_IMPL_BSD_SOCKETS
6 
7 #include <cstring>
8 
9 #ifdef USE_ESP32
10 #include <esp_idf_version.h>
11 #include <lwip/sockets.h>
12 #endif
13 
14 namespace esphome {
15 namespace socket {
16 
17 std::string format_sockaddr(const struct sockaddr_storage &storage) {
18  if (storage.ss_family == AF_INET) {
19  const struct sockaddr_in *addr = reinterpret_cast<const struct sockaddr_in *>(&storage);
20  char buf[INET_ADDRSTRLEN];
21  if (inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)) != nullptr)
22  return std::string{buf};
23  }
24 #if LWIP_IPV6
25  else if (storage.ss_family == AF_INET6) {
26  const struct sockaddr_in6 *addr = reinterpret_cast<const struct sockaddr_in6 *>(&storage);
27  char buf[INET6_ADDRSTRLEN];
28  // Format IPv4-mapped IPv6 addresses as regular IPv4 addresses
29  if (addr->sin6_addr.un.u32_addr[0] == 0 && addr->sin6_addr.un.u32_addr[1] == 0 &&
30  addr->sin6_addr.un.u32_addr[2] == htonl(0xFFFF) &&
31  inet_ntop(AF_INET, &addr->sin6_addr.un.u32_addr[3], buf, sizeof(buf)) != nullptr) {
32  return std::string{buf};
33  }
34  if (inet_ntop(AF_INET6, &addr->sin6_addr, buf, sizeof(buf)) != nullptr)
35  return std::string{buf};
36  }
37 #endif
38  return {};
39 }
40 
41 class BSDSocketImpl : public Socket {
42  public:
43  BSDSocketImpl(int fd) : fd_(fd) {}
44  ~BSDSocketImpl() override {
45  if (!closed_) {
46  close(); // NOLINT(clang-analyzer-optin.cplusplus.VirtualCall)
47  }
48  }
49  int connect(const struct sockaddr *addr, socklen_t addrlen) override { return ::connect(fd_, addr, addrlen); }
50  std::unique_ptr<Socket> accept(struct sockaddr *addr, socklen_t *addrlen) override {
51  int fd = ::accept(fd_, addr, addrlen);
52  if (fd == -1)
53  return {};
54  return make_unique<BSDSocketImpl>(fd);
55  }
56  int bind(const struct sockaddr *addr, socklen_t addrlen) override { return ::bind(fd_, addr, addrlen); }
57  int close() override {
58  int ret = ::close(fd_);
59  closed_ = true;
60  return ret;
61  }
62  int shutdown(int how) override { return ::shutdown(fd_, how); }
63 
64  int getpeername(struct sockaddr *addr, socklen_t *addrlen) override { return ::getpeername(fd_, addr, addrlen); }
65  std::string getpeername() override {
66  struct sockaddr_storage storage;
67  socklen_t len = sizeof(storage);
68  int err = this->getpeername((struct sockaddr *) &storage, &len);
69  if (err != 0)
70  return {};
71  return format_sockaddr(storage);
72  }
73  int getsockname(struct sockaddr *addr, socklen_t *addrlen) override { return ::getsockname(fd_, addr, addrlen); }
74  std::string getsockname() override {
75  struct sockaddr_storage storage;
76  socklen_t len = sizeof(storage);
77  int err = this->getsockname((struct sockaddr *) &storage, &len);
78  if (err != 0)
79  return {};
80  return format_sockaddr(storage);
81  }
82  int getsockopt(int level, int optname, void *optval, socklen_t *optlen) override {
83  return ::getsockopt(fd_, level, optname, optval, optlen);
84  }
85  int setsockopt(int level, int optname, const void *optval, socklen_t optlen) override {
86  return ::setsockopt(fd_, level, optname, optval, optlen);
87  }
88  int listen(int backlog) override { return ::listen(fd_, backlog); }
89  ssize_t read(void *buf, size_t len) override { return ::read(fd_, buf, len); }
90  ssize_t recvfrom(void *buf, size_t len, sockaddr *addr, socklen_t *addr_len) override {
91 #if defined(USE_ESP32) || defined(USE_HOST)
92  return ::recvfrom(this->fd_, buf, len, 0, addr, addr_len);
93 #else
94  return ::lwip_recvfrom(this->fd_, buf, len, 0, addr, addr_len);
95 #endif
96  }
97  ssize_t readv(const struct iovec *iov, int iovcnt) override {
98 #if defined(USE_ESP32)
99  return ::lwip_readv(fd_, iov, iovcnt);
100 #else
101  return ::readv(fd_, iov, iovcnt);
102 #endif
103  }
104  ssize_t write(const void *buf, size_t len) override { return ::write(fd_, buf, len); }
105  ssize_t send(void *buf, size_t len, int flags) { return ::send(fd_, buf, len, flags); }
106  ssize_t writev(const struct iovec *iov, int iovcnt) override {
107 #if defined(USE_ESP32)
108  return ::lwip_writev(fd_, iov, iovcnt);
109 #else
110  return ::writev(fd_, iov, iovcnt);
111 #endif
112  }
113 
114  ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) override {
115  return ::sendto(fd_, buf, len, flags, to, tolen);
116  }
117 
118  int setblocking(bool blocking) override {
119  int fl = ::fcntl(fd_, F_GETFL, 0);
120  if (blocking) {
121  fl &= ~O_NONBLOCK;
122  } else {
123  fl |= O_NONBLOCK;
124  }
125  ::fcntl(fd_, F_SETFL, fl);
126  return 0;
127  }
128 
129  protected:
130  int fd_;
131  bool closed_ = false;
132 };
133 
134 std::unique_ptr<Socket> socket(int domain, int type, int protocol) {
135  int ret = ::socket(domain, type, protocol);
136  if (ret == -1)
137  return nullptr;
138  return std::unique_ptr<Socket>{new BSDSocketImpl(ret)};
139 }
140 
141 } // namespace socket
142 } // namespace esphome
143 
144 #endif // USE_SOCKET_IMPL_BSD_SOCKETS
sa_family_t ss_family
Definition: headers.h:92
uint32_t socklen_t
Definition: headers.h:97
uint8_t type
Definition: headers.h:100
const uint32_t flags
Definition: stm32flash.h:85
struct in_addr sin_addr
Definition: headers.h:65
std::string size_t len
Definition: helpers.h:301
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
std::string format_sockaddr(const struct sockaddr_storage &storage)
struct in6_addr sin6_addr
Definition: headers.h:77
std::unique_ptr< Socket > socket(int domain, int type, int protocol)
Create a socket of the given domain, type and protocol.