48 static const char *
const TAG =
"udp";
54 static const uint32_t DELTA = 0x9e3779b9;
55 #define MX ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum ^ y) + (k[(p ^ e) & 7] ^ z))) 61 static void xxtea_encrypt(uint32_t *v,
size_t n,
const uint32_t *k) {
62 uint32_t z,
y, sum, e;
64 size_t q = 6 + 52 / n;
70 for (p = 0; p != n - 1; p++) {
79 static void xxtea_decrypt(uint32_t *v,
size_t n,
const uint32_t *k) {
80 uint32_t z,
y, sum, e;
82 size_t q = 6 + 52 / n;
87 for (p = n - 1; p != 0; p--) {
97 inline static size_t round4(
size_t value) {
return (value + 3) & ~3; }
104 static const size_t MAX_PACKET_SIZE = 508;
105 static const uint16_t MAGIC_NUMBER = 0x4553;
106 static const uint16_t MAGIC_PING = 0x5048;
107 static const uint32_t PREF_HASH = 0x45535043;
117 static const size_t MAX_PING_KEYS = 4;
119 static inline void add(std::vector<uint8_t> &vec, uint32_t data) {
120 vec.push_back(data & 0xFF);
121 vec.push_back((data >> 8) & 0xFF);
122 vec.push_back((data >> 16) & 0xFF);
123 vec.push_back((data >> 24) & 0xFF);
126 static inline uint32_t get_uint32(uint8_t *&buf) {
127 uint32_t data = *buf++;
129 data += *buf++ << 16;
130 data += *buf++ << 24;
134 static inline uint16_t get_uint16(uint8_t *&buf) {
135 uint16_t data = *buf++;
140 static inline void add(std::vector<uint8_t> &vec, uint8_t data) { vec.push_back(data); }
141 static inline void add(std::vector<uint8_t> &vec, uint16_t data) {
142 vec.push_back((uint8_t) data);
143 vec.push_back((uint8_t) (data >> 8));
145 static inline void add(std::vector<uint8_t> &vec,
DataKey data) { vec.push_back(data); }
146 static void add(std::vector<uint8_t> &vec,
const char *str) {
147 auto len = strlen(str);
149 for (
size_t i = 0; i !=
len; i++) {
150 vec.push_back(*str++);
156 if (strlen(this->name_) > 255) {
158 this->status_set_error(
"Device name exceeds 255 chars");
161 this->resend_ping_key_ = this->ping_pong_enable_;
164 this->pref_.
load(&this->rolling_code_[1]);
165 this->rolling_code_[1]++;
166 this->pref_.save(&this->rolling_code_[1]);
168 ESP_LOGV(TAG,
"Rolling code incremented, upper part now %u", (
unsigned) this->rolling_code_[1]);
170 for (
auto &
sensor : this->sensors_) {
172 this->updated_ =
true;
177 #ifdef USE_BINARY_SENSOR 178 for (
auto &
sensor : this->binary_sensors_) {
180 this->updated_ =
true;
185 this->should_send_ = this->ping_pong_enable_;
187 this->should_send_ |= !this->sensors_.empty();
189 #ifdef USE_BINARY_SENSOR 190 this->should_send_ |= !this->binary_sensors_.empty();
192 this->should_listen_ = !this->providers_.empty() || this->is_encrypted_();
194 add(this->header_, MAGIC_NUMBER);
195 add(this->header_, this->name_);
197 while (this->header_.size() & 0x3)
198 this->header_.push_back(0);
199 #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) 200 for (
const auto &
address : this->addresses_) {
203 this->sockaddrs_.push_back(saddr);
206 if (this->should_send_) {
207 this->broadcast_socket_ =
socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
208 if (this->broadcast_socket_ ==
nullptr) {
210 this->status_set_error(
"Could not create socket");
214 auto err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable,
sizeof(
int));
216 this->status_set_warning(
"Socket unable to set reuseaddr");
219 err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_BROADCAST, &enable,
sizeof(
int));
221 this->status_set_warning(
"Socket unable to set broadcast");
226 if (this->should_listen_) {
227 this->listen_socket_ =
socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
228 if (this->listen_socket_ ==
nullptr) {
230 this->status_set_error(
"Could not create socket");
233 auto err = this->listen_socket_->setblocking(
false);
235 ESP_LOGE(TAG,
"Unable to set nonblocking: errno %d", errno);
237 this->status_set_error(
"Unable to set nonblocking");
241 err = this->listen_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable,
sizeof(enable));
243 this->status_set_warning(
"Socket unable to set reuseaddr");
250 ESP_LOGE(TAG,
"Socket unable to set sockaddr: errno %d", errno);
252 this->status_set_error(
"Unable to set sockaddr");
256 err = this->listen_socket_->bind((
struct sockaddr *) &server,
sizeof(server));
258 ESP_LOGE(TAG,
"Socket unable to bind: errno %d", errno);
260 this->status_set_error(
"Unable to bind socket");
265 #ifdef USE_SOCKET_IMPL_LWIP_TCP 267 for (
const auto &
address : this->addresses_) {
268 auto ipaddr = IPAddress();
269 ipaddr.fromString(
address.c_str());
270 this->ipaddrs_.push_back(ipaddr);
272 if (this->should_listen_)
273 this->udp_client_.begin(this->port_);
279 if (this->rolling_code_enable_) {
281 add(this->data_, this->rolling_code_[0]);
282 add(this->data_, this->rolling_code_[1]);
283 this->increment_code_();
287 for (
auto pkey : this->ping_keys_) {
289 add(this->data_, pkey.second);
296 uint32_t buffer[MAX_PACKET_SIZE / 4];
297 memset(buffer, 0,
sizeof buffer);
299 auto header_len = round4(this->header_.size()) / 4;
300 auto len = round4(data_.size()) / 4;
301 memcpy(buffer, this->header_.data(), this->header_.size());
302 memcpy(buffer + header_len, this->data_.data(), this->data_.size());
303 if (this->is_encrypted_()) {
304 xxtea_encrypt(buffer + header_len, len, (uint32_t *) this->encryption_key_.data());
306 auto total_len = (header_len +
len) * 4;
307 this->send_packet_(buffer, total_len);
311 auto len = 1 + 1 + 1 + strlen(
id);
312 if (
len + this->header_.size() + this->data_.size() > MAX_PACKET_SIZE) {
315 add(this->data_, key);
316 add(this->data_, (uint8_t) data);
317 add(this->data_,
id);
320 FuData udata{.f32 = data};
321 this->add_data_(key,
id, udata.u32);
325 auto len = 4 + 1 + 1 + strlen(
id);
326 if (
len + this->header_.size() + this->data_.size() > MAX_PACKET_SIZE) {
329 add(this->data_, key);
330 add(this->data_, data);
331 add(this->data_,
id);
338 for (
auto &
sensor : this->sensors_) {
339 if (all ||
sensor.updated) {
345 #ifdef USE_BINARY_SENSOR 346 for (
auto &
sensor : this->binary_sensors_) {
347 if (all ||
sensor.updated) {
354 this->updated_ =
false;
355 this->resend_data_ =
false;
359 this->updated_ =
true;
360 this->resend_data_ = this->should_send_;
361 auto now =
millis() / 1000;
362 if (this->last_key_time_ + this->ping_pong_recyle_time_ < now) {
363 this->resend_ping_key_ = this->ping_pong_enable_;
364 this->last_key_time_ = now;
369 uint8_t buf[MAX_PACKET_SIZE];
370 if (this->should_listen_) {
372 #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) 373 auto len = this->listen_socket_->read(buf,
sizeof(buf));
375 #ifdef USE_SOCKET_IMPL_LWIP_TCP 376 auto len = this->udp_client_.parsePacket();
378 len = this->udp_client_.read(buf,
sizeof(buf));
381 this->process_(buf,
len);
387 if (this->resend_ping_key_)
388 this->send_ping_pong_request_();
389 if (this->updated_) {
390 this->send_data_(this->resend_data_);
395 if (!this->is_encrypted_())
397 if (this->ping_keys_.count(name) == 0 && this->ping_keys_.size() == MAX_PING_KEYS) {
398 ESP_LOGW(TAG,
"Ping key from %s discarded", name);
401 this->ping_keys_[
name] = key;
402 this->resend_data_ =
true;
403 ESP_LOGV(TAG,
"Ping key from %s now %X", name, (
unsigned) key);
408 ESP_LOGW(TAG,
"Bad ping request");
411 auto key = get_uint32(ptr);
412 this->add_key_(name, key);
413 ESP_LOGV(TAG,
"Updated ping key for %s to %08X", name, (
unsigned) key);
416 static bool process_rolling_code(
Provider &provider, uint8_t *&buf,
const uint8_t *
end) {
419 auto code0 = get_uint32(buf);
420 auto code1 = get_uint32(buf);
422 ESP_LOGW(TAG,
"Rolling code for %s %08lX:%08lX is old", provider.
name, (
unsigned long) code1,
423 (
unsigned long) code0);
435 auto ping_key_seen = !this->ping_pong_enable_;
437 return ESP_LOGV(TAG,
"Bad length %zu", len);
441 uint8_t *start_ptr = buf;
442 const uint8_t *end = buf +
len;
444 auto magic = get_uint16(buf);
445 if (magic != MAGIC_NUMBER && magic != MAGIC_PING)
446 return ESP_LOGV(TAG,
"Bad magic %X", magic);
449 if (hlen > len - 3) {
450 return ESP_LOGV(TAG,
"Bad hostname length %u > %zu", hlen, len - 3);
452 memcpy(namebuf, buf, hlen);
453 if (strcmp(this->name_, namebuf) == 0) {
454 return ESP_LOGV(TAG,
"Ignoring our own data");
457 if (magic == MAGIC_PING)
458 return this->process_ping_request_(namebuf, buf, end - buf);
459 if (round4(len) != len) {
460 return ESP_LOGW(TAG,
"Bad length %zu", len);
462 hlen = round4(hlen + 3);
463 buf = start_ptr + hlen;
465 return ESP_LOGV(TAG,
"No data after header");
468 if (this->providers_.count(namebuf) == 0) {
469 return ESP_LOGVV(TAG,
"Unknown hostname %s", namebuf);
471 auto &provider = this->providers_[namebuf];
474 ping_key_seen =
true;
476 ESP_LOGV(TAG,
"Found hostname %s", namebuf);
478 auto &sensors = this->remote_sensors_[namebuf];
480 #ifdef USE_BINARY_SENSOR 481 auto &binary_sensors = this->remote_binary_sensors_[namebuf];
485 xxtea_decrypt((uint32_t *) buf, (end - buf) / 4, (uint32_t *) provider.
encryption_key.data());
489 if (!process_rolling_code(provider, buf, end))
492 return ESP_LOGV(TAG,
"Expected rolling_key or data_key, got %X", byte);
500 return ESP_LOGV(TAG,
"PING_KEY requires 4 more bytes");
502 auto key = get_uint32(buf);
503 if (key == this->ping_key_) {
504 ping_key_seen =
true;
505 ESP_LOGV(TAG,
"Found good ping key %X", (
unsigned) key);
507 ESP_LOGV(TAG,
"Unknown ping key %X", (
unsigned) key);
511 if (!ping_key_seen) {
512 ESP_LOGW(TAG,
"Ping key not seen");
513 this->resend_ping_key_ =
true;
518 return ESP_LOGV(TAG,
"Binary sensor key requires at least 3 more bytes");
523 return ESP_LOGV(TAG,
"Sensor key requires at least 6 more bytes");
525 rdata.u32 = get_uint32(buf);
527 return ESP_LOGW(TAG,
"Unknown key byte %X", byte);
531 if (end - buf < hlen) {
532 return ESP_LOGV(TAG,
"Name length of %u not available", hlen);
534 memset(namebuf, 0,
sizeof namebuf);
535 memcpy(namebuf, buf, hlen);
536 ESP_LOGV(TAG,
"Found sensor key %d, id %s, data %lX", byte, namebuf, (
unsigned long) rdata.u32);
539 if (byte ==
SENSOR_KEY && sensors.count(namebuf) != 0)
540 sensors[namebuf]->publish_state(rdata.f32);
542 #ifdef USE_BINARY_SENSOR 544 binary_sensors[namebuf]->publish_state(rdata.u32 != 0);
550 ESP_LOGCONFIG(TAG,
"UDP:");
551 ESP_LOGCONFIG(TAG,
" Port: %u", this->port_);
552 ESP_LOGCONFIG(TAG,
" Encrypted: %s", YESNO(this->is_encrypted_()));
553 ESP_LOGCONFIG(TAG,
" Ping-pong: %s", YESNO(this->ping_pong_enable_));
554 for (
const auto &
address : this->addresses_)
555 ESP_LOGCONFIG(TAG,
" Address: %s",
address.c_str());
557 for (
auto sensor : this->sensors_)
558 ESP_LOGCONFIG(TAG,
" Sensor: %s",
sensor.id);
560 #ifdef USE_BINARY_SENSOR 561 for (
auto sensor : this->binary_sensors_)
562 ESP_LOGCONFIG(TAG,
" Binary Sensor: %s",
sensor.id);
564 for (
const auto &host : this->providers_) {
565 ESP_LOGCONFIG(TAG,
" Remote host: %s", host.first.c_str());
566 ESP_LOGCONFIG(TAG,
" Encrypted: %s", YESNO(!host.second.encryption_key.empty()));
568 for (
const auto &
sensor : this->remote_sensors_[host.first.c_str()])
569 ESP_LOGCONFIG(TAG,
" Sensor: %s",
sensor.first.c_str());
571 #ifdef USE_BINARY_SENSOR 572 for (
const auto &
sensor : this->remote_binary_sensors_[host.first.c_str()])
573 ESP_LOGCONFIG(TAG,
" Binary Sensor: %s",
sensor.first.c_str());
578 if (this->rolling_code_enable_) {
579 if (++this->rolling_code_[0] == 0) {
580 this->rolling_code_[1]++;
581 this->pref_.save(&this->rolling_code_[1]);
586 #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) 587 for (
const auto &saddr : this->sockaddrs_) {
588 auto result = this->broadcast_socket_->sendto(data, len, 0, &saddr,
sizeof(saddr));
590 ESP_LOGW(TAG,
"sendto() error %d", errno);
593 #ifdef USE_SOCKET_IMPL_LWIP_TCP 594 auto iface = IPAddress(0, 0, 0, 0);
595 for (
const auto &saddr : this->ipaddrs_) {
596 if (this->udp_client_.beginPacketMulticast(saddr, this->port_, iface, 128) != 0) {
597 this->udp_client_.write((
const uint8_t *) data, len);
598 auto result = this->udp_client_.endPacket();
600 ESP_LOGW(TAG,
"udp.write() error");
610 this->ping_header_.clear();
611 add(this->ping_header_, MAGIC_PING);
612 add(this->ping_header_, this->name_);
613 add(this->ping_header_, this->ping_key_);
614 this->send_packet_(this->ping_header_.data(), this->ping_header_.size());
615 this->resend_ping_key_ =
false;
616 ESP_LOGV(TAG,
"Sent new ping request %08X", (
unsigned) this->ping_key_);
void add_on_state_callback(std::function< void(float)> &&callback)
Add a callback that will be called every time a filtered value arrives.
std::vector< uint8_t > encryption_key
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().
uint32_t random_uint32()
Return a random 32-bit unsigned integer.
void add_binary_data_(uint8_t key, const char *id, bool data)
bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
uint32_t IRAM_ATTR HOT millis()
void send_data_(bool all)
float state
This member variable stores the last state that has passed through all filters.
void process_(uint8_t *buf, size_t len)
Process a received packet.
ESPPreferences * global_preferences
void dump_config() override
void add_key_(const char *name, uint32_t key)
Application App
Global storage of Application pointer - only one Application can exist.
const std::string & get_name() const
Get the name of this Application set by pre_setup().
void send_packet_(void *data, size_t len)
float get_state() const
Getter-syntax for .state.
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
Implementation of SPI Controller mode.
void add_data_(uint8_t key, const char *id, float data)
void send_ping_pong_request_()
void process_ping_request_(const char *name, uint8_t *ptr, size_t len)
socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port)
Set a sockaddr to the specified address and port for the IP version used by socket_ip().
esphome::sensor::Sensor * sensor
std::unique_ptr< Socket > socket(int domain, int type, int protocol)
Create a socket of the given domain, type and protocol.