3#ifdef USE_API_PLAINTEXT
18static const char *
const TAG =
"api.plaintext";
21static constexpr size_t API_MAX_LOG_BYTES = 168;
23#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
24#define HELPER_LOG(msg, ...) \
26 char peername_buf[socket::SOCKADDR_STR_LEN]; \
27 this->get_peername_to(peername_buf); \
28 ESP_LOGVV(TAG, "%s (%s): " msg, this->client_name_, peername_buf, ##__VA_ARGS__); \
31#define HELPER_LOG(msg, ...) ((void) 0)
34#ifdef HELPER_LOG_PACKETS
35#define LOG_PACKET_RECEIVED(buffer) \
37 char hex_buf_[format_hex_pretty_size(API_MAX_LOG_BYTES)]; \
38 ESP_LOGVV(TAG, "Received frame: %s", \
39 format_hex_pretty_to(hex_buf_, (buffer).data(), \
40 (buffer).size() < API_MAX_LOG_BYTES ? (buffer).size() : API_MAX_LOG_BYTES)); \
43#define LOG_PACKET_RECEIVED(buffer) ((void) 0)
103 HELPER_LOG(
"Header buffer overflow");
125 uint8_t varint_pos = 1;
129 if (!msg_size_varint.has_value()) {
134 if (msg_size_varint.value > MAX_MESSAGE_SIZE) {
136 HELPER_LOG(
"Bad packet: message size %" PRIu32
" exceeds maximum %u",
137 static_cast<uint32_t>(msg_size_varint.value), MAX_MESSAGE_SIZE);
143 varint_pos += msg_size_varint.consumed;
146 if (!msg_type_varint.has_value()) {
150 if (msg_type_varint.value > std::numeric_limits<uint16_t>::max()) {
152 HELPER_LOG(
"Bad packet: message type %" PRIu32
" exceeds maximum %u",
153 static_cast<uint32_t>(msg_type_varint.value), std::numeric_limits<uint16_t>::max());
174 if (
static_cast<uint16_t
>(received) != to_read) {
180 LOG_PACKET_RECEIVED(this->
rx_buf_);
209 static constexpr uint8_t INDICATOR_MSG_SIZE = 19;
211 static const char MSG_PROGMEM[] PROGMEM =
"\x00"
212 "Bad indicator byte";
213 char msg[INDICATOR_MSG_SIZE];
214 memcpy_P(msg, MSG_PROGMEM, INDICATOR_MSG_SIZE);
217 static const char MSG[] =
"\x00"
218 "Bad indicator byte";
232ESPHOME_ALWAYS_INLINE
static inline void encode_varint_16(uint16_t value, uint8_t varint_len, uint8_t *p) {
233 if (varint_len >= 2) {
234 *p++ =
static_cast<uint8_t
>(value | 0x80);
236 if (varint_len == 3) {
237 *p++ =
static_cast<uint8_t
>(value | 0x80);
241 *p =
static_cast<uint8_t
>(value);
245ESPHOME_ALWAYS_INLINE
static inline void encode_varint_8(uint8_t value, uint8_t varint_len, uint8_t *p) {
246 if (varint_len == 2) {
247 *p++ =
static_cast<uint8_t
>(value | 0x80);
248 *p =
static_cast<uint8_t
>(value >> 7);
258ESPHOME_ALWAYS_INLINE
static inline uint8_t write_plaintext_header(uint8_t *buf_start, uint16_t
payload_size,
259 uint8_t message_type, uint8_t padding_size) {
262 uint8_t total_header_len = 1 + size_varint_len + type_varint_len;
274#ifdef ESPHOME_DEBUG_API
275 assert(padding_size >= total_header_len);
277 uint32_t header_offset = padding_size - total_header_len;
280 buf_start[header_offset] = 0x00;
283 encode_varint_16(
payload_size, size_varint_len, buf_start + header_offset + 1);
284 encode_varint_8(message_type, type_varint_len, buf_start + header_offset + 1 + size_varint_len);
286 return total_header_len;
290#ifdef ESPHOME_DEBUG_API
302 std::span<const MessageInfo> messages) {
303#ifdef ESPHOME_DEBUG_API
305 assert(!messages.empty());
312 const auto &first = messages[0];
313 uint8_t *first_start = buffer_data + first.offset;
314 uint8_t header_len = write_plaintext_header(first_start, first.payload_size, first.message_type,
HEADER_PADDING);
316 uint16_t total_len = header_len + first.payload_size;
318 for (
size_t i = 1; i < messages.size(); i++) {
319 const auto &msg = messages[i];
320 header_len = write_plaintext_header(buffer_data + msg.offset, msg.payload_size, msg.message_type, msg.header_size);
321 total_len += header_len + msg.payload_size;
void resize(size_t n) ESPHOME_ALWAYS_INLINE
APIError handle_socket_read_result_(ssize_t received)
APIError ESPHOME_ALWAYS_INLINE write_raw_fast_buf_(const void *data, uint16_t len)
APIError write_raw_buf_(const void *data, uint16_t len, ssize_t sent=WRITE_NOT_ATTEMPTED)
APIOverflowBuffer overflow_buf_
std::unique_ptr< socket::Socket > socket_
APIError ESPHOME_ALWAYS_INLINE check_data_state_() const
APIError drain_overflow_and_handle_errors_()
bool empty() const
True when no backlogged data is waiting.
uint8_t rx_header_buf_[6]
uint16_t rx_header_parsed_type_
APIError try_read_frame_()
Read a packet into the rx_buf_.
APIError init() override
Initialize the frame helper, returns OK if successful.
uint16_t rx_header_parsed_len_
APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) override
APIError read_packet(ReadPacketBuffer *buffer) override
uint8_t rx_header_buf_pos_
static constexpr uint8_t HEADER_PADDING
APIError write_protobuf_messages(ProtoWriteBuffer buffer, std::span< const MessageInfo > messages) override
static constexpr uint8_t ESPHOME_ALWAYS_INLINE varint8(uint8_t value)
static constexpr uint8_t ESPHOME_ALWAYS_INLINE varint16(uint16_t value)
static ProtoVarIntResult ESPHOME_ALWAYS_INLINE parse_non_empty(const uint8_t *buffer, uint32_t len)
Parse a varint from buffer.
static ProtoVarIntResult ESPHOME_ALWAYS_INLINE parse(const uint8_t *buffer, uint32_t len)
Parse a varint from buffer (safe for empty buffers).
APIBuffer * get_buffer() const