ESPHome 2026.4.0-dev
Loading...
Searching...
No Matches
api_overflow_buffer.cpp
Go to the documentation of this file.
2#ifdef USE_API
3#include <cstring>
4
5namespace esphome::api {
6
8 for (auto *entry : this->queue_) {
9 if (entry != nullptr)
10 Entry::destroy(entry);
11 }
12}
13
15 while (this->count_ > 0) {
16 Entry *front = this->queue_[this->head_];
17
18 ssize_t sent = socket->write(front->current_data(), front->remaining());
19
20 if (sent <= 0) {
21 // -1 = error (caller checks errno for EWOULDBLOCK vs hard error)
22 // 0 = nothing sent (treat as no progress)
23 return sent;
24 }
25
26 if (static_cast<uint16_t>(sent) < front->remaining()) {
27 // Partially sent, update offset and stop
28 front->offset += static_cast<uint16_t>(sent);
29 return sent;
30 }
31
32 // Entry fully sent — free it and advance
33 Entry::destroy(front);
34 this->queue_[this->head_] = nullptr;
35 this->head_ = (this->head_ + 1) % API_MAX_SEND_QUEUE;
36 this->count_--;
37 }
38
39 return 0; // All drained
40}
41
42bool APIOverflowBuffer::enqueue_iov(const struct iovec *iov, int iovcnt, uint16_t total_len, uint16_t skip) {
43 if (this->count_ >= API_MAX_SEND_QUEUE)
44 return false;
45
46 uint16_t buffer_size = total_len - skip;
47 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
48 auto *entry = new Entry{new uint8_t[buffer_size], buffer_size, 0};
49 this->queue_[this->tail_] = entry;
50
51 uint16_t to_skip = skip;
52 uint16_t write_pos = 0;
53
54 for (int i = 0; i < iovcnt; i++) {
55 if (to_skip >= iov[i].iov_len) {
56 to_skip -= static_cast<uint16_t>(iov[i].iov_len);
57 } else {
58 const uint8_t *src = reinterpret_cast<uint8_t *>(iov[i].iov_base) + to_skip;
59 uint16_t len = static_cast<uint16_t>(iov[i].iov_len) - to_skip;
60 std::memcpy(entry->data + write_pos, src, len);
61 write_pos += len;
62 to_skip = 0;
63 }
64 }
65
66 this->tail_ = (this->tail_ + 1) % API_MAX_SEND_QUEUE;
67 this->count_++;
68 return true;
69}
70
71} // namespace esphome::api
72
73#endif // USE_API
std::array< Entry *, API_MAX_SEND_QUEUE > queue_
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.
__int64 ssize_t
Definition httplib.h:178
std::string size_t len
Definition helpers.h:1045
A single heap-allocated send-backlog entry.
uint16_t offset
uint16_t remaining() const
const uint8_t * current_data() const
static ESPHOME_ALWAYS_INLINE void destroy(Entry *entry)
Free this entry and its data buffer.
void * iov_base
Definition headers.h:103
size_t iov_len
Definition headers.h:104