ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
ota_esphome_inflate_session.cpp
Go to the documentation of this file.
1#include "ota_esphome.h"
2#ifdef USE_OTA
3#ifdef USE_OTA_DEFLATE
6#include "esphome/core/log.h"
7
8namespace esphome {
9
10ESPHOME_LOG_TAG(TAG, "esphome.ota");
11
12// The window doubles as the output buffer; flushed bytes stay as back
13// reference history for the next windowful.
15 const size_t produced = session.dest - session.window;
16 const size_t pending = produced - session.flushed;
17 if (pending != 0) {
18 if (pending > session.image_size - session.written) {
19 ESP_LOGW(TAG, "Inflate overrun");
21 }
22 ota::OTAResponseTypes result = this->write_flash_(session.window + session.flushed, pending);
23 if (result != ota::OTA_RESPONSE_OK)
24 return result;
25 session.flushed = produced;
26 session.written += pending;
27 // A compressible region yields many windows per socket read
28 App.feed_wdt();
29 }
30 // Even with nothing new written: a block boundary can fall inside a header
31 this->ack_written_(*session.xfer);
33}
34
36 InflateSession &session = *this->inflate_;
37 session.self = this;
38 session.xfer = &xfer;
39 session.in = in;
40 session.image_size = image_size;
41 session.written = 0;
44 // Where the ack must follow the write, flush and ack before waiting for
45 // input, or the client waits for an ack while the decoder waits for data
46 session.source_read_cb = [](OtaInflateState *d) -> int {
47 auto *s = static_cast<InflateSession *>(d);
48 if (ACK_AFTER_WRITE) {
49 s->error = s->self->inflate_flush_(*s);
50 if (s->error != ota::OTA_RESPONSE_OK)
51 return -1;
52 }
53 // More input than announced; reported by the size check below
54 if (s->xfer->total >= s->xfer->ota_size)
55 return -1;
56 ssize_t read = s->self->receive_data_(s->in, *s->xfer);
57 if (read <= 0) {
58 // Already logged by receive_data_
60 return -1;
61 }
62 d->source = s->in + 1;
63 d->source_limit = s->in + read;
64 return s->in[0];
65 };
66
67 int res;
68 do {
69 // The ring index wrapped to 0 exactly when the window filled
70 session.dest = session.window;
71 session.dest_limit = session.window + OTA_INFLATE_WINDOW_SIZE;
72 session.flushed = 0;
73 res = ota_inflate(&session);
74 // A stored block keeps emitting zeros after a failed read, hence eof
75 if (res < 0 || session.eof)
76 break;
77 session.error = this->inflate_flush_(session);
78 } while (res != OTA_INFLATE_DONE && session.error == ota::OTA_RESPONSE_OK);
79
80 // Transport and flash failures are logged where they happen
81 if (session.error != ota::OTA_RESPONSE_OK)
82 return session.error;
83 if (res != OTA_INFLATE_DONE || session.written != image_size || xfer.total != xfer.ota_size) {
84 ESP_LOGW(TAG, "Inflate err %d, %zu of %zu B from %zu of %zu", res, session.written, image_size, xfer.total,
85 xfer.ota_size);
87 }
88 ESP_LOGD(TAG, "Inflated %zu bytes from %zu", session.written, xfer.total);
90}
91
92} // namespace esphome
93#endif // USE_OTA_DEFLATE
94#endif // USE_OTA
void feed_wdt()
Feed the task watchdog.
ssize_t receive_data_(uint8_t *buf, DataTransfer &xfer)
ota::OTAResponseTypes write_flash_(uint8_t *data, size_t len)
static constexpr bool ACK_AFTER_WRITE
static constexpr size_t OTA_INFLATE_WINDOW_SIZE
void ack_written_(DataTransfer &xfer)
RAMUniquePtr< InflateSession > inflate_
ota::OTAResponseTypes inflate_data_(uint8_t *in, size_t image_size, DataTransfer &xfer)
ota::OTAResponseTypes inflate_flush_(InflateSession &session)
__int64 ssize_t
Definition httplib.h:178
ESPHOME_LOG_TAG(TAG, CRASH_LOG_TAG)
@ OTA_RESPONSE_ERROR_UNKNOWN
Definition ota_backend.h:55
Application App
Global storage of Application pointer - only one Application can exist.
void ota_inflate_init(TINF_DATA *d, unsigned char *dict, unsigned int dict_len)
int ota_inflate(TINF_DATA *d)
@ OTA_INFLATE_DONE
unsigned char * dest
int(* source_read_cb)(struct OtaInflateState *d)
unsigned char * dest_limit
uint8_t window[OTA_INFLATE_WINDOW_SIZE]