ESPHome 2026.1.5
Loading...
Searching...
No Matches
ota_esphome.cpp
Go to the documentation of this file.
1#include "ota_esphome.h"
2#ifdef USE_OTA
3#ifdef USE_OTA_PASSWORD
5#endif
14#include "esphome/core/hal.h"
16#include "esphome/core/log.h"
17#include "esphome/core/util.h"
18
19#include <cerrno>
20#include <cstdio>
21
22namespace esphome {
23
24static const char *const TAG = "esphome.ota";
25static constexpr uint16_t OTA_BLOCK_SIZE = 8192;
26static constexpr size_t OTA_BUFFER_SIZE = 1024; // buffer size for OTA data transfer
27static constexpr uint32_t OTA_SOCKET_TIMEOUT_HANDSHAKE = 20000; // milliseconds for initial handshake
28static constexpr uint32_t OTA_SOCKET_TIMEOUT_DATA = 90000; // milliseconds for data transfer
29
31 this->server_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0); // monitored for incoming connections
32 if (this->server_ == nullptr) {
33 this->log_socket_error_(LOG_STR("creation"));
34 this->mark_failed();
35 return;
36 }
37 int enable = 1;
38 int err = this->server_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
39 if (err != 0) {
40 this->log_socket_error_(LOG_STR("reuseaddr"));
41 // we can still continue
42 }
43 err = this->server_->setblocking(false);
44 if (err != 0) {
45 this->log_socket_error_(LOG_STR("non-blocking"));
46 this->mark_failed();
47 return;
48 }
49
50 struct sockaddr_storage server;
51
52 socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), this->port_);
53 if (sl == 0) {
54 this->log_socket_error_(LOG_STR("set sockaddr"));
55 this->mark_failed();
56 return;
57 }
58
59 err = this->server_->bind((struct sockaddr *) &server, sizeof(server));
60 if (err != 0) {
61 this->log_socket_error_(LOG_STR("bind"));
62 this->mark_failed();
63 return;
64 }
65
66 err = this->server_->listen(1); // Only one client at a time
67 if (err != 0) {
68 this->log_socket_error_(LOG_STR("listen"));
69 this->mark_failed();
70 return;
71 }
72}
73
75 ESP_LOGCONFIG(TAG,
76 "Over-The-Air updates:\n"
77 " Address: %s:%u\n"
78 " Version: %d",
79 network::get_use_address(), this->port_, USE_OTA_VERSION);
80#ifdef USE_OTA_PASSWORD
81 if (!this->password_.empty()) {
82 ESP_LOGCONFIG(TAG, " Password configured");
83 }
84#endif
85}
86
88 // Skip handle_handshake_() call if no client connected and no incoming connections
89 // This optimization reduces idle loop overhead when OTA is not active
90 // Note: No need to check server_ for null as the component is marked failed in setup()
91 // if server_ creation fails
92 if (this->client_ != nullptr || this->server_->ready()) {
93 this->handle_handshake_();
94 }
95}
96
97static const uint8_t FEATURE_SUPPORTS_COMPRESSION = 0x01;
98static const uint8_t FEATURE_SUPPORTS_SHA256_AUTH = 0x02;
99
106
107 if (this->client_ == nullptr) {
108 // We already checked server_->ready() in loop(), so we can accept directly
109 struct sockaddr_storage source_addr;
110 socklen_t addr_len = sizeof(source_addr);
111 int enable = 1;
112
113 this->client_ = this->server_->accept_loop_monitored((struct sockaddr *) &source_addr, &addr_len);
114 if (this->client_ == nullptr)
115 return;
116 int err = this->client_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(int));
117 if (err != 0) {
118 this->log_socket_error_(LOG_STR("nodelay"));
119 this->cleanup_connection_();
120 return;
121 }
122 err = this->client_->setblocking(false);
123 if (err != 0) {
124 this->log_socket_error_(LOG_STR("non-blocking"));
125 this->cleanup_connection_();
126 return;
127 }
128 this->log_start_(LOG_STR("handshake"));
130 this->handshake_buf_pos_ = 0; // Reset handshake buffer position
132 }
133
134 // Check for handshake timeout
135 uint32_t now = App.get_loop_component_start_time();
136 if (now - this->client_connect_time_ > OTA_SOCKET_TIMEOUT_HANDSHAKE) {
137 ESP_LOGW(TAG, "Handshake timeout");
138 this->cleanup_connection_();
139 return;
140 }
141
142 switch (this->ota_state_) {
144 // Try to read remaining magic bytes (5 total)
145 if (!this->try_read_(5, LOG_STR("read magic"))) {
146 return;
147 }
148
149 // Validate magic bytes
150 static const uint8_t MAGIC_BYTES[5] = {0x6C, 0x26, 0xF7, 0x5C, 0x45};
151 if (memcmp(this->handshake_buf_, MAGIC_BYTES, 5) != 0) {
152 ESP_LOGW(TAG, "Magic bytes mismatch! 0x%02X-0x%02X-0x%02X-0x%02X-0x%02X", this->handshake_buf_[0],
153 this->handshake_buf_[1], this->handshake_buf_[2], this->handshake_buf_[3], this->handshake_buf_[4]);
155 return;
156 }
157
158 // Magic bytes valid, move to next state
161 this->handshake_buf_[1] = USE_OTA_VERSION;
162 [[fallthrough]];
163 }
164
165 case OTAState::MAGIC_ACK: {
166 // Send OK and version - 2 bytes
167 if (!this->try_write_(2, LOG_STR("ack magic"))) {
168 return;
169 }
170 // All bytes sent, create backend and move to next state
173 [[fallthrough]];
174 }
175
177 // Read features - 1 byte
178 if (!this->try_read_(1, LOG_STR("read feature"))) {
179 return;
180 }
181 this->ota_features_ = this->handshake_buf_[0];
182 ESP_LOGV(TAG, "Features: 0x%02X", this->ota_features_);
184 this->handshake_buf_[0] =
185 ((this->ota_features_ & FEATURE_SUPPORTS_COMPRESSION) != 0 && this->backend_->supports_compression())
188 [[fallthrough]];
189 }
190
192 // Acknowledge header - 1 byte
193 if (!this->try_write_(1, LOG_STR("ack feature"))) {
194 return;
195 }
196#ifdef USE_OTA_PASSWORD
197 // If password is set, move to auth phase
198 if (!this->password_.empty()) {
200 } else
201#endif
202 {
203 // No password, move directly to data phase
205 }
206 [[fallthrough]];
207 }
208
209#ifdef USE_OTA_PASSWORD
210 case OTAState::AUTH_SEND: {
211 // Non-blocking authentication send
212 if (!this->handle_auth_send_()) {
213 return;
214 }
216 [[fallthrough]];
217 }
218
219 case OTAState::AUTH_READ: {
220 // Non-blocking authentication read & verify
221 if (!this->handle_auth_read_()) {
222 return;
223 }
225 [[fallthrough]];
226 }
227#endif
228
229 case OTAState::DATA:
230 this->handle_data_();
231 return;
232
233 default:
234 break;
235 }
236}
237
247 bool update_started = false;
248 size_t total = 0;
249 uint32_t last_progress = 0;
250 uint8_t buf[OTA_BUFFER_SIZE];
251 char *sbuf = reinterpret_cast<char *>(buf);
252 size_t ota_size;
253#if USE_OTA_VERSION == 2
254 size_t size_acknowledged = 0;
255#endif
256
257 // Acknowledge auth OK - 1 byte
259
260 // Read size, 4 bytes MSB first
261 if (!this->readall_(buf, 4)) {
262 this->log_read_error_(LOG_STR("size"));
263 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
264 }
265 ota_size = (static_cast<size_t>(buf[0]) << 24) | (static_cast<size_t>(buf[1]) << 16) |
266 (static_cast<size_t>(buf[2]) << 8) | buf[3];
267 ESP_LOGV(TAG, "Size is %u bytes", ota_size);
268
269 // Now that we've passed authentication and are actually
270 // starting the update, set the warning status and notify
271 // listeners. This ensures that port scanners do not
272 // accidentally trigger the update process.
273 this->log_start_(LOG_STR("update"));
274 this->status_set_warning();
275#ifdef USE_OTA_STATE_LISTENER
276 this->notify_state_(ota::OTA_STARTED, 0.0f, 0);
277#endif
278
279 // This will block for a few seconds as it locks flash
280 error_code = this->backend_->begin(ota_size);
281 if (error_code != ota::OTA_RESPONSE_OK)
282 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
283 update_started = true;
284
285 // Acknowledge prepare OK - 1 byte
287
288 // Read binary MD5, 32 bytes
289 if (!this->readall_(buf, 32)) {
290 this->log_read_error_(LOG_STR("MD5 checksum"));
291 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
292 }
293 sbuf[32] = '\0';
294 ESP_LOGV(TAG, "Update: Binary MD5 is %s", sbuf);
295 this->backend_->set_update_md5(sbuf);
296
297 // Acknowledge MD5 OK - 1 byte
299
300 while (total < ota_size) {
301 // TODO: timeout check
302 size_t remaining = ota_size - total;
303 size_t requested = remaining < OTA_BUFFER_SIZE ? remaining : OTA_BUFFER_SIZE;
304 ssize_t read = this->client_->read(buf, requested);
305 if (read == -1) {
306 if (this->would_block_(errno)) {
308 continue;
309 }
310 ESP_LOGW(TAG, "Read err %d", errno);
311 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
312 } else if (read == 0) {
313 ESP_LOGW(TAG, "Remote closed");
314 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
315 }
316
317 error_code = this->backend_->write(buf, read);
318 if (error_code != ota::OTA_RESPONSE_OK) {
319 ESP_LOGW(TAG, "Flash write err %d", error_code);
320 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
321 }
322 total += read;
323#if USE_OTA_VERSION == 2
324 while (size_acknowledged + OTA_BLOCK_SIZE <= total || (total == ota_size && size_acknowledged < ota_size)) {
326 size_acknowledged += OTA_BLOCK_SIZE;
327 }
328#endif
329
330 uint32_t now = millis();
331 if (now - last_progress > 1000) {
332 last_progress = now;
333 float percentage = (total * 100.0f) / ota_size;
334 ESP_LOGD(TAG, "Progress: %0.1f%%", percentage);
335#ifdef USE_OTA_STATE_LISTENER
336 this->notify_state_(ota::OTA_IN_PROGRESS, percentage, 0);
337#endif
338 // feed watchdog and give other tasks a chance to run
340 }
341 }
342
343 // Acknowledge receive OK - 1 byte
345
346 error_code = this->backend_->end();
347 if (error_code != ota::OTA_RESPONSE_OK) {
348 ESP_LOGW(TAG, "End update err %d", error_code);
349 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
350 }
351
352 // Acknowledge Update end OK - 1 byte
354
355 // Read ACK
356 if (!this->readall_(buf, 1) || buf[0] != ota::OTA_RESPONSE_OK) {
357 this->log_read_error_(LOG_STR("ack"));
358 // do not go to error, this is not fatal
359 }
360
361 this->cleanup_connection_();
362 delay(10);
363 ESP_LOGI(TAG, "Update complete");
364 this->status_clear_warning();
365#ifdef USE_OTA_STATE_LISTENER
366 this->notify_state_(ota::OTA_COMPLETED, 100.0f, 0);
367#endif
368 delay(100); // NOLINT
370
371error:
372 this->write_byte_(static_cast<uint8_t>(error_code));
373
374 // Abort backend before cleanup - cleanup_connection_() destroys the backend
375 if (this->backend_ != nullptr && update_started) {
376 this->backend_->abort();
377 }
378
379 this->cleanup_connection_();
380
381 this->status_momentary_error("err", 5000);
382#ifdef USE_OTA_STATE_LISTENER
383 this->notify_state_(ota::OTA_ERROR, 0.0f, static_cast<uint8_t>(error_code));
384#endif
385}
386
387bool ESPHomeOTAComponent::readall_(uint8_t *buf, size_t len) {
388 uint32_t start = millis();
389 uint32_t at = 0;
390 while (len - at > 0) {
391 uint32_t now = millis();
392 if (now - start > OTA_SOCKET_TIMEOUT_DATA) {
393 ESP_LOGW(TAG, "Timeout reading %zu bytes", len);
394 return false;
395 }
396
397 ssize_t read = this->client_->read(buf + at, len - at);
398 if (read == -1) {
399 if (!this->would_block_(errno)) {
400 ESP_LOGW(TAG, "Read err %zu bytes, errno %d", len, errno);
401 return false;
402 }
403 } else if (read == 0) {
404 ESP_LOGW(TAG, "Remote closed");
405 return false;
406 } else {
407 at += read;
408 }
410 }
411
412 return true;
413}
414bool ESPHomeOTAComponent::writeall_(const uint8_t *buf, size_t len) {
415 uint32_t start = millis();
416 uint32_t at = 0;
417 while (len - at > 0) {
418 uint32_t now = millis();
419 if (now - start > OTA_SOCKET_TIMEOUT_DATA) {
420 ESP_LOGW(TAG, "Timeout writing %zu bytes", len);
421 return false;
422 }
423
424 ssize_t written = this->client_->write(buf + at, len - at);
425 if (written == -1) {
426 if (!this->would_block_(errno)) {
427 ESP_LOGW(TAG, "Write err %zu bytes, errno %d", len, errno);
428 return false;
429 }
430 } else {
431 at += written;
432 }
434 }
435 return true;
436}
437
439uint16_t ESPHomeOTAComponent::get_port() const { return this->port_; }
440void ESPHomeOTAComponent::set_port(uint16_t port) { this->port_ = port; }
441
442void ESPHomeOTAComponent::log_socket_error_(const LogString *msg) {
443 ESP_LOGW(TAG, "Socket %s: errno %d", LOG_STR_ARG(msg), errno);
444}
445
446void ESPHomeOTAComponent::log_read_error_(const LogString *what) { ESP_LOGW(TAG, "Read %s failed", LOG_STR_ARG(what)); }
447
448void ESPHomeOTAComponent::log_start_(const LogString *phase) {
449 char peername[socket::SOCKADDR_STR_LEN];
450 this->client_->getpeername_to(peername);
451 ESP_LOGD(TAG, "Starting %s from %s", LOG_STR_ARG(phase), peername);
452}
453
454void ESPHomeOTAComponent::log_remote_closed_(const LogString *during) {
455 ESP_LOGW(TAG, "Remote closed at %s", LOG_STR_ARG(during));
456}
457
458bool ESPHomeOTAComponent::handle_read_error_(ssize_t read, const LogString *desc) {
459 if (read == -1 && this->would_block_(errno)) {
460 return false; // No data yet, try again next loop
461 }
462
463 if (read <= 0) {
464 read == 0 ? this->log_remote_closed_(desc) : this->log_socket_error_(desc);
465 this->cleanup_connection_();
466 return false;
467 }
468 return true;
469}
470
471bool ESPHomeOTAComponent::handle_write_error_(ssize_t written, const LogString *desc) {
472 if (written == -1) {
473 if (this->would_block_(errno)) {
474 return false; // Try again next loop
475 }
476 this->log_socket_error_(desc);
477 this->cleanup_connection_();
478 return false;
479 }
480 return true;
481}
482
483bool ESPHomeOTAComponent::try_read_(size_t to_read, const LogString *desc) {
484 // Read bytes into handshake buffer, starting at handshake_buf_pos_
485 size_t bytes_to_read = to_read - this->handshake_buf_pos_;
486 ssize_t read = this->client_->read(this->handshake_buf_ + this->handshake_buf_pos_, bytes_to_read);
487
488 if (!this->handle_read_error_(read, desc)) {
489 return false;
490 }
491
492 this->handshake_buf_pos_ += read;
493 // Return true only if we have all the requested bytes
494 return this->handshake_buf_pos_ >= to_read;
495}
496
497bool ESPHomeOTAComponent::try_write_(size_t to_write, const LogString *desc) {
498 // Write bytes from handshake buffer, starting at handshake_buf_pos_
499 size_t bytes_to_write = to_write - this->handshake_buf_pos_;
500 ssize_t written = this->client_->write(this->handshake_buf_ + this->handshake_buf_pos_, bytes_to_write);
501
502 if (!this->handle_write_error_(written, desc)) {
503 return false;
504 }
505
506 this->handshake_buf_pos_ += written;
507 // Return true only if we have written all the requested bytes
508 return this->handshake_buf_pos_ >= to_write;
509}
510
512 this->client_->close();
513 this->client_ = nullptr;
514 this->client_connect_time_ = 0;
515 this->handshake_buf_pos_ = 0;
517 this->ota_features_ = 0;
518 this->backend_ = nullptr;
519#ifdef USE_OTA_PASSWORD
520 this->cleanup_auth_();
521#endif
522}
523
528
529#ifdef USE_OTA_PASSWORD
530void ESPHomeOTAComponent::log_auth_warning_(const LogString *msg) { ESP_LOGW(TAG, "Auth: %s", LOG_STR_ARG(msg)); }
531
533 bool client_supports_sha256 = (this->ota_features_ & FEATURE_SUPPORTS_SHA256_AUTH) != 0;
534
535 // Require SHA256
536 if (!client_supports_sha256) {
537 this->log_auth_warning_(LOG_STR("SHA256 required"));
539 return false;
540 }
542 return true;
543}
544
546 // Initialize auth buffer if not already done
547 if (!this->auth_buf_) {
548 // Select auth type based on client capabilities and configuration
549 if (!this->select_auth_type_()) {
550 return false;
551 }
552
553 // Generate nonce - hasher must be created and used in same stack frame
554 // CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION REQUIREMENTS:
555 // 1. Hash objects must NEVER be passed to another function (different stack frame)
556 // 2. NO Variable Length Arrays (VLAs) - they corrupt the stack with hardware DMA
557 // 3. All hash operations (init/add/calculate) must happen in the SAME function where object is created
558 // Violating these causes truncated hash output (20 bytes instead of 32) or memory corruption.
559 //
560 // Buffer layout after AUTH_READ completes:
561 // [0]: auth_type (1 byte)
562 // [1...hex_size]: nonce (hex_size bytes) - our random nonce sent in AUTH_SEND
563 // [1+hex_size...1+2*hex_size-1]: cnonce (hex_size bytes) - client's nonce
564 // [1+2*hex_size...1+3*hex_size-1]: response (hex_size bytes) - client's hash
565
566 // CRITICAL ESP32-S2/S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame
567 // (no passing to other functions). All hash operations must happen in this function.
568 sha256::SHA256 hasher;
569
570 const size_t hex_size = hasher.get_size() * 2;
571 const size_t nonce_len = hasher.get_size() / 4;
572 const size_t auth_buf_size = 1 + 3 * hex_size;
573 this->auth_buf_ = std::make_unique<uint8_t[]>(auth_buf_size);
574 this->auth_buf_pos_ = 0;
575
576 char *buf = reinterpret_cast<char *>(this->auth_buf_.get() + 1);
577 if (!random_bytes(reinterpret_cast<uint8_t *>(buf), nonce_len)) {
578 this->log_auth_warning_(LOG_STR("Random failed"));
580 return false;
581 }
582
583 hasher.init();
584 hasher.add(buf, nonce_len);
585 hasher.calculate();
586 this->auth_buf_[0] = this->auth_type_;
587 hasher.get_hex(buf);
588
589 ESP_LOGV(TAG, "Auth: Nonce is %.*s", hex_size, buf);
590 }
591
592 // Try to write auth_type + nonce
593 constexpr size_t hex_size = SHA256_HEX_SIZE;
594 const size_t to_write = 1 + hex_size;
595 size_t remaining = to_write - this->auth_buf_pos_;
596
597 ssize_t written = this->client_->write(this->auth_buf_.get() + this->auth_buf_pos_, remaining);
598 if (!this->handle_write_error_(written, LOG_STR("ack auth"))) {
599 return false;
600 }
601
602 this->auth_buf_pos_ += written;
603
604 // Check if we still have more to write
605 if (this->auth_buf_pos_ < to_write) {
606 return false; // More to write, try again next loop
607 }
608
609 // All written, prepare for reading phase
610 this->auth_buf_pos_ = 0;
611 return true;
612}
613
615 constexpr size_t hex_size = SHA256_HEX_SIZE;
616 const size_t to_read = hex_size * 2; // CNonce + Response
617
618 // Try to read remaining bytes (CNonce + Response)
619 // We read cnonce+response starting at offset 1+hex_size (after auth_type and our nonce)
620 size_t cnonce_offset = 1 + hex_size; // Offset where cnonce should be stored in buffer
621 size_t remaining = to_read - this->auth_buf_pos_;
622 ssize_t read = this->client_->read(this->auth_buf_.get() + cnonce_offset + this->auth_buf_pos_, remaining);
623
624 if (!this->handle_read_error_(read, LOG_STR("read auth"))) {
625 return false;
626 }
627
628 this->auth_buf_pos_ += read;
629
630 // Check if we still need more data
631 if (this->auth_buf_pos_ < to_read) {
632 return false; // More to read, try again next loop
633 }
634
635 // We have all the data, verify it
636 const char *nonce = reinterpret_cast<char *>(this->auth_buf_.get() + 1);
637 const char *cnonce = nonce + hex_size;
638 const char *response = cnonce + hex_size;
639
640 // CRITICAL ESP32-S2/S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame
641 // (no passing to other functions). All hash operations must happen in this function.
642 sha256::SHA256 hasher;
643
644 hasher.init();
645 hasher.add(this->password_.c_str(), this->password_.length());
646 hasher.add(nonce, hex_size * 2); // Add both nonce and cnonce (contiguous in buffer)
647 hasher.calculate();
648
649 ESP_LOGV(TAG, "Auth: CNonce is %.*s", hex_size, cnonce);
650#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
651 char computed_hash[SHA256_HEX_SIZE + 1]; // Buffer for hex-encoded hash (max expected length + null terminator)
652 hasher.get_hex(computed_hash);
653 ESP_LOGV(TAG, "Auth: Result is %.*s", hex_size, computed_hash);
654#endif
655 ESP_LOGV(TAG, "Auth: Response is %.*s", hex_size, response);
656
657 // Compare response
658 bool matches = hasher.equals_hex(response);
659
660 if (!matches) {
661 this->log_auth_warning_(LOG_STR("Password mismatch"));
663 return false;
664 }
665
666 // Authentication successful - clean up auth state
667 this->cleanup_auth_();
668
669 return true;
670}
671
673 this->auth_buf_ = nullptr;
674 this->auth_buf_pos_ = 0;
675 this->auth_type_ = 0;
676}
677#endif // USE_OTA_PASSWORD
678
679} // namespace esphome
680#endif
void feed_wdt(uint32_t time=0)
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
virtual void mark_failed()
Mark this component as failed.
void status_momentary_error(const char *name, uint32_t length=5000)
Set error status flag and automatically clear it after a timeout.
void status_set_warning(const char *message=nullptr)
void status_clear_warning()
bool would_block_(int error_code) const
Definition ota_esphome.h:61
std::unique_ptr< ota::OTABackend > backend_
Definition ota_esphome.h:88
static constexpr size_t SHA256_HEX_SIZE
Definition ota_esphome.h:47
bool writeall_(const uint8_t *buf, size_t len)
bool try_read_(size_t to_read, const LogString *desc)
bool try_write_(size_t to_write, const LogString *desc)
std::unique_ptr< uint8_t[]> auth_buf_
Definition ota_esphome.h:83
bool handle_write_error_(ssize_t written, const LogString *desc)
void log_auth_warning_(const LogString *msg)
float get_setup_priority() const override
void send_error_and_cleanup_(ota::OTAResponseTypes error)
Definition ota_esphome.h:74
bool handle_read_error_(ssize_t read, const LogString *desc)
void log_read_error_(const LogString *what)
bool readall_(uint8_t *buf, size_t len)
void set_port(uint16_t port)
Manually set the port OTA should listen on.
bool write_byte_(uint8_t byte)
Definition ota_esphome.h:56
std::unique_ptr< socket::Socket > server_
Definition ota_esphome.h:86
void transition_ota_state_(OTAState next_state)
Definition ota_esphome.h:64
void log_remote_closed_(const LogString *during)
std::unique_ptr< socket::Socket > client_
Definition ota_esphome.h:87
void log_start_(const LogString *phase)
void log_socket_error_(const LogString *msg)
void get_hex(char *output)
Retrieve the hash as hex characters. Output buffer must hold get_size() * 2 + 1 bytes.
Definition hash_base.h:29
bool equals_hex(const char *expected)
Compare the hash against a provided hex-encoded hash.
Definition hash_base.h:35
void notify_state_(OTAState state, float progress, uint8_t error)
SHA256 hash implementation.
Definition sha256.h:38
void calculate() override
Definition sha256.cpp:56
size_t get_size() const override
Get the size of the hash in bytes (32 for SHA256)
Definition sha256.h:51
void add(const uint8_t *data, size_t len) override
Definition sha256.cpp:54
void init() override
Definition sha256.cpp:49
uint16_t addr_len
uint32_t socklen_t
Definition headers.h:97
__int64 ssize_t
Definition httplib.h:178
const char * get_use_address()
Get the active network hostname.
Definition util.cpp:88
std::unique_ptr< ota::OTABackend > make_ota_backend()
@ OTA_RESPONSE_UPDATE_PREPARE_OK
Definition ota_backend.h:21
@ OTA_RESPONSE_SUPPORTS_COMPRESSION
Definition ota_backend.h:25
@ OTA_RESPONSE_BIN_MD5_OK
Definition ota_backend.h:22
@ OTA_RESPONSE_UPDATE_END_OK
Definition ota_backend.h:24
@ OTA_RESPONSE_RECEIVE_OK
Definition ota_backend.h:23
@ OTA_RESPONSE_CHUNK_OK
Definition ota_backend.h:26
@ OTA_RESPONSE_ERROR_AUTH_INVALID
Definition ota_backend.h:30
@ OTA_RESPONSE_ERROR_UNKNOWN
Definition ota_backend.h:41
@ OTA_RESPONSE_REQUEST_SHA256_AUTH
Definition ota_backend.h:17
@ OTA_RESPONSE_ERROR_MAGIC
Definition ota_backend.h:28
@ OTA_RESPONSE_HEADER_OK
Definition ota_backend.h:19
const float AFTER_WIFI
For components that should be initialized after WiFi is connected.
Definition component.cpp:88
std::unique_ptr< Socket > socket_ip_loop_monitored(int type, int protocol)
Definition socket.cpp:102
socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port)
Set a sockaddr to the any address and specified port for the IP version used by socket_ip().
Definition socket.cpp:149
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
bool random_bytes(uint8_t *data, size_t len)
Generate len number of random bytes.
Definition helpers.cpp:18
std::string size_t len
Definition helpers.h:595
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:26
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:25
Application App
Global storage of Application pointer - only one Application can exist.