ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
api_outgoing_connection.h
Go to the documentation of this file.
1#pragma once
2
4#if defined(USE_API) && defined(USE_API_OUTGOING_CONNECTION)
5
6#ifndef USE_API_NOISE
7#error "api outgoing_connection needs noise encryption so the peer is verified by key"
8#endif
9
12
13#include <memory>
14
15namespace esphome::api {
16
17class APIServer;
18class APIConnection;
19
20// Room for an IPv6 address in every build, so a remembered IPv4 target is
21// still dialed after enable_ipv6 is turned on. A size that followed the build
22// would also shift every preference registered after this one on ESP8266,
23// where slots are positional. An IPv6 target on a build without IPv6 is
24// dropped by target_sockaddr_() and relearned.
25// Bytes in an IPv6 address
26static constexpr size_t TARGET_ADDR_LEN = 16;
27
29 // 0 when none is remembered, else AF_INET or AF_INET6
30 uint8_t family;
31 // Network order, IPv4 in the first four bytes and the rest zero
32 uint8_t addr[TARGET_ADDR_LEN];
33 // Interface a link-local IPv6 target is reachable on, 0 when it needs none.
34 // Free in flash: the record still rounds up to the same five words.
35 uint8_t scope_id;
36} PACKED; // NOLINT
37
42 public:
43 void setup();
44 void loop(APIServer *server);
48 void on_client_removed(APIConnection *conn, bool was_authenticated);
49 void on_shutdown() { this->dial_socket_.reset(); }
50 void dump_config() const;
51
52 protected:
53 enum class DialState : uint8_t {
57 };
58
59 static constexpr uint32_t BACKOFF_MIN_MS = 5000;
60 static constexpr uint32_t BACKOFF_MAX_MS = 300000;
61 static constexpr uint32_t CONNECT_TIMEOUT_MS = 10000;
62 static constexpr uint32_t CONNECT_POLL_INTERVAL_MS = 250;
63 static constexpr uint32_t NETWORK_RETRY_MS = 500;
64 static constexpr uint32_t PRECONDITION_RETRY_MS = 5000;
65 // A deep sleep wake window is too short to spend on the delay, so those
66 // builds dial out as soon as the target is gone
67#ifdef USE_DEEP_SLEEP
68 static constexpr uint32_t BOOT_WAIT_MS = 0;
70#else
71 static constexpr uint32_t BOOT_WAIT_MS = API_OUTGOING_CONNECTION_DELAY;
72 static constexpr uint32_t IDLE_WAIT_MS = API_OUTGOING_CONNECTION_DELAY;
73#endif
74
75 void try_dial_(APIServer *server, uint32_t now);
76 void poll_connect_(APIServer *server, uint32_t now);
77 // Hand the connected socket to the server and gate on the new connection
78 void handoff_(APIServer *server, uint32_t now);
79 // Close any half-open dial and wait a jittered backoff before retrying
80 void schedule_retry_(uint32_t now);
81 // Wait without escalating the backoff (used for unmet preconditions)
82 void schedule_wait_(uint32_t now, uint32_t wait);
85#ifndef API_OUTGOING_CONNECTION_HOST
86 // Write saved_ to flash, tracking success in host_persisted_
89 return this->host_persisted_;
90 }
92 void format_target_(std::span<char, socket::SOCKADDR_STR_LEN> buf) const;
93#endif
94
95 // Pointers first (4 bytes each on 32-bit)
96 std::unique_ptr<socket::Socket> dial_socket_;
97 // Compared only, never dereferenced
99#ifndef API_OUTGOING_CONNECTION_HOST
101#endif
102
103 // 4-byte types
108
109 // Byte-aligned types last
110#ifndef API_OUTGOING_CONNECTION_HOST
112 // False while saved_ holds a value the flash write failed for; retried on
113 // the next flagged hello
114 bool host_persisted_{false};
115#endif
117};
118
119} // namespace esphome::api
120#endif // USE_API && USE_API_OUTGOING_CONNECTION
Dials out when no dial-back target client is connected.
void poll_connect_(APIServer *server, uint32_t now)
void handoff_(APIServer *server, uint32_t now)
socklen_t target_sockaddr_(struct sockaddr_storage *addr) const
Fill addr with the target and return its length, or 0 when there is none.
void format_target_(std::span< char, socket::SOCKADDR_STR_LEN > buf) const
Format the remembered target for a log line; empty when there is none.
void on_client_removed(APIConnection *conn, bool was_authenticated)
Clears the dialed-connection gate; dying unauthenticated escalates the backoff.
void schedule_wait_(uint32_t now, uint32_t wait)
void on_target_client(APIConnection *conn)
A key-verified client declared itself a dial-back target; last one wins.
std::unique_ptr< socket::Socket > dial_socket_
void try_dial_(APIServer *server, uint32_t now)
uint32_t socklen_t
Definition headers.h:109
void loop()
struct esphome::api::SavedOutgoingTarget PACKED
ESPPreferences * global_preferences
static void uint32_t
bool sync()
Commit pending writes to flash.
Definition preferences.h:33