ESPHome 2026.3.0
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#include <sys/time.h>
22
23namespace esphome {
24
25static const char *const TAG = "esphome.ota";
26static constexpr uint16_t OTA_BLOCK_SIZE = 8192;
27static constexpr size_t OTA_BUFFER_SIZE = 1024; // buffer size for OTA data transfer
28static constexpr uint32_t OTA_SOCKET_TIMEOUT_HANDSHAKE = 20000; // milliseconds for initial handshake
29static constexpr uint32_t OTA_SOCKET_TIMEOUT_DATA = 90000; // milliseconds for data transfer
30
32 this->server_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0).release(); // monitored for incoming connections
33 if (this->server_ == nullptr) {
34 this->server_failed_(LOG_STR("creation"));
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->server_failed_(LOG_STR("nonblocking"));
46 return;
47 }
48
49 struct sockaddr_storage server;
50
51 socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), this->port_);
52 if (sl == 0) {
53 this->server_failed_(LOG_STR("set sockaddr"));
54 return;
55 }
56
57 err = this->server_->bind((struct sockaddr *) &server, sizeof(server));
58 if (err != 0) {
59 this->server_failed_(LOG_STR("bind"));
60 return;
61 }
62
63 err = this->server_->listen(1); // Only one client at a time
64 if (err != 0) {
65 this->server_failed_(LOG_STR("listen"));
66 return;
67 }
68}
69
71 ESP_LOGCONFIG(TAG,
72 "Over-The-Air updates:\n"
73 " Address: %s:%u\n"
74 " Version: %d",
75 network::get_use_address(), this->port_, USE_OTA_VERSION);
76#ifdef USE_OTA_PASSWORD
77 if (!this->password_.empty()) {
78 ESP_LOGCONFIG(TAG, " Password configured");
79 }
80#endif
81}
82
84 // Skip handle_handshake_() call if no client connected and no incoming connections
85 // This optimization reduces idle loop overhead when OTA is not active
86 // Note: No need to check server_ for null as the component is marked failed in setup()
87 // if server_ creation fails
88 if (this->client_ != nullptr || this->server_->ready()) {
89 this->handle_handshake_();
90 }
91}
92
93static const uint8_t FEATURE_SUPPORTS_COMPRESSION = 0x01;
94static const uint8_t FEATURE_SUPPORTS_SHA256_AUTH = 0x02;
95
102
103 if (this->client_ == nullptr) {
104 // We already checked server_->ready() in loop(), so we can accept directly
105 struct sockaddr_storage source_addr;
106 socklen_t addr_len = sizeof(source_addr);
107 int enable = 1;
108
109 this->client_ = this->server_->accept_loop_monitored((struct sockaddr *) &source_addr, &addr_len);
110 if (this->client_ == nullptr)
111 return;
112 int err = this->client_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(int));
113 if (err != 0) {
114 this->log_socket_error_(LOG_STR("nodelay"));
115 this->cleanup_connection_();
116 return;
117 }
118 err = this->client_->setblocking(false);
119 if (err != 0) {
120 this->log_socket_error_(LOG_STR("non-blocking"));
121 this->cleanup_connection_();
122 return;
123 }
124 this->log_start_(LOG_STR("handshake"));
126 this->handshake_buf_pos_ = 0; // Reset handshake buffer position
128 }
129
130 // Check for handshake timeout
132 if (now - this->client_connect_time_ > OTA_SOCKET_TIMEOUT_HANDSHAKE) {
133 ESP_LOGW(TAG, "Handshake timeout");
134 this->cleanup_connection_();
135 return;
136 }
137
138 switch (this->ota_state_) {
140 // Try to read remaining magic bytes (5 total)
141 if (!this->try_read_(5, LOG_STR("read magic"))) {
142 return;
143 }
144
145 // Validate magic bytes
146 static const uint8_t MAGIC_BYTES[5] = {0x6C, 0x26, 0xF7, 0x5C, 0x45};
147 if (memcmp(this->handshake_buf_, MAGIC_BYTES, 5) != 0) {
148 ESP_LOGW(TAG, "Magic bytes mismatch! 0x%02X-0x%02X-0x%02X-0x%02X-0x%02X", this->handshake_buf_[0],
149 this->handshake_buf_[1], this->handshake_buf_[2], this->handshake_buf_[3], this->handshake_buf_[4]);
151 return;
152 }
153
154 // Magic bytes valid, move to next state
157 this->handshake_buf_[1] = USE_OTA_VERSION;
158 [[fallthrough]];
159 }
160
161 case OTAState::MAGIC_ACK: {
162 // Send OK and version - 2 bytes
163 if (!this->try_write_(2, LOG_STR("ack magic"))) {
164 return;
165 }
166 // All bytes sent, create backend and move to next state
169 [[fallthrough]];
170 }
171
173 // Read features - 1 byte
174 if (!this->try_read_(1, LOG_STR("read feature"))) {
175 return;
176 }
177 this->ota_features_ = this->handshake_buf_[0];
178 ESP_LOGV(TAG, "Features: 0x%02X", this->ota_features_);
180 this->handshake_buf_[0] =
181 ((this->ota_features_ & FEATURE_SUPPORTS_COMPRESSION) != 0 && this->backend_->supports_compression())
184 [[fallthrough]];
185 }
186
188 // Acknowledge header - 1 byte
189 if (!this->try_write_(1, LOG_STR("ack feature"))) {
190 return;
191 }
192#ifdef USE_OTA_PASSWORD
193 // If password is set, move to auth phase
194 if (!this->password_.empty()) {
196 } else
197#endif
198 {
199 // No password, move directly to data phase
201 }
202 [[fallthrough]];
203 }
204
205#ifdef USE_OTA_PASSWORD
206 case OTAState::AUTH_SEND: {
207 // Non-blocking authentication send
208 if (!this->handle_auth_send_()) {
209 return;
210 }
212 [[fallthrough]];
213 }
214
215 case OTAState::AUTH_READ: {
216 // Non-blocking authentication read & verify
217 if (!this->handle_auth_read_()) {
218 return;
219 }
221 [[fallthrough]];
222 }
223#endif
224
225 case OTAState::DATA:
226 this->handle_data_();
227 return;
228
229 default:
230 break;
231 }
232}
233
268 bool update_started = false;
269 size_t total = 0;
270 uint32_t last_progress = 0;
271 uint8_t buf[OTA_BUFFER_SIZE];
272 char *sbuf = reinterpret_cast<char *>(buf);
273 size_t ota_size;
274#if USE_OTA_VERSION == 2
275 size_t size_acknowledged = 0;
276#endif
277
278 // Set socket timeouts and blocking mode (see strategy table above)
279 struct timeval tv;
280 tv.tv_sec = 2;
281 tv.tv_usec = 0;
282 this->client_->setsockopt(SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
283 this->client_->setsockopt(SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
284 this->client_->setblocking(true);
285
286 // Acknowledge auth OK - 1 byte
288
289 // Read size, 4 bytes MSB first
290 if (!this->readall_(buf, 4)) {
291 this->log_read_error_(LOG_STR("size"));
292 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
293 }
294 ota_size = (static_cast<size_t>(buf[0]) << 24) | (static_cast<size_t>(buf[1]) << 16) |
295 (static_cast<size_t>(buf[2]) << 8) | buf[3];
296 ESP_LOGV(TAG, "Size is %u bytes", ota_size);
297
298 // Now that we've passed authentication and are actually
299 // starting the update, set the warning status and notify
300 // listeners. This ensures that port scanners do not
301 // accidentally trigger the update process.
302 this->log_start_(LOG_STR("update"));
303 this->status_set_warning();
304#ifdef USE_OTA_STATE_LISTENER
305 this->notify_state_(ota::OTA_STARTED, 0.0f, 0);
306#endif
307
308 // This will block for a few seconds as it locks flash
309 error_code = this->backend_->begin(ota_size);
310 if (error_code != ota::OTA_RESPONSE_OK)
311 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
312 update_started = true;
313
314 // Acknowledge prepare OK - 1 byte
316
317 // Read binary MD5, 32 bytes
318 if (!this->readall_(buf, 32)) {
319 this->log_read_error_(LOG_STR("MD5 checksum"));
320 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
321 }
322 sbuf[32] = '\0';
323 ESP_LOGV(TAG, "Update: Binary MD5 is %s", sbuf);
324 this->backend_->set_update_md5(sbuf);
325
326 // Acknowledge MD5 OK - 1 byte
328
329 while (total < ota_size) {
330 // TODO: timeout check
331 size_t remaining = ota_size - total;
332 size_t requested = remaining < OTA_BUFFER_SIZE ? remaining : OTA_BUFFER_SIZE;
333 ssize_t read = this->client_->read(buf, requested);
334 if (read == -1) {
335 if (this->would_block_(errno)) {
336 // read() already waited up to SO_RCVTIMEO for data, just feed WDT
337 App.feed_wdt();
338 continue;
339 }
340 ESP_LOGW(TAG, "Read err %d", errno);
341 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
342 } else if (read == 0) {
343 ESP_LOGW(TAG, "Remote closed");
344 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
345 }
346
347 error_code = this->backend_->write(buf, read);
348 if (error_code != ota::OTA_RESPONSE_OK) {
349 ESP_LOGW(TAG, "Flash write err %d", error_code);
350 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
351 }
352 total += read;
353#if USE_OTA_VERSION == 2
354 while (size_acknowledged + OTA_BLOCK_SIZE <= total || (total == ota_size && size_acknowledged < ota_size)) {
356 size_acknowledged += OTA_BLOCK_SIZE;
357 }
358#endif
359
360 uint32_t now = millis();
361 if (now - last_progress > 1000) {
362 last_progress = now;
363 float percentage = (total * 100.0f) / ota_size;
364 ESP_LOGD(TAG, "Progress: %0.1f%%", percentage);
365#ifdef USE_OTA_STATE_LISTENER
366 this->notify_state_(ota::OTA_IN_PROGRESS, percentage, 0);
367#endif
368 // feed watchdog and give other tasks a chance to run
370 }
371 }
372
373 // Acknowledge receive OK - 1 byte
375
376 error_code = this->backend_->end();
377 if (error_code != ota::OTA_RESPONSE_OK) {
378 ESP_LOGW(TAG, "End update err %d", error_code);
379 goto error; // NOLINT(cppcoreguidelines-avoid-goto)
380 }
381
382 // Acknowledge Update end OK - 1 byte
384
385 // Read ACK
386 if (!this->readall_(buf, 1) || buf[0] != ota::OTA_RESPONSE_OK) {
387 this->log_read_error_(LOG_STR("ack"));
388 // do not go to error, this is not fatal
389 }
390
391 this->cleanup_connection_();
392 delay(10);
393 ESP_LOGI(TAG, "Update complete");
394 this->status_clear_warning();
395#ifdef USE_OTA_STATE_LISTENER
396 this->notify_state_(ota::OTA_COMPLETED, 100.0f, 0);
397#endif
398 delay(100); // NOLINT
400
401error:
402 this->write_byte_(static_cast<uint8_t>(error_code));
403
404 // Abort backend before cleanup - cleanup_connection_() destroys the backend
405 if (this->backend_ != nullptr && update_started) {
406 this->backend_->abort();
407 }
408
409 this->cleanup_connection_();
410
411 this->status_momentary_error("err", 5000);
412#ifdef USE_OTA_STATE_LISTENER
413 this->notify_state_(ota::OTA_ERROR, 0.0f, static_cast<uint8_t>(error_code));
414#endif
415}
416
417bool ESPHomeOTAComponent::readall_(uint8_t *buf, size_t len) {
418 uint32_t start = millis();
419 uint32_t at = 0;
420 while (len - at > 0) {
421 uint32_t now = millis();
422 if (now - start > OTA_SOCKET_TIMEOUT_DATA) {
423 ESP_LOGW(TAG, "Timeout reading %zu bytes", len);
424 return false;
425 }
426
427 ssize_t read = this->client_->read(buf + at, len - at);
428 if (read == -1) {
429 if (!this->would_block_(errno)) {
430 ESP_LOGW(TAG, "Read err %zu bytes, errno %d", len, errno);
431 return false;
432 }
433 } else if (read == 0) {
434 ESP_LOGW(TAG, "Remote closed");
435 return false;
436 } else {
437 at += read;
438 }
439 // read() already waited via SO_RCVTIMEO, just yield without 1ms stall
440 App.feed_wdt();
441 delay(0);
442 }
443
444 return true;
445}
446bool ESPHomeOTAComponent::writeall_(const uint8_t *buf, size_t len) {
447 uint32_t start = millis();
448 uint32_t at = 0;
449 while (len - at > 0) {
450 uint32_t now = millis();
451 if (now - start > OTA_SOCKET_TIMEOUT_DATA) {
452 ESP_LOGW(TAG, "Timeout writing %zu bytes", len);
453 return false;
454 }
455
456 ssize_t written = this->client_->write(buf + at, len - at);
457 if (written == -1) {
458 if (!this->would_block_(errno)) {
459 ESP_LOGW(TAG, "Write err %zu bytes, errno %d", len, errno);
460 return false;
461 }
462 // EWOULDBLOCK: on raw TCP writes never block, delay(1) prevents spinning
464 } else {
465 at += written;
466 // write() may block up to SO_SNDTIMEO on BSD/lwip sockets, feed WDT
467 App.feed_wdt();
468 }
469 }
470 return true;
471}
472
474uint16_t ESPHomeOTAComponent::get_port() const { return this->port_; }
475void ESPHomeOTAComponent::set_port(uint16_t port) { this->port_ = port; }
476
477void ESPHomeOTAComponent::log_socket_error_(const LogString *msg) {
478 ESP_LOGW(TAG, "Socket %s: errno %d", LOG_STR_ARG(msg), errno);
479}
480
481void ESPHomeOTAComponent::log_read_error_(const LogString *what) { ESP_LOGW(TAG, "Read %s failed", LOG_STR_ARG(what)); }
482
483void ESPHomeOTAComponent::log_start_(const LogString *phase) {
484 char peername[socket::SOCKADDR_STR_LEN];
485 this->client_->getpeername_to(peername);
486 ESP_LOGD(TAG, "Starting %s from %s", LOG_STR_ARG(phase), peername);
487}
488
489void ESPHomeOTAComponent::log_remote_closed_(const LogString *during) {
490 ESP_LOGW(TAG, "Remote closed at %s", LOG_STR_ARG(during));
491}
492
493void ESPHomeOTAComponent::server_failed_(const LogString *msg) {
494 this->log_socket_error_(msg);
495 // No explicit close() needed — listen sockets have no active connections on
496 // failure/shutdown. Destructor handles fd cleanup (close or abort per platform).
497 delete this->server_;
498 this->server_ = nullptr;
499 this->mark_failed();
500}
501
502bool ESPHomeOTAComponent::handle_read_error_(ssize_t read, const LogString *desc) {
503 if (read == -1 && this->would_block_(errno)) {
504 return false; // No data yet, try again next loop
505 }
506
507 if (read <= 0) {
508 read == 0 ? this->log_remote_closed_(desc) : this->log_socket_error_(desc);
509 this->cleanup_connection_();
510 return false;
511 }
512 return true;
513}
514
516 if (written == -1) {
517 if (this->would_block_(errno)) {
518 return false; // Try again next loop
519 }
520 this->log_socket_error_(desc);
521 this->cleanup_connection_();
522 return false;
523 }
524 return true;
525}
526
527bool ESPHomeOTAComponent::try_read_(size_t to_read, const LogString *desc) {
528 // Read bytes into handshake buffer, starting at handshake_buf_pos_
529 size_t bytes_to_read = to_read - this->handshake_buf_pos_;
530 ssize_t read = this->client_->read(this->handshake_buf_ + this->handshake_buf_pos_, bytes_to_read);
531
532 if (!this->handle_read_error_(read, desc)) {
533 return false;
534 }
535
536 this->handshake_buf_pos_ += read;
537 // Return true only if we have all the requested bytes
538 return this->handshake_buf_pos_ >= to_read;
539}
540
541bool ESPHomeOTAComponent::try_write_(size_t to_write, const LogString *desc) {
542 // Write bytes from handshake buffer, starting at handshake_buf_pos_
543 size_t bytes_to_write = to_write - this->handshake_buf_pos_;
544 ssize_t written = this->client_->write(this->handshake_buf_ + this->handshake_buf_pos_, bytes_to_write);
545
546 if (!this->handle_write_error_(written, desc)) {
547 return false;
548 }
549
550 this->handshake_buf_pos_ += written;
551 // Return true only if we have written all the requested bytes
552 return this->handshake_buf_pos_ >= to_write;
553}
554
556 this->client_->close();
557 this->client_ = nullptr;
558 this->client_connect_time_ = 0;
559 this->handshake_buf_pos_ = 0;
561 this->ota_features_ = 0;
562 this->backend_ = nullptr;
563#ifdef USE_OTA_PASSWORD
564 this->cleanup_auth_();
565#endif
566}
567
572
573#ifdef USE_OTA_PASSWORD
574void ESPHomeOTAComponent::log_auth_warning_(const LogString *msg) { ESP_LOGW(TAG, "Auth: %s", LOG_STR_ARG(msg)); }
575
577 bool client_supports_sha256 = (this->ota_features_ & FEATURE_SUPPORTS_SHA256_AUTH) != 0;
578
579 // Require SHA256
580 if (!client_supports_sha256) {
581 this->log_auth_warning_(LOG_STR("SHA256 required"));
583 return false;
584 }
586 return true;
587}
588
590 // Initialize auth buffer if not already done
591 if (!this->auth_buf_) {
592 // Select auth type based on client capabilities and configuration
593 if (!this->select_auth_type_()) {
594 return false;
595 }
596
597 // Generate nonce - hasher must be created and used in same stack frame
598 // CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION REQUIREMENTS:
599 // 1. Hash objects must NEVER be passed to another function (different stack frame)
600 // 2. NO Variable Length Arrays (VLAs) - they corrupt the stack with hardware DMA
601 // 3. All hash operations (init/add/calculate) must happen in the SAME function where object is created
602 // Violating these causes truncated hash output (20 bytes instead of 32) or memory corruption.
603 //
604 // Buffer layout after AUTH_READ completes:
605 // [0]: auth_type (1 byte)
606 // [1...hex_size]: nonce (hex_size bytes) - our random nonce sent in AUTH_SEND
607 // [1+hex_size...1+2*hex_size-1]: cnonce (hex_size bytes) - client's nonce
608 // [1+2*hex_size...1+3*hex_size-1]: response (hex_size bytes) - client's hash
609
610 // CRITICAL ESP32-S2/S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame
611 // (no passing to other functions). All hash operations must happen in this function.
612 sha256::SHA256 hasher;
613
614 const size_t hex_size = hasher.get_size() * 2;
615 const size_t nonce_len = hasher.get_size() / 4;
616 const size_t auth_buf_size = 1 + 3 * hex_size;
617 this->auth_buf_ = std::make_unique<uint8_t[]>(auth_buf_size);
618 this->auth_buf_pos_ = 0;
619
620 char *buf = reinterpret_cast<char *>(this->auth_buf_.get() + 1);
621 if (!random_bytes(reinterpret_cast<uint8_t *>(buf), nonce_len)) {
622 this->log_auth_warning_(LOG_STR("Random failed"));
624 return false;
625 }
626
627 hasher.init();
628 hasher.add(buf, nonce_len);
629 hasher.calculate();
630 this->auth_buf_[0] = this->auth_type_;
631 hasher.get_hex(buf);
632
633 ESP_LOGV(TAG, "Auth: Nonce is %.*s", hex_size, buf);
634 }
635
636 // Try to write auth_type + nonce
637 constexpr size_t hex_size = SHA256_HEX_SIZE;
638 const size_t to_write = 1 + hex_size;
639 size_t remaining = to_write - this->auth_buf_pos_;
640
641 ssize_t written = this->client_->write(this->auth_buf_.get() + this->auth_buf_pos_, remaining);
642 if (!this->handle_write_error_(written, LOG_STR("ack auth"))) {
643 return false;
644 }
645
646 this->auth_buf_pos_ += written;
647
648 // Check if we still have more to write
649 if (this->auth_buf_pos_ < to_write) {
650 return false; // More to write, try again next loop
651 }
652
653 // All written, prepare for reading phase
654 this->auth_buf_pos_ = 0;
655 return true;
656}
657
659 constexpr size_t hex_size = SHA256_HEX_SIZE;
660 const size_t to_read = hex_size * 2; // CNonce + Response
661
662 // Try to read remaining bytes (CNonce + Response)
663 // We read cnonce+response starting at offset 1+hex_size (after auth_type and our nonce)
664 size_t cnonce_offset = 1 + hex_size; // Offset where cnonce should be stored in buffer
665 size_t remaining = to_read - this->auth_buf_pos_;
666 ssize_t read = this->client_->read(this->auth_buf_.get() + cnonce_offset + this->auth_buf_pos_, remaining);
667
668 if (!this->handle_read_error_(read, LOG_STR("read auth"))) {
669 return false;
670 }
671
672 this->auth_buf_pos_ += read;
673
674 // Check if we still need more data
675 if (this->auth_buf_pos_ < to_read) {
676 return false; // More to read, try again next loop
677 }
678
679 // We have all the data, verify it
680 const char *nonce = reinterpret_cast<char *>(this->auth_buf_.get() + 1);
681 const char *cnonce = nonce + hex_size;
682 const char *response = cnonce + hex_size;
683
684 // CRITICAL ESP32-S2/S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame
685 // (no passing to other functions). All hash operations must happen in this function.
686 sha256::SHA256 hasher;
687
688 hasher.init();
689 hasher.add(this->password_.c_str(), this->password_.length());
690 hasher.add(nonce, hex_size * 2); // Add both nonce and cnonce (contiguous in buffer)
691 hasher.calculate();
692
693 ESP_LOGV(TAG, "Auth: CNonce is %.*s", hex_size, cnonce);
694#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
695 char computed_hash[SHA256_HEX_SIZE + 1]; // Buffer for hex-encoded hash (max expected length + null terminator)
696 hasher.get_hex(computed_hash);
697 ESP_LOGV(TAG, "Auth: Result is %.*s", hex_size, computed_hash);
698#endif
699 ESP_LOGV(TAG, "Auth: Response is %.*s", hex_size, response);
700
701 // Compare response
702 bool matches = hasher.equals_hex(response);
703
704 if (!matches) {
705 this->log_auth_warning_(LOG_STR("Password mismatch"));
707 return false;
708 }
709
710 // Authentication successful - clean up auth state
711 this->cleanup_auth_();
712
713 return true;
714}
715
717 this->auth_buf_ = nullptr;
718 this->auth_buf_pos_ = 0;
719 this->auth_type_ = 0;
720}
721#endif // USE_OTA_PASSWORD
722
723} // namespace esphome
724#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.
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()
Definition component.h:254
bool would_block_(int error_code) const
Definition ota_esphome.h:61
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)
ota::OTABackendPtr backend_
Definition ota_esphome.h:89
bool try_write_(size_t to_write, const LogString *desc)
std::unique_ptr< uint8_t[]> auth_buf_
Definition ota_esphome.h:84
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:75
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
void server_failed_(const LogString *msg)
void transition_ota_state_(OTAState next_state)
Definition ota_esphome.h:64
socket::ListenSocket * server_
Definition ota_esphome.h:87
void log_remote_closed_(const LogString *during)
std::unique_ptr< socket::Socket > client_
Definition ota_esphome.h:88
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
int bind(const struct sockaddr *addr, socklen_t addrlen)
int setsockopt(int level, int optname, const void *optval, socklen_t optlen)
std::unique_ptr< BSDSocketImpl > accept_loop_monitored(struct sockaddr *addr, socklen_t *addrlen)
uint16_t addr_len
uint32_t socklen_t
Definition headers.h:99
__int64 ssize_t
Definition httplib.h:178
const char * get_use_address()
Get the active network hostname.
Definition util.cpp:45
@ 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
std::unique_ptr< ArduinoLibreTinyOTABackend > make_ota_backend()
constexpr float AFTER_WIFI
For components that should be initialized after WiFi is connected.
Definition component.h:41
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:143
std::unique_ptr< ListenSocket > socket_ip_loop_monitored(int type, int protocol)
Definition socket.cpp:95
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:892
void HOT delay(uint32_t ms)
Definition core.cpp:28
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:26
int written
Definition helpers.h:936
Application App
Global storage of Application pointer - only one Application can exist.
static void uint32_t