From e56a295e34f90ce256b767dfe1acb9f45044c987 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Thu, 12 Dec 2024 11:55:14 -0800 Subject: [PATCH] Add MDNS.addServiceTxt() to SimpleMDNS (#2679) * Add MDNS.addServiceTxt() to SimpleMDNS Fixes #2678 A simple mapping allows for basic service text addition even when using SimpleMDNS and ArduinoOTA. * Protection against duplicate services addition --- libraries/SimpleMDNS/src/SimpleMDNS.cpp | 75 +++++++++++++++++++++++-- libraries/SimpleMDNS/src/SimpleMDNS.h | 36 +++++++++++- 2 files changed, 103 insertions(+), 8 deletions(-) diff --git a/libraries/SimpleMDNS/src/SimpleMDNS.cpp b/libraries/SimpleMDNS/src/SimpleMDNS.cpp index 6eeeb5d..700d8bd 100644 --- a/libraries/SimpleMDNS/src/SimpleMDNS.cpp +++ b/libraries/SimpleMDNS/src/SimpleMDNS.cpp @@ -42,7 +42,7 @@ bool SimpleMDNS::begin(const char *hostname, unsigned int ttl) { } void SimpleMDNS::enableArduino(unsigned int port, bool passwd) { - if (!_running) { + if (!_running || _arduinoAdded) { return; } struct netif *n = netif_list; @@ -50,20 +50,28 @@ void SimpleMDNS::enableArduino(unsigned int port, bool passwd) { mdns_resp_add_service(n, _hostname, "_arduino", DNSSD_PROTO_TCP, port, _arduinoGetTxt, (void *)passwd); n = n->next; } + _arduinoAdded = true; } -void SimpleMDNS::addService(const char *service, const char *proto, unsigned int port) { +hMDNSService SimpleMDNS::addService(const char *service, const char *proto, unsigned int port) { if (!_running) { - return; + return nullptr; + } + if (_svcMap.find(service) != _svcMap.end()) { + // Duplicates = error + return nullptr; } char s[128]; snprintf(s, sizeof(s), "_%s", service); s[sizeof(s) - 1] = 0; + SimpleMDNSService *svc = new SimpleMDNSService(); + _svcMap.insert({strdup(service), svc}); struct netif *n = netif_list; while (n) { - mdns_resp_add_service(n, _hostname, s, !strcasecmp("tcp", proto) ? DNSSD_PROTO_TCP : DNSSD_PROTO_UDP, port, _nullGetTxt, nullptr); + mdns_resp_add_service(n, _hostname, s, !strcasecmp("tcp", proto) ? DNSSD_PROTO_TCP : DNSSD_PROTO_UDP, port, SimpleMDNSService::callback, (void *)svc); n = n->next; } + return (hMDNSService*) service; } void SimpleMDNS::update() { @@ -89,10 +97,65 @@ void SimpleMDNS::_arduinoGetTxt(struct mdns_service *service, void *txt_userdata _addServiceTxt(service, (bool)txt_userdata ? "auth_upload=yes" : "auth_upload=no"); } -void SimpleMDNS::_nullGetTxt(struct mdns_service *service, void *txt_userdata) { - /* nop */ + +SimpleMDNSService::SimpleMDNSService() { } +void SimpleMDNSService::callback(struct mdns_service *service, void *txt_userdata) { + SimpleMDNSService *obj = (SimpleMDNSService *)txt_userdata; + for (auto s : obj->txt) { + mdns_resp_add_service_txtitem(service, s, strlen(s)); + } +} + +hMDNSTxt SimpleMDNSService::add(const char *key, const char *value) { + char s[128]; + snprintf(s, sizeof(s), "%s=%s", key, value); + s[sizeof(s) - 1] = 0; + char *copy = strdup(s); + txt.push_back(copy); + return (void *)copy; // Do not use... +}; + +// Add a (static) MDNS TXT item ('key' = 'value') to the service +hMDNSTxt SimpleMDNS::addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, const char* p_pcValue) { + const char *s = (const char *)p_hService; + auto o = _svcMap.find(s); + if (o != _svcMap.end()) { + return o->second->add(p_pcKey, p_pcValue); + } + return nullptr; +} + +hMDNSTxt SimpleMDNS::addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, uint32_t p_u32Value) { + char s[16]; + sprintf(s, "%lu", p_u32Value); + return addServiceTxt(p_hService, p_pcKey, s); +} + +hMDNSTxt SimpleMDNS::addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, uint16_t p_u16Value) { + return addServiceTxt(p_hService, p_pcKey, (uint32_t)p_u16Value); +} + +hMDNSTxt SimpleMDNS::addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, uint8_t p_u8Value) { + return addServiceTxt(p_hService, p_pcKey, (uint32_t)p_u8Value); +} + +hMDNSTxt SimpleMDNS::addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, int32_t p_i32Value) { + char s[16]; + sprintf(s, "%ld", p_i32Value); + return addServiceTxt(p_hService, p_pcKey, s); +} + +hMDNSTxt SimpleMDNS::addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, int16_t p_i16Value) { + return addServiceTxt(p_hService, p_pcKey, (int32_t)p_i16Value); +} + +hMDNSTxt SimpleMDNS::addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, int8_t p_i8Value) { + return addServiceTxt(p_hService, p_pcKey, (int32_t)p_i8Value); +} + + const char *SimpleMDNS::_hostname = nullptr; SimpleMDNS MDNS; diff --git a/libraries/SimpleMDNS/src/SimpleMDNS.h b/libraries/SimpleMDNS/src/SimpleMDNS.h index 0e7c8ab..eb70b54 100644 --- a/libraries/SimpleMDNS/src/SimpleMDNS.h +++ b/libraries/SimpleMDNS/src/SimpleMDNS.h @@ -21,13 +21,44 @@ #pragma once #include +#include +#include +#include + +typedef void* hMDNSTxt; // Unusable in SimpleMDNS, for signature compatibility only + +class SimpleMDNSService { +public: + SimpleMDNSService(); + static void callback(struct mdns_service *service, void *txt_userdata); + hMDNSTxt add(const char *key, const char *val); +private: + std::vector txt; +}; + +// hMDNSService (opaque handle to access the service) +typedef const void* hMDNSService; class SimpleMDNS { public: bool begin(const char *hostname, unsigned int ttl = 60); void enableArduino(unsigned int port, bool passwd = false); - void addService(const char *service, const char *proto, unsigned int port); + + hMDNSService addService(const char *service, const char *proto, unsigned int port); + hMDNSService addService(const char *name, const char *service, const char *proto, unsigned int port) { + (void) name; // Ignored + return addService(service, proto, port); + } + + // Add a (static) MDNS TXT item ('key' = 'value') to the service + hMDNSTxt addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, const char* p_pcValue); + hMDNSTxt addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, uint32_t p_u32Value); + hMDNSTxt addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, uint16_t p_u16Value); + hMDNSTxt addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, uint8_t p_u8Value); + hMDNSTxt addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, int32_t p_i32Value); + hMDNSTxt addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, int16_t p_i16Value); + hMDNSTxt addServiceTxt(const hMDNSService p_hService, const char* p_pcKey, int8_t p_i8Value); // No-ops here void end(); @@ -37,10 +68,11 @@ private: static void _statusCB(struct netif *netif); static void _addServiceTxt(struct mdns_service *service, const char *str); static void _arduinoGetTxt(struct mdns_service *service, void *txt_userdata); - static void _nullGetTxt(struct mdns_service *service, void *txt_userdata); bool _running = false; static const char *_hostname; + std::map _svcMap; + bool _arduinoAdded = false; }; extern SimpleMDNS MDNS;