13static const char *
const TAG =
"api.frame_helper";
16static constexpr size_t API_MAX_LOG_BYTES = 168;
18#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
19#define HELPER_LOG(msg, ...) \
21 char peername_buf[socket::SOCKADDR_STR_LEN]; \
22 this->get_peername_to(peername_buf); \
23 ESP_LOGVV(TAG, "%s (%s): " msg, this->client_name_, peername_buf, ##__VA_ARGS__); \
26#define HELPER_LOG(msg, ...) ((void) 0)
29#ifdef HELPER_LOG_PACKETS
30#define LOG_PACKET_RECEIVED(buffer) \
32 char hex_buf_[format_hex_pretty_size(API_MAX_LOG_BYTES)]; \
33 ESP_LOGVV(TAG, "Received frame: %s", \
34 format_hex_pretty_to(hex_buf_, (buffer).data(), \
35 (buffer).size() < API_MAX_LOG_BYTES ? (buffer).size() : API_MAX_LOG_BYTES)); \
37#define LOG_PACKET_SENDING(data, len) \
39 char hex_buf_[format_hex_pretty_size(API_MAX_LOG_BYTES)]; \
40 ESP_LOGVV(TAG, "Sending raw: %s", \
41 format_hex_pretty_to(hex_buf_, data, (len) < API_MAX_LOG_BYTES ? (len) : API_MAX_LOG_BYTES)); \
44#define LOG_PACKET_RECEIVED(buffer) ((void) 0)
45#define LOG_PACKET_SENDING(data, len) ((void) 0)
53 return LOG_STR(
"WOULD_BLOCK");
55 return LOG_STR(
"BAD_INDICATOR");
57 return LOG_STR(
"BAD_DATA_PACKET");
59 return LOG_STR(
"TCP_NODELAY_FAILED");
61 return LOG_STR(
"TCP_NONBLOCKING_FAILED");
63 return LOG_STR(
"CLOSE_FAILED");
65 return LOG_STR(
"SHUTDOWN_FAILED");
67 return LOG_STR(
"BAD_STATE");
69 return LOG_STR(
"BAD_ARG");
71 return LOG_STR(
"SOCKET_READ_FAILED");
73 return LOG_STR(
"SOCKET_WRITE_FAILED");
75 return LOG_STR(
"OUT_OF_MEMORY");
77 return LOG_STR(
"CONNECTION_CLOSED");
81 return LOG_STR(
"BAD_HANDSHAKE_PACKET_LEN");
83 return LOG_STR(
"HANDSHAKESTATE_READ_FAILED");
85 return LOG_STR(
"HANDSHAKESTATE_WRITE_FAILED");
87 return LOG_STR(
"HANDSHAKESTATE_BAD_STATE");
89 return LOG_STR(
"CIPHERSTATE_DECRYPT_FAILED");
91 return LOG_STR(
"CIPHERSTATE_ENCRYPT_FAILED");
93 return LOG_STR(
"HANDSHAKESTATE_SETUP_FAILED");
95 return LOG_STR(
"HANDSHAKESTATE_SPLIT_FAILED");
97 return LOG_STR(
"BAD_HANDSHAKE_ERROR_BYTE");
100 return LOG_STR(
"UNKNOWN");
103#ifdef HELPER_LOG_PACKETS
105 LOG_PACKET_SENDING(
reinterpret_cast<const uint8_t *
>(data),
len);
112 if (err != EWOULDBLOCK && err != EAGAIN) {
114 HELPER_LOG(
"Socket write failed with errno %d", err);
123 struct iovec iov = {
const_cast<void *
>(data),
len};
125#ifdef HELPER_LOG_PACKETS
128 LOG_PACKET_SENDING(
reinterpret_cast<const uint8_t *
>(data),
len);
147 if (sent ==
static_cast<ssize_t>(total_write_len))
158 if (err != EWOULDBLOCK && err != EAGAIN) {
160 HELPER_LOG(
"Socket write failed with errno %d", err);
168 if (sent ==
static_cast<ssize_t>(total_write_len))
173 HELPER_LOG(
"Overflow buffer full, dropping connection");
182 this->
socket_->getpeername_to(buf);
191 HELPER_LOG(
"Bad state for init %d", (
int)
state_);
194 int err = this->
socket_->setblocking(
false);
197 HELPER_LOG(
"Setting nonblocking failed with errno %d", errno);
202 err = this->
socket_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable,
sizeof(
int));
205 HELPER_LOG(
"Setting nodelay failed with errno %d", errno);
212 if (received == -1) {
213 const int err = errno;
214 if (err == EWOULDBLOCK || err == EAGAIN) {
218 HELPER_LOG(
"Socket read failed with errno %d", err);
220 }
else if (received == 0) {
222 HELPER_LOG(
"Connection closed");
APIError handle_socket_read_result_(ssize_t received)
void log_packet_sending_(const void *data, uint16_t len)
APIError write_raw_buf_(const void *data, uint16_t len, ssize_t sent=WRITE_NOT_ATTEMPTED)
static constexpr ssize_t WRITE_FAILED
APIError write_raw_iov_(const struct iovec *iov, int iovcnt, uint16_t total_write_len, ssize_t sent=WRITE_NOT_ATTEMPTED)
static constexpr ssize_t WRITE_NOT_ATTEMPTED
const char * get_peername_to(std::span< char, socket::SOCKADDR_STR_LEN > buf) const
APIOverflowBuffer overflow_buf_
std::unique_ptr< socket::Socket > socket_
APIError drain_overflow_and_handle_errors_()
ssize_t ESPHOME_ALWAYS_INLINE write_iov_to_socket_(const struct iovec *iov, int iovcnt)
bool empty() const
True when no backlogged data is waiting.
bool enqueue_iov(const struct iovec *iov, int iovcnt, uint16_t total_len, uint16_t skip)
Enqueue unsent IOV data into the backlog.
ssize_t try_drain(socket::Socket *socket)
Try to drain queued data to the socket.
const LogString * api_error_to_logstr(APIError err)
@ HANDSHAKESTATE_READ_FAILED
@ HANDSHAKESTATE_BAD_STATE
@ HANDSHAKESTATE_SPLIT_FAILED
@ BAD_HANDSHAKE_PACKET_LEN
@ BAD_HANDSHAKE_ERROR_BYTE
@ HANDSHAKESTATE_SETUP_FAILED
@ CIPHERSTATE_ENCRYPT_FAILED
@ CIPHERSTATE_DECRYPT_FAILED
@ HANDSHAKESTATE_WRITE_FAILED