From 66e79bf81a51d479b8e5ff92a461d4a58dcba5a8 Mon Sep 17 00:00:00 2001 From: LaborEtArs <laboretars@googlemail.ocm> Date: Mon, 2 Dec 2019 19:19:27 +0100 Subject: [PATCH 001/152] LEAmDNS2 (Host Version) --- .../ESP8266WebServer/src/detail/RequestHandler.h | 3 ++- libraries/ESP8266WiFi/src/include/UdpContext.h | 16 ++++++++++++++++ libraries/ESP8266mDNS/src/ESP8266mDNS.h | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandler.h b/libraries/ESP8266WebServer/src/detail/RequestHandler.h index db840af2a1..7da7f4be9c 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h @@ -5,8 +5,9 @@ template<typename ServerType> class RequestHandler { - using WebServerType = ESP8266WebServerTemplate<ServerType>; public: + using WebServerType = ESP8266WebServerTemplate<ServerType>; + virtual ~RequestHandler() { } virtual bool canHandle(HTTPMethod method, String uri) { (void) method; (void) uri; return false; } virtual bool canUpload(String uri) { (void) uri; return false; } diff --git a/libraries/ESP8266WiFi/src/include/UdpContext.h b/libraries/ESP8266WiFi/src/include/UdpContext.h index 8ad074eeec..9ac77ce4da 100644 --- a/libraries/ESP8266WiFi/src/include/UdpContext.h +++ b/libraries/ESP8266WiFi/src/include/UdpContext.h @@ -167,6 +167,22 @@ class UdpContext #endif // !LWIP_IPV6 + /* + * Add a netif (by its index) as the multicast interface + */ + void setMulticastInterface(netif* p_pNetIf) + { + udp_set_multicast_netif_index(_pcb, netif_get_index(p_pNetIf)); + } + + /* + * Allow access to pcb to change eg. options + */ + udp_pcb* pcb(void) + { + return _pcb; + } + void setMulticastTTL(int ttl) { #ifdef LWIP_MAYBE_XCC diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index 66d40b1b2e..585ddfbbec 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -44,12 +44,14 @@ #include "ESP8266mDNS_Legacy.h" #include "LEAmDNS.h" +#include "LEAmDNS2.h" #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) // Maps the implementation to use to the global namespace type //using MDNSResponder = Legacy_MDNSResponder::MDNSResponder; //legacy using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; //new +//using MDNSResponder = esp8266::experimental::MDNSResponder; //new^2 not compatible extern MDNSResponder MDNS; #endif From af3a877e56103cd5fa01543dc971f5b06eb54150 Mon Sep 17 00:00:00 2001 From: LaborEtArs <laboretars@googlemail.ocm> Date: Tue, 3 Dec 2019 18:18:53 +0100 Subject: [PATCH 002/152] Second try :-) --- libraries/ESP8266mDNS/src/LEAmDNS2.h | 1303 ++++++ libraries/ESP8266mDNS/src/LEAmDNS2_API.cpp | 4164 +++++++++++++++++ .../ESP8266mDNS/src/LEAmDNS2_APIHelpers.cpp | 354 ++ libraries/ESP8266mDNS/src/LEAmDNS2_Host.cpp | 1336 ++++++ libraries/ESP8266mDNS/src/LEAmDNS2_Host.hpp | 1177 +++++ .../ESP8266mDNS/src/LEAmDNS2_Host_Control.cpp | 2207 +++++++++ .../ESP8266mDNS/src/LEAmDNS2_Host_Debug.cpp | 327 ++ .../ESP8266mDNS/src/LEAmDNS2_Host_Structs.cpp | 2435 ++++++++++ .../src/LEAmDNS2_Host_Transfer.cpp | 2390 ++++++++++ libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h | 169 + libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h | 44 + 11 files changed, 15906 insertions(+) create mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2.h create mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_API.cpp create mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_APIHelpers.cpp create mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_Host.cpp create mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_Host.hpp create mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_Host_Control.cpp create mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_Host_Debug.cpp create mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_Host_Structs.cpp create mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_Host_Transfer.cpp create mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h create mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2.h b/libraries/ESP8266mDNS/src/LEAmDNS2.h new file mode 100755 index 0000000000..7aa3bb0160 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2.h @@ -0,0 +1,1303 @@ +/* + LEAmDNS2.h + (c) 2018, LaborEtArs + + Version 0.9 beta + + Some notes (from LaborEtArs, 2018): + Essentially, this is an rewrite of the original EPS8266 Multicast DNS code (ESP8266mDNS). + The target of this rewrite was to keep the existing interface as stable as possible while + adding and extending the supported set of mDNS features. + A lot of the additions were basicly taken from Erik Ekman's lwIP mdns app code. + + Supported mDNS features (in some cases somewhat limited): + - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service + - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented + - Probing host and service domains for uniqueness in the local network + - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak) + - Announcing available services after successful probing + - Using fixed service TXT items or + - Using dynamic service TXT items for presented services (via callback) + - Remove services (and un-announcing them to the observers by sending goodbye-messages) + - Static queries for DNS-SD services (creating a fixed answer set after a certain timeout period) + - Dynamic queries for DNS-SD services with cached and updated answers and user notifications + + + Usage: + In most cases, this implementation should work as a 'drop-in' replacement for the original + ESP8266 Multicast DNS code. Adjustments to the existing code would only be needed, if some + of the new features should be used. + + For presenting services: + In 'setup()': + Install a callback for the probing of host (and service) domains via 'MDNS.setProbeResultCallback(probeResultCallback, &userData);' + Register DNS-SD services with 'MDNSResponder::hMDNSService hService = MDNS.addService("MyESP", "http", "tcp", 5000);' + (Install additional callbacks for the probing of these service domains via 'MDNS.setServiceProbeResultCallback(hService, probeResultCallback, &userData);') + Add service TXT items with 'MDNS.addServiceTxt(hService, "c#", "1");' or by installing a service TXT callback + using 'MDNS.setDynamicServiceTxtCallback(dynamicServiceTxtCallback, &userData);' or service specific + 'MDNS.setDynamicServiceTxtCallback(hService, dynamicServiceTxtCallback, &userData);' + Call MDNS.begin("MyHostName"); + + In 'probeResultCallback(MDNSResponder* p_MDNSResponder, const char* p_pcDomain, MDNSResponder:hMDNSService p_hMDNSService, bool p_bProbeResult, void* p_pUserdata)': + Check the probe result and update the host or service domain name if the probe failed + + In 'dynamicServiceTxtCallback(MDNSResponder* p_MDNSResponder, const hMDNSService p_hMDNSService, void* p_pUserdata)': + Add dynamic TXT items by calling 'MDNS.addDynamicServiceTxt(p_hMDNSService, "c#", "1");' + + In loop(): + Call 'MDNS.update();' + + + For querying services/hosts: + Static: + Call 'uint32_t u32AnswerCount = MDNS.queryService("http", "tcp");' or 'MDNS.queryHost("esp8266")'; + Iterate answers by: 'for (uint32_t u=0; u<u32AnswerCount; ++u) { const char* pHostName = MDNS.answerHostName(u); }' + You should call MDNS.removeQuery() sometimes later (when the answers are not needed anymore) + + Dynamic: + Install a dynamic service query by calling 'DNSResponder::hMDNSQuery hQuery = MDNS.installServiceQuery("http", "tcp", serviceQueryCallback, &userData);' + The callback 'serviceQueryCallback(MDNSResponder* p_MDNSResponder, const stcAnswerAccessor& p_MDNSAnswerAccessor, typeQueryAnswerType p_QueryAnswerTypeFlags, bool p_bSetContent)' + is called for any change in the answer set. + Call 'MDNS.removeQuery(hServiceQuery);' when the answers are not needed anymore + + + Reference: + Used mDNS messages: + A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 + AAAA (0x1C): eg. esp8266.local AAAA OP TTL 1234:5678::90 + PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local + PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local + PTR (0x0C, IPv4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local + PTR (0x0C, IPv6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local + SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local + TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 + NSEC (0x2F): eg. esp8266.local ... (DNSSEC) + + Some NOT used message types: + OPT (0x29): eDNS + + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#ifndef LEAMDNS2_H +#define LEAMDNS2_H + +#include <functional> // for UdpContext.h +#include <list> +#include <limits> +#include <map> + +#include "lwip/netif.h" +#include "WiFiUdp.h" +#include "lwip/udp.h" +#include "debug.h" +#include "include/UdpContext.h" +#include <PolledTimeout.h> + +#include "ESP8266WiFi.h" + + +namespace esp8266 +{ + +/** + LEAmDNS +*/ +namespace experimental +{ + +//this should be user-defined at build time +#ifndef ARDUINO_BOARD +#define ARDUINO_BOARD "generic" +#endif + +#define MDNS_IPV4_SUPPORT +#if LWIP_IPV6 +#define MDNS_IPV6_SUPPORT // If we've got IPv6 support, then we need IPv6 support :-) +#endif + + +#ifdef MDNS_IPV4_SUPPORT +#define MDNS_IPV4_SIZE 4 +#endif +#ifdef MDNS_IPV6_SUPPORT +#define MDNS_IPV6_SIZE 16 +#endif +/* + Maximum length for all service txts for one service +*/ +#define MDNS_SERVICE_TXT_MAXLENGTH 1300 +/* + Maximum length for a full domain name eg. MyESP._http._tcp.local +*/ +#define MDNS_DOMAIN_MAXLENGTH 256 +/* + Maximum length of on label in a domain name (length info fits into 6 bits) +*/ +#define MDNS_DOMAIN_LABEL_MAXLENGTH 63 +/* + Maximum length of a service name eg. http +*/ +#define MDNS_SERVICE_NAME_LENGTH 15 +/* + Maximum length of a service protocol name eg. tcp +*/ +#define MDNS_SERVICE_PROTOCOL_LENGTH 3 +/* + Default timeout for static service queries +*/ +#define MDNS_QUERYSERVICES_WAIT_TIME 5000 + +/* + DNS_RRTYPE_NSEC +*/ +#ifndef DNS_RRTYPE_NSEC +#define DNS_RRTYPE_NSEC 0x2F +#endif + + +/** + MDNSResponder +*/ +class MDNSResponder +{ +protected: +#include "LEAmDNS2_Host.hpp" + +public: + // MISC HELPERS + // Domain name helper + static bool indexDomain(char*& p_rpcDomain, + const char* p_pcDivider = "-", + const char* p_pcDefaultDomain = 0); + // Host name helper + static bool setNetIfHostName(netif* p_pNetIf, + const char* p_pcHostName); + + // INTERFACE + MDNSResponder(void); + virtual ~MDNSResponder(void); + + // HANDLEs for opaque access to responder objects + /** + hMDNSHost + */ + using hMDNSHost = const void*; + /** + hMDNSService + */ + using hMDNSService = const void*; + /** + hMDNSTxt + */ + using hMDNSTxt = const void*; + /** + hMDNSQuery + */ + using hMDNSQuery = const void*; + + // CALLBACKS + /** + MDNSHostProbeResultCallbackFn + Callback function for host domain probe results + */ + using MDNSHostProbeResultCallbackFn = std::function<void(MDNSResponder& p_rMDNSResponder, + const hMDNSHost p_hMDNSHost, + const char* p_pcDomainName, + bool p_bProbeResult)>; + + // Create a MDNS netif responder netif by setting the default hostname + // Later call 'update()' in every 'loop' to run the process loop + // (probing, announcing, responding, ...) + // If no callback is given, the (maybe) already installed callback stays set + hMDNSHost begin(const char* p_pcHostName, + netif* p_pNetIf, + MDNSHostProbeResultCallbackFn p_fnCallback = 0); + bool begin(const char* p_pcHostName, + WiFiMode_t p_WiFiMode, + MDNSHostProbeResultCallbackFn p_fnCallback = 0); + bool begin(const char* p_pcHostName, + MDNSHostProbeResultCallbackFn p_fnCallback = 0); + + // Finish MDNS processing + bool close(const hMDNSHost p_hMDNSHost); + bool close(void); + + hMDNSHost getMDNSHost(netif* p_pNetIf) const; + hMDNSHost getMDNSHost(WiFiMode_t p_WiFiMode) const; + + // Change hostname (probing is restarted) + // If no callback is given, the (maybe) already installed callback stays set + bool setHostName(const hMDNSHost p_hMDNSHost, + const char* p_pcHostName, + MDNSHostProbeResultCallbackFn p_fnCallback = 0); + + const char* hostName(const hMDNSHost p_hMDNSHost) const; + + // Set a callback function for host probe results + // The callback function is called, when the probeing for the host domain + // succeededs or fails. + // In case of failure, the failed domain name should be changed. + bool setHostProbeResultCallback(const hMDNSHost p_hMDNSHost, + MDNSHostProbeResultCallbackFn p_fnCallback); + + // Returns 'true' is host domain probing is done + bool status(const hMDNSHost p_hMDNSHost) const; + + // Add a 'global' default' instance name for new services + bool setInstanceName(const hMDNSHost p_hMDNSHost, + const char* p_pcInstanceName); + const char* instanceName(const hMDNSHost p_hMDNSHost) const; + + /** + MDNSServiceProbeResultCallbackFn + Callback function for service domain probe results + */ + using MDNSServiceProbeResultCallbackFn = std::function<void(MDNSResponder& p_rMDNSResponder, + const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcServiceName, + bool p_bProbeResult)>; + // Add a new service to the MDNS responder. If no name (instance name) is given (p_pcName = 0) + // the current hostname is used. If the hostname is changed later, the instance names for + // these 'auto-named' services are changed to the new name also (and probing is restarted). + // The usual '_' before p_pcService (eg. http) and protocol (eg. tcp) may be given.# + // If no callback is given, the (maybe) already installed callback stays set + hMDNSService addService(const hMDNSHost p_hMDNSHost, + const char* p_pcName, + const char* p_pcServiceType, + const char* p_pcProtocol, + uint16_t p_u16Port, + MDNSServiceProbeResultCallbackFn p_fnCallback = 0); + // Removes a service from the MDNS responder + bool removeService(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService); + bool removeService(const hMDNSHost p_hMDNSHost, + const char* p_pcInstanceName, + const char* p_pcServiceType, + const char* p_pcProtocol); + hMDNSService findService(const hMDNSHost p_hMDNSHost, + const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol); + + // Change the services instance name (and restart probing). + // If no callback is given, the (maybe) already installed callback stays set + bool setServiceName(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcInstanceName, + MDNSServiceProbeResultCallbackFn p_fnCallback = 0); + const char* serviceName(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const; + const char* serviceType(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const; + const char* serviceProtocol(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const; + uint16_t servicePort(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const; + + // Set a service specific probe result callcack + bool setServiceProbeResultCallback(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + MDNSServiceProbeResultCallbackFn p_fnCallback); + + bool serviceStatus(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const; + + // Add a (static) MDNS TXT item ('key' = 'value') to the service + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + const char* p_pcValue); + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint32_t p_u32Value); + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint16_t p_u16Value); + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint8_t p_u8Value); + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + int32_t p_i32Value); + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + int16_t p_i16Value); + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + int8_t p_i8Value); + + // Remove an existing (static) MDNS TXT item from the service + bool removeServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const hMDNSTxt p_hTxt); + bool removeServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey); + + /** + MDNSDynamicServiceTxtCallbackFn + Callback function for dynamic MDNS TXT items + */ + using MDNSDynamicServiceTxtCallbackFn = std::function<void(MDNSResponder& p_rMDNSResponder, + const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService)>; + bool setDynamicServiceTxtCallback(const hMDNSHost p_hMDNSHost, + MDNSDynamicServiceTxtCallbackFn p_fnCallback); + bool setDynamicServiceTxtCallback(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + MDNSDynamicServiceTxtCallbackFn p_fnCallback); + + // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service + // Dynamic TXT items are removed right after one-time use. So they need to be added + // every time the value s needed (via callback). + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + const char* p_pcValue); + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint32_t p_u32Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint16_t p_u16Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint8_t p_u8Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + int32_t p_i32Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + int16_t p_i16Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + int8_t p_i8Value); + + // QUERIES & ANSWERS + /** + clsMDNSAnswerAccessor & clsAnswerAccessorVector + */ + struct clsMDNSAnswerAccessor + { + protected: + /** + stcCompareTxtKey + */ + struct stcCompareTxtKey + { + bool operator()(char const* p_pA, char const* p_pB) const; + }; + public: + clsMDNSAnswerAccessor(const clsHost::stcQuery::stcAnswer* p_pAnswer); + ~clsMDNSAnswerAccessor(void); + + /** + clsTxtKeyValueMap + */ + using clsTxtKeyValueMap = std::map<const char*, const char*, stcCompareTxtKey>; + + bool serviceDomainAvailable(void) const; + const char* serviceDomain(void) const; + bool hostDomainAvailable(void) const; + const char* hostDomain(void) const; + bool hostPortAvailable(void) const; + uint16_t hostPort(void) const; +#ifdef MDNS_IPV4_SUPPORT + bool IPv4AddressAvailable(void) const; + std::vector<IPAddress> IPv4Addresses(void) const; +#endif +#ifdef MDNS_IPV6_SUPPORT + bool IPv6AddressAvailable(void) const; + std::vector<IPAddress> IPv6Addresses(void) const; +#endif + bool txtsAvailable(void) const; + const char* txts(void) const; + const clsTxtKeyValueMap& txtKeyValues(void) const; + const char* txtValue(const char* p_pcKey) const; + + size_t printTo(Print& p_Print) const; + + protected: + const clsHost::stcQuery::stcAnswer* m_pAnswer; + clsTxtKeyValueMap m_TxtKeyValueMap; + }; + using clsMDNSAnswerAccessorVector = std::vector<clsMDNSAnswerAccessor>; + using typeQueryAnswerType = clsHost::typeQueryAnswerType; + using enuQueryAnswerType = clsHost::enuQueryAnswerType; + + // STATIC QUERY + // Perform a (static) service/host query. The function returns after p_u16Timeout milliseconds + // The answers (the number of received answers is returned) can be retrieved by calling + // - answerHostName (or hostname) + // - answerIP (or IP) + // - answerPort (or port) + uint32_t queryService(const hMDNSHost p_hMDNSHost, + const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); + uint32_t queryHost(const hMDNSHost p_hMDNSHost, + const char* p_pcHostName, + const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); + bool removeQuery(const hMDNSHost p_hMDNSHost); + bool hasQuery(const hMDNSHost p_hMDNSHost); + hMDNSQuery getQuery(const hMDNSHost p_hMDNSHost); + + clsMDNSAnswerAccessorVector answerAccessors(const hMDNSHost p_hMDNSHost); + uint32_t answerCount(const hMDNSHost p_hMDNSHost); + clsMDNSAnswerAccessor answerAccessor(const hMDNSHost p_hMDNSHost, + uint32_t p_u32AnswerIndex); + + // DYNAMIC QUERIES + /** + MDNSQueryCallbackFn + + Callback function for received answers for dynamic queries + */ + using MDNSQueryCallbackFn = std::function<void(MDNSResponder& p_pMDNSResponder, + hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hMDNSQuery, + const clsMDNSAnswerAccessor& p_MDNSAnswerAccessor, + typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)>; // true: Answer component set, false: component deleted + + // Install a dynamic service/host query. For every received answer (part) the given callback + // function is called. The query will be updated every time, the TTL for an answer + // has timed-out. + // The answers can also be retrieved by calling + // - answerCount service/host (for host queries, this should never be >1) + // - answerServiceDomain service + // - hasAnswerHostDomain/answerHostDomain service/host + // - hasAnswerIPv4Address/answerIPv4Address service/host + // - hasAnswerIPv6Address/answerIPv6Address service/host + // - hasAnswerPort/answerPort service + // - hasAnswerTxts/answerTxts service + hMDNSQuery installServiceQuery(const hMDNSHost p_hMDNSHost, + const char* p_pcServiceType, + const char* p_pcProtocol, + MDNSQueryCallbackFn p_fnCallback); + hMDNSQuery installHostQuery(const hMDNSHost p_hMDNSHost, + const char* p_pcHostName, + MDNSQueryCallbackFn p_fnCallback); + // Remove a dynamic service query + bool removeQuery(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hMDNSQuery); + + + uint32_t answerCount(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hMDNSQuery); + clsMDNSAnswerAccessorVector answerAccessors(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hMDNSQuery); + clsMDNSAnswerAccessor answerAccessor(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hMDNSQuery, + uint32 p_u32AnswerIndex); + + /* bool hasAnswerServiceDomain(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + const char* answerServiceDomain(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + bool hasAnswerHostDomain(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + const char* answerHostDomain(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + #ifdef MDNS_IPV4_SUPPORT + bool hasAnswerIPv4Address(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + uint32_t answerIPv4AddressCount(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + IPAddress answerIPv4Address(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex); + #endif + #ifdef MDNS_IPV6_SUPPORT + bool hasAnswerIPv6Address(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + uint32_t answerIPv6AddressCount(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + IPAddress answerIPv6Address(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex); + #endif + bool hasAnswerPort(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + uint16_t answerPort(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + bool hasAnswerTxts(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + // Get the TXT items as a ';'-separated string + const char* answerTxts(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex);*/ + + // GENERAL MANAGEMENT + // Application should call this whenever AP is configured/disabled + bool notifyNetIfChange(netif* p_pNetIf); + + // 'update' should be called in every 'loop' to run the MDNS processing + bool update(const hMDNSHost p_hMDNSHost); + bool update(void); // Convenience + + // 'announce' can be called every time, the configuration of some service + // changes. Mainly, this would be changed content of TXT items. + bool announce(const hMDNSHost p_hMDNSHost); + bool announce(void); // Convenience + + // MISC + // Enable OTA update + hMDNSService enableArduino(const hMDNSHost p_hMDNSHost, + uint16_t p_u16Port, + bool p_bAuthUpload = false); + +protected: + /** Internal CLASSES & STRUCTS **/ + + // InstanceData + UdpContext* m_pUDPContext; + clsHostList m_HostList; + + // UDP CONTEXT + bool _allocUDPContext(void); + bool _releaseUDPContext(void); + bool _processUDPInput(void); + + // NETIF + clsHost* _createHost(netif* p_pNetIf); + bool _releaseHost(clsHost* p_pHost); + + const clsHost* _findHost(netif* p_pNetIf) const; + clsHost* _findHost(netif* p_pNetIf); + const clsHost* _findHost(const hMDNSHost p_hMDNSHost) const; + clsHost* _findHost(const hMDNSHost p_hMDNSHost); + + + // HANDLE HELPERS + bool _validateMDNSHostHandle(const hMDNSHost p_hMDNSHost) const; + bool _validateMDNSHostHandle(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const; + + clsHost* _NRH2Ptr(const hMDNSHost p_hMDNSHost); + const clsHost* _NRH2Ptr(const hMDNSHost p_hMDNSHost) const; + clsHost::stcService* _SH2Ptr(const hMDNSService p_hMDNSService); + const clsHost::stcService* _SH2Ptr(const hMDNSService p_hMDNSService) const; + + // INIT + clsHost* _begin(const char* p_pcHostName, + netif* p_pNetIf, + MDNSHostProbeResultCallbackFn p_fnCallback); + bool _close(clsHost& p_rHost); + + +#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER + + const char* _DH(hMDNSHost p_hMDNSResponder = 0) const; + +#endif // not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER + +}; + +#ifdef __MDNS_USE_LEGACY +/** + MDNSResponder_Legacy +*/ +class MDNSResponder_Legacy //: public MDNSResponder +{ +public: + /* INTERFACE */ + MDNSResponder_Legacy(void); + virtual ~MDNSResponder_Legacy(void); + + /** + hMDNSHost (opaque handle to access a netif binding) + */ + using hMDNSHost = const void*; + /** + hMDNSService (opaque handle to access the service) + */ + using hMDNSService = const void*; + /** + MDNSHostProbeResultCallbackFn + Callback function for host domain probe results + */ + using MDNSHostProbeResultCallbackFn = std::function<void(MDNSResponder* p_pMDNSResponder, + const hMDNSHost p_hMDNSHost, + const char* p_pcDomainName, + bool p_bProbeResult)>; + /* LEGACY 2 */ + using MDNSServiceProbeResultCallbackFn1 = std::function<void(MDNSResponder* p_pMDNSResponder, + const hMDNSService p_hMDNSService, + const char* p_pcServiceName, + bool p_bProbeResult)>; + using MDNSServiceProbeResultCallbackFn2 = std::function<void(const hMDNSService p_hMDNSService, + const char* p_pcServiceName, + bool p_bProbeResult)>; + /** + hMDNSTxt (opaque handle to access the TXT items) + */ + using hMDNSTxt = const void*; + /** + MDNSDynamicServiceTxtCallbackFn + Callback function for dynamic MDNS TXT items + */ + using MDNSDynamicServiceTxtCallbackFn = std::function<void(MDNSResponder* p_pMDNSResponder, + const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService)>; + // LEGACY + using MDNSDynamicServiceTxtCallbackFn1 = std::function<void(MDNSResponder* p_pMDNSResponder, + const hMDNSService p_hMDNSService)>; + using MDNSDynamicServiceTxtCallbackFn2 = std::function<void(const hMDNSService p_hMDNSService)>; + + + hMDNSHost getNetIfBinding(netif* p_pNetIf) const; + hMDNSHost getNetIfBinding(WiFiMode_t p_WiFiMode) const; + + // Create a MDNS responder netif binding by setting the default hostname + // Later call 'update()' in every 'loop' to run the process loop + // (probing, announcing, responding, ...) + + hMDNSHost begin(const char* p_pcHostName, + netif* p_pNetIf, + MDNSHostProbeResultCallbackFn p_fnCallback = 0); + bool begin(const char* p_pcHostName, + WiFiMode_t p_WiFiMode, + MDNSHostProbeResultCallbackFn p_fnCallback = 0); + bool begin(const char* p_pcHostName, + MDNSHostProbeResultCallbackFn p_fnCallback = 0); + + /* bool begin(const String& p_strHostName) {return begin(p_strHostName.c_str());} + // for compatibility + bool begin(const char* p_pcHostName, + IPAddress p_IPAddress, // ignored + uint32_t p_u32TTL = 120); // ignored + bool begin(const String& p_strHostName, + IPAddress p_IPAddress, // ignored + uint32_t p_u32TTL = 120) { // ignored + return begin(p_strHostName.c_str(), p_IPAddress, p_u32TTL); + }*/ + // Finish MDNS processing + bool close(const hMDNSHost p_hMDNSHost); + bool close(void); + // for ESP32 compatibility + bool end(void); + + // Change hostname (probing is restarted) + bool setHostName(const hMDNSHost p_hMDNSHost, + const char* p_pcHostName); + // for compatibility... + bool setHostname(const char* p_pcHostName); + bool setHostname(String p_strHostName); + + const char* hostName(const hMDNSHost p_hMDNSHost) const; + const char* hostname(void) const; + + // Returns 'true' is host domain probing is done + bool status(const hMDNSHost p_hMDNSHost) const; + bool status(void) const; + + bool setInstanceName(const hMDNSHost p_hMDNSHost, + const char* p_pcInstanceName); + bool setInstanceName(const char* p_pcInstanceName); + // for ESP32 compatibility + bool setInstanceName(const String& p_strHostName); + + // Add a new service to the MDNS responder. If no name (instance name) is given (p_pcName = 0) + // the current hostname is used. If the hostname is changed later, the instance names for + // these 'auto-named' services are changed to the new name also (and probing is restarted). + // The usual '_' before p_pcService (eg. http) and protocol (eg. tcp) may be given. + hMDNSService addService(const hMDNSHost p_hMDNSHost, + const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + uint16_t p_u16Port); + hMDNSService addService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + uint16_t p_u16Port); + // Removes a service from the MDNS responder + bool removeService(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService); + bool removeService(const hMDNSHost p_hMDNSHost, + const char* p_pcInstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol); + bool removeService(const hMDNSService p_hMDNSService); + bool removeService(const char* p_pcInstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol); + // for compatibility... + bool addService(String p_strServiceName, + String p_strProtocol, + uint16_t p_u16Port); + hMDNSService findService(const hMDNSHost p_hMDNSHost, + const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol); + hMDNSService findService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol); + + // Change the services instance name (and restart probing). + bool setServiceName(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcInstanceName); + bool setServiceName(const hMDNSService p_hMDNSService, + const char* p_pcInstanceName); + + const char* serviceName(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const; + const char* service(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const; + const char* serviceProtocol(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const; + /* LEGACY */ + const char* serviceName(const hMDNSService p_hMDNSService) const; + const char* service(const hMDNSService p_hMDNSService) const; + const char* serviceProtocol(const hMDNSService p_hMDNSService) const; + + bool serviceStatus(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const; + bool serviceStatus(const hMDNSService p_hMDNSService) const; + + // Add a (static) MDNS TXT item ('key' = 'value') to the service + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + const char* p_pcValue); + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint32_t p_u32Value); + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint16_t p_u16Value); + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint8_t p_u8Value); + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + int32_t p_i32Value); + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + int16_t p_i16Value); + hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + int8_t p_i8Value); + // LEGACY + hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + const char* p_pcValue); + hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint32_t p_u32Value); + hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint16_t p_u16Value); + hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint8_t p_u8Value); + hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + int32_t p_i32Value); + hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + int16_t p_i16Value); + hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + int8_t p_i8Value); + + // Remove an existing (static) MDNS TXT item from the service + bool removeServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const hMDNSTxt p_hTxt); + bool removeServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey); + bool removeServiceTxt(const hMDNSHost p_hMDNSHost, + const char* p_pcinstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol, + const char* p_pcKey); + bool removeServiceTxt(const hMDNSService p_hMDNSService, + const hMDNSTxt p_hTxt); + bool removeServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey); + bool removeServiceTxt(const char* p_pcinstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol, + const char* p_pcKey); + // for compatibility... + bool addServiceTxt(const char* p_pcService, + const char* p_pcProtocol, + const char* p_pcKey, + const char* p_pcValue); + bool addServiceTxt(String p_strService, + String p_strProtocol, + String p_strKey, + String p_strValue); + + bool setDynamicServiceTxtCallback(const hMDNSHost p_hMDNSHost, + MDNSDynamicServiceTxtCallbackFn p_fnCallback); + bool setDynamicServiceTxtCallback(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + MDNSDynamicServiceTxtCallbackFn p_fnCallback); + + // Set a global callback for dynamic MDNS TXT items. The callback function is called + // every time, a TXT item is needed for one of the installed services. + bool setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFn1 p_fnCallback); + bool setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFn2 p_fnCallback); + + // Set a service specific callback for dynamic MDNS TXT items. The callback function + // is called every time, a TXT item is needed for the given service. + bool setDynamicServiceTxtCallback(const hMDNSService p_hMDNSService, + MDNSDynamicServiceTxtCallbackFn1 p_fnCallback); + bool setDynamicServiceTxtCallback(const hMDNSService p_hMDNSService, + MDNSDynamicServiceTxtCallbackFn2 p_fnCallback); + + // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service + // Dynamic TXT items are removed right after one-time use. So they need to be added + // every time the value s needed (via callback). + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + const char* p_pcValue); + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint32_t p_u32Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint16_t p_u16Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint8_t p_u8Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + int32_t p_i32Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + int16_t p_i16Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcKey, + int8_t p_i8Value); + /* LEGACY */ + hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + const char* p_pcValue); + hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint32_t p_u32Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint16_t p_u16Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + uint8_t p_u8Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + int32_t p_i32Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + int16_t p_i16Value); + hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, + const char* p_pcKey, + int8_t p_i8Value); + + /** + hMDNSQuery (opaque handle to access dynamic service queries) + */ + using hMDNSQuery = const void*; + //using hMDNSServiceQuery = hMDNSQuery; // for compatibility with V1 + + // Perform a (static) service/host query. The function returns after p_u16Timeout milliseconds + // The answers (the number of received answers is returned) can be retrieved by calling + // - answerHostName (or hostname) + // - answerIP (or IP) + // - answerPort (or port) + uint32_t queryService(const hMDNSHost p_hMDNSHost, + const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); + uint32_t queryService(const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); + // for compatibility... + uint32_t queryService(const String& p_strService, + const String& p_strProtocol); + uint32_t queryHost(const hMDNSHost p_hMDNSHost, + const char* p_pcHostName, + const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); + uint32_t queryHost(const char* p_pcHostName, + const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); + bool removeQuery(const hMDNSHost p_hMDNSHost); + bool removeQuery(void); + bool hasQuery(const hMDNSHost p_hMDNSHost); + bool hasQuery(void); + hMDNSQuery getQuery(const hMDNSHost p_hMDNSHost); + hMDNSQuery getQuery(void); + + const char* answerHostName(const hMDNSHost p_hMDNSHost, + const uint32_t p_u32AnswerIndex); + const char* answerHostName(const uint32_t p_u32AnswerIndex); + // for compatibility... + String hostname(const uint32_t p_u32AnswerIndex); +#ifdef MDNS_IPV4_SUPPORT + IPAddress answerIPv4(const hMDNSHost p_hMDNSHost, + const uint32_t p_u32AnswerIndex); + IPAddress answerIPv4(const uint32_t p_u32AnswerIndex); + // for compatibility + IPAddress answerIP(const uint32_t p_u32AnswerIndex); + IPAddress IP(const uint32_t p_u32AnswerIndex); +#endif +#ifdef MDNS_IPV6_SUPPORT + IPAddress answerIPv6(const hMDNSHost p_hMDNSHost, + const uint32_t p_u32AnswerIndex); + IPAddress answerIPv6(const uint32_t p_u32AnswerIndex); +#endif + uint16_t answerPort(const hMDNSHost p_hMDNSHost, + const uint32_t p_u32AnswerIndex); + uint16_t answerPort(const uint32_t p_u32AnswerIndex); + // for compatibility + uint16_t port(const uint32_t p_u32AnswerIndex); + + /** + typeQueryAnswerType & enuQueryAnswerType + */ + using typeQueryAnswerType = uint8_t; + enum class enuQueryAnswerType : typeQueryAnswerType + { + Unknown = 0x00, + ServiceDomain = 0x01, // Service domain + HostDomain = 0x02, // Host domain + Port = 0x04, // Port + Txts = 0x08, // TXT items +#ifdef MDNS_IPV4_SUPPORT + IPv4Address = 0x10, // IPv4 address +#endif +#ifdef MDNS_IPV6_SUPPORT + IPv6Address = 0x20, // IPv6 address +#endif + }; + //using AnswerType = enuQueryAnswerType; // for compatibility with V1 + + /** + stcAnswerAccessor + */ + struct stcAnswerAccessor + { + protected: + /** + stcCompareTxtKey + */ + struct stcCompareTxtKey + { + bool operator()(char const* p_pA, char const* p_pB) const; + }; + public: + stcAnswerAccessor(MDNSResponder& p_rMDNSResponder, + hMDNSQuery p_hQuery, + uint32_t p_u32AnswerIndex); + /** + clsTxtKeyValueMap + */ + using clsTxtKeyValueMap = std::map<const char*, const char*, stcCompareTxtKey>; + + bool serviceDomainAvailable(void) const; + const char* serviceDomain(void) const; + bool hostDomainAvailable(void) const; + const char* hostDomain(void) const; + bool hostPortAvailable(void) const; + uint16_t hostPort(void) const; +#ifdef MDNS_IPV4_SUPPORT + bool IPv4AddressAvailable(void) const; + std::vector<IPAddress> IPv4Addresses(void) const; +#endif +#ifdef MDNS_IPV6_SUPPORT + bool IPv6AddressAvailable(void) const; + std::vector<IPAddress> IPv6Addresses(void) const; +#endif + bool txtsAvailable(void) const; + const char* txts(void) const; + const clsTxtKeyValueMap& txtKeyValues(void) const; + const char* txtValue(const char* p_pcKey) const; + + size_t printTo(Print& p_Print) const; + + protected: + MDNSResponder& m_rMDNSResponder; + hMDNSQuery m_hQuery; + uint32_t m_u32AnswerIndex; + clsTxtKeyValueMap m_TxtKeyValueMap; + }; + + /** + MDNSQueryCallbackFn + + Callback function for received answers for dynamic queries + */ + using MDNSQueryCallbackFn = std::function<void(MDNSResponder* p_pMDNSResponder, + hMDNSHost p_hMDNSHost, + const stcAnswerAccessor& p_MDNSAnswerAccessor, + typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)>; // true: Answer component set, false: component deleted + // LEGACY + using MDNSQueryCallbackFn1 = std::function<void(MDNSResponder* p_pMDNSResponder, + const stcAnswerAccessor& p_MDNSAnswerAccessor, + typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)>; // true: Answer component set, false: component deleted + using MDNSQueryCallbackFn2 = std::function<void(const stcAnswerAccessor& p_MDNSAnswerAccessor, + typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)>; // true: Answer component set, false: component deleted + //using MDNSServiceInfo = stcAnswerAccessor; // for compatibility with V1 + + // Install a dynamic service/host query. For every received answer (part) the given callback + // function is called. The query will be updated every time, the TTL for an answer + // has timed-out. + // The answers can also be retrieved by calling + // - answerCount service/host (for host queries, this should never be >1) + // - answerServiceDomain service + // - hasAnswerHostDomain/answerHostDomain service/host + // - hasAnswerIPv4Address/answerIPv4Address service/host + // - hasAnswerIPv6Address/answerIPv6Address service/host + // - hasAnswerPort/answerPort service + // - hasAnswerTxts/answerTxts service + hMDNSQuery installServiceQuery(const hMDNSHost p_hMDNSHost, + const char* p_pcService, + const char* p_pcProtocol, + MDNSQueryCallbackFn p_fnCallback); + hMDNSQuery installHostQuery(const hMDNSHost p_hMDNSHost, + const char* p_pcHostName, + MDNSQueryCallbackFn p_fnCallback); + + hMDNSQuery installServiceQuery(const char* p_pcService, + const char* p_pcProtocol, + MDNSQueryCallbackFn1 p_fnCallback); + hMDNSQuery installServiceQuery(const char* p_pcService, + const char* p_pcProtocol, + MDNSQueryCallbackFn2 p_fnCallback); + + hMDNSQuery installHostQuery(const char* p_pcHostName, + MDNSQueryCallbackFn1 p_fnCallback); + hMDNSQuery installHostQuery(const char* p_pcHostName, + MDNSQueryCallbackFn2 p_fnCallback); + // Remove a dynamic service query + bool removeDynamicQuery(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hMDNSQuery); + bool removeDynamicQuery(const hMDNSQuery p_hQuery); + + /** + clsMDNSAnswerAccessorVector + */ + using clsMDNSAnswerAccessorVector = std::vector<stcAnswerAccessor>; + + clsMDNSAnswerAccessorVector answerAccessors(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hMDNSQuery); + clsMDNSAnswerAccessorVector answerAccessors(const hMDNSQuery p_hQuery); + + uint32_t answerCount(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hMDNSQuery); + uint32_t answerCount(const hMDNSQuery p_hQuery); + + bool hasAnswerServiceDomain(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + bool hasAnswerServiceDomain(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + const char* answerServiceDomain(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + const char* answerServiceDomain(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + bool hasAnswerHostDomain(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + bool hasAnswerHostDomain(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + const char* answerHostDomain(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + const char* answerHostDomain(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); +#ifdef MDNS_IPV4_SUPPORT + bool hasAnswerIPv4Address(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + uint32_t answerIPv4AddressCount(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + IPAddress answerIPv4Address(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex); + bool hasAnswerIPv4Address(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + uint32_t answerIPv4AddressCount(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + IPAddress answerIPv4Address(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex); +#endif +#ifdef MDNS_IPV6_SUPPORT + bool hasAnswerIPv6Address(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + uint32_t answerIPv6AddressCount(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + IPAddress answerIPv6Address(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex); + bool hasAnswerIPv6Address(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + uint32_t answerIPv6AddressCount(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + IPAddress answerIPv6Address(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex); +#endif + bool hasAnswerPort(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + bool hasAnswerPort(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + uint16_t answerPort(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + /* uint16_t answerPort(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex);*/ + bool hasAnswerTxts(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + bool hasAnswerTxts(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + // Get the TXT items as a ';'-separated string + const char* answerTxts(const hMDNSHost p_hMDNSHost, + const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + const char* answerTxts(const hMDNSQuery p_hQuery, + const uint32_t p_u32AnswerIndex); + + // Set a callback function for host probe results + // The callback function is called, when the probeing for the host domain + // succeededs or fails. + // In case of failure, the failed domain name should be changed. + bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn p_fnCallback); + /* LEGACY 2 */ + using MDNSHostProbeResultCallbackFn1 = std::function<void(MDNSResponder* p_pMDNSResponder, + const char* p_pcDomainName, + bool p_bProbeResult)>; + using MDNSHostProbeResultCallbackFn2 = std::function<void(const char* p_pcDomainName, + bool p_bProbeResult)>; + + bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn1 p_fnCallback); + bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn2 p_fnCallback); + + /** + MDNSServiceProbeResultCallbackFn + Callback function for service domain probe results + */ + using MDNSServiceProbeResultCallbackFn = std::function<void(MDNSResponder* p_pMDNSResponder, + const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcServiceName, + bool p_bProbeResult)>; + // Set a service specific probe result callcack + bool setServiceProbeResultCallback(const hMDNSService p_hMDNSService, + MDNSServiceProbeResultCallbackFn p_fnCallback); + + bool setServiceProbeResultCallback(const hMDNSService p_hMDNSService, + MDNSServiceProbeResultCallbackFn1 p_fnCallback); + bool setServiceProbeResultCallback(const hMDNSService p_hMDNSService, + MDNSServiceProbeResultCallbackFn2 p_fnCallback); + + // Application should call this whenever AP is configured/disabled + bool notifyNetIfChange(netif* p_pNetIf); + + // 'update' should be called in every 'loop' to run the MDNS processing + bool update(const hMDNSHost p_hMDNSHost); + bool update(void); + + // 'announce' can be called every time, the configuration of some service + // changes. Mainly, this would be changed content of TXT items. + bool announce(const hMDNSHost p_hMDNSHost); + bool announce(void); + + // Enable OTA update + hMDNSService enableArduino(const hMDNSHost p_hMDNSHost, + uint16_t p_u16Port, + bool p_bAuthUpload = false); + hMDNSService enableArduino(uint16_t p_u16Port, + bool p_bAuthUpload = false); + + // Domain name helper + static bool indexDomain(char*& p_rpcDomain, + const char* p_pcDivider = "-", + const char* p_pcDefaultDomain = 0); + // Host name helper + static bool setNetIfHostName(netif* p_pNetIf, + const char* p_pcHostName); +}; +#endif + +} // namespace MDNSImplementation + +} // namespace esp8266 + +#endif // LEAMDNS2_H + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_API.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_API.cpp new file mode 100755 index 0000000000..4b3d22902e --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_API.cpp @@ -0,0 +1,4164 @@ +/* + LEAmDNS2_API.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + + +#include <Schedule.h> +#include <lwip/netif.h> + +#include "LEAmDNS2_Priv.h" + + +namespace +{ + +/* + strrstr (static) + + Backwards search for p_pcPattern in p_pcString + Based on: https://stackoverflow.com/a/1634398/2778898 + +*/ +const char* strrstr(const char*__restrict p_pcString, const char*__restrict p_pcPattern) +{ + const char* pcResult = 0; + + size_t stStringLength = (p_pcString ? strlen(p_pcString) : 0); + size_t stPatternLength = (p_pcPattern ? strlen(p_pcPattern) : 0); + + if ((stStringLength) && + (stPatternLength) && + (stPatternLength <= stStringLength)) + { + // Pattern is shorter or has the same length tham the string + + for (const char* s = (p_pcString + stStringLength - stPatternLength); s >= p_pcString; --s) + { + if (0 == strncmp(s, p_pcPattern, stPatternLength)) + { + pcResult = s; + break; + } + } + } + return pcResult; +} + +} // anonymous + + +namespace esp8266 +{ + +/* + LEAmDNS +*/ +namespace experimental +{ + +/** + STRINGIZE +*/ +#ifndef STRINGIZE +#define STRINGIZE(x) #x +#endif +#ifndef STRINGIZE_VALUE_OF +#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) +#endif + +/** + HELPERS +*/ + +/* + MDNSResponder::indexDomain (static) + + Updates the given domain 'p_rpcHostName' by appending a delimiter and an index number. + + If the given domain already hasa numeric index (after the given delimiter), this index + incremented. If not, the delimiter and index '2' is added. + + If 'p_rpcHostName' is empty (==0), the given default name 'p_pcDefaultHostName' is used, + if no default is given, 'esp8266' is used. + +*/ +/*static*/ bool MDNSResponder::indexDomain(char*& p_rpcDomain, + const char* p_pcDivider /*= "-"*/, + const char* p_pcDefaultDomain /*= 0*/) +{ + bool bResult = false; + + // Ensure a divider exists; use '-' as default + const char* pcDivider = (p_pcDivider ? : "-"); + + if (p_rpcDomain) + { + const char* pFoundDivider = strrstr(p_rpcDomain, pcDivider); + if (pFoundDivider) // maybe already extended + { + char* pEnd = 0; + unsigned long ulIndex = strtoul((pFoundDivider + strlen(pcDivider)), &pEnd, 10); + if ((ulIndex) && + ((pEnd - p_rpcDomain) == (ptrdiff_t)strlen(p_rpcDomain)) && + (!*pEnd)) // Valid (old) index found + { + + char acIndexBuffer[16]; + sprintf(acIndexBuffer, "%lu", (++ulIndex)); + size_t stLength = ((pFoundDivider - p_rpcDomain + strlen(pcDivider)) + strlen(acIndexBuffer) + 1); + char* pNewHostName = new char[stLength]; + if (pNewHostName) + { + memcpy(pNewHostName, p_rpcDomain, (pFoundDivider - p_rpcDomain + strlen(pcDivider))); + pNewHostName[pFoundDivider - p_rpcDomain + strlen(pcDivider)] = 0; + strcat(pNewHostName, acIndexBuffer); + + delete[] p_rpcDomain; + p_rpcDomain = pNewHostName; + + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] indexDomain: FAILED to alloc new hostname!\n"));); + } + } + else + { + pFoundDivider = 0; // Flag the need to (base) extend the hostname + } + } + + if (!pFoundDivider) // not yet extended (or failed to increment extension) -> start indexing + { + size_t stLength = strlen(p_rpcDomain) + (strlen(pcDivider) + 1 + 1); // Name + Divider + '2' + '\0' + char* pNewHostName = new char[stLength]; + if (pNewHostName) + { + sprintf(pNewHostName, "%s%s2", p_rpcDomain, pcDivider); + + delete[] p_rpcDomain; + p_rpcDomain = pNewHostName; + + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] indexDomain: FAILED to alloc new hostname!\n"));); + } + } + } + else + { + // No given host domain, use base or default + const char* cpcDefaultName = (p_pcDefaultDomain ? : "esp8266"); + + size_t stLength = strlen(cpcDefaultName) + 1; // '\0' + p_rpcDomain = new char[stLength]; + if (p_rpcDomain) + { + strncpy(p_rpcDomain, cpcDefaultName, stLength); + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] indexDomain: FAILED to alloc new hostname!\n"));); + } + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] indexDomain: %s\n"), p_rpcDomain);); + return bResult; +} + + +/* + MDNSResponder::setStationHostName (static) + + Sets the staion hostname + +*/ +/*static*/ bool MDNSResponder::setNetIfHostName(netif* p_pNetIf, + const char* p_pcHostName) +{ + if ((p_pNetIf) && + (p_pcHostName)) + { + netif_set_hostname(p_pNetIf, p_pcHostName); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setNetIfHostName host name: %s!\n"), p_pcHostName);); + } + return true; +} + + +/** + INTERFACE +*/ + +/** + MDNSResponder::MDNSResponder +*/ +MDNSResponder::MDNSResponder(void) + : m_pUDPContext(0) +{ + _allocUDPContext(); +} + +/* + MDNSResponder::~MDNSResponder +*/ +MDNSResponder::~MDNSResponder(void) +{ + close(); +} + +/* + MDNSResponder::begin (hostname, netif, probe_callback) +*/ +MDNSResponder::hMDNSHost MDNSResponder::begin(const char* p_pcHostName, + netif* p_pNetIf, + MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s, netif: %u)\n"), _DH(), (p_pcHostName ? : "-"), (p_pNetIf ? netif_get_index(p_pNetIf) : 0));); + + return (hMDNSHost)_begin(p_pcHostName, p_pNetIf, p_fnCallback); +} + +/* + MDNSResponder::begin (hostname, probe_callback) +*/ +bool MDNSResponder::begin(const char* p_pcHostName, + MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s)\n"), _DH(), (p_pcHostName ? : "_"));); + + return begin(p_pcHostName, (WiFiMode_t)wifi_get_opmode(), p_fnCallback); +} + +/* + MDNSResponder::begin (hostname, WiFiMode, probe_callback) +*/ +bool MDNSResponder::begin(const char* p_pcHostName, + WiFiMode_t p_WiFiMode, + MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s, opmode: %u)\n"), _DH(), (p_pcHostName ? : "_"), (uint32_t)p_WiFiMode);); + + bool bResult = true; + + if ((bResult) && + (p_WiFiMode & WIFI_STA)) + { + bResult = (0 != _begin(p_pcHostName, netif_get_by_index(WIFI_STA), p_fnCallback)); + } + if ((bResult) && + (p_WiFiMode & WIFI_AP)) + { + bResult = (0 != _begin(p_pcHostName, netif_get_by_index(WIFI_AP), p_fnCallback)); + } + return bResult; +} + +/* + MDNSResponder::close +*/ +bool MDNSResponder::close(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_close(*(clsHost*)p_hMDNSHost))); +} + +/* + MDNSResponder::close (convenience) +*/ +bool MDNSResponder::close(void) +{ + clsHostList::iterator it(m_HostList.begin()); + while (m_HostList.end() != it) + { + _close(**it++); + } + + return _releaseUDPContext(); +} + + +/* + MDNSResponder::getMDNSHost (netif) +*/ +MDNSResponder::hMDNSHost MDNSResponder::getMDNSHost(netif* p_pNetIf) const +{ + return (hMDNSHost)(p_pNetIf ? _findHost(p_pNetIf) : 0); +} + +/* + MDNSResponder::getMDNSHost (WiFiMode) +*/ +MDNSResponder::hMDNSHost MDNSResponder::getMDNSHost(WiFiMode_t p_WiFiMode) const +{ + hMDNSHost hResult = 0; + + if (WIFI_STA == p_WiFiMode) + { + hResult = getMDNSHost(netif_get_by_index(WIFI_STA)); + } + else if (WIFI_AP == p_WiFiMode) + { + hResult = getMDNSHost(netif_get_by_index(WIFI_AP)); + } + return hResult; +} + +/* + MDNSResponder::setHostName +*/ +bool MDNSResponder::setHostName(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcHostName, + MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_NRH2Ptr(p_hMDNSHost)->setHostName(p_pcHostName)) && + (p_fnCallback ? setHostProbeResultCallback(p_hMDNSHost, p_fnCallback) : true)); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setHostName: FAILED for '%s'!\n"), _DH(p_hMDNSHost), (p_pcHostName ? : "-"));); + return bResult; +} + +/* + MDNSResponder::hostName +*/ +const char* MDNSResponder::hostName(const MDNSResponder::hMDNSHost p_hMDNSHost) const +{ + return (_validateMDNSHostHandle(p_hMDNSHost) + ? (_NRH2Ptr(p_hMDNSHost)->hostName()) + : 0); +} + +/* + MDNSResponder::setHostProbeResultCallback +*/ +bool MDNSResponder::setHostProbeResultCallback(const hMDNSHost p_hMDNSHost, + MDNSHostProbeResultCallbackFn p_fnCallback) +{ + bool bResult = false; + if ((bResult = _validateMDNSHostHandle(p_hMDNSHost))) + { + if (p_fnCallback) + { + _NRH2Ptr(p_hMDNSHost)->m_HostProbeInformation.m_fnProbeResultCallback = [this, p_fnCallback](clsHost & p_rHost, + const char* p_pcDomainName, + bool p_bProbeResult)->void + { + p_fnCallback(*this, (hMDNSHost)&p_rHost, p_pcDomainName, p_bProbeResult); + }; + } + else + { + _NRH2Ptr(p_hMDNSHost)->m_HostProbeInformation.m_fnProbeResultCallback = 0; + } + } + return bResult; +} + +/* + MDNSResponder::status +*/ +bool MDNSResponder::status(const MDNSResponder::hMDNSHost p_hMDNSHost) const +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_NRH2Ptr(p_hMDNSHost)->probeStatus())); +} + + +/* + SERVICES +*/ + +/* + MDNSResponder::setInstanceName +*/ +bool MDNSResponder::setInstanceName(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcInstanceName) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_NRH2Ptr(p_hMDNSHost)->setInstanceName(p_pcInstanceName))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setInstanceName: FAILED for '%s'!\n"), _DH(p_hMDNSHost), (p_pcInstanceName ? : "-"));); + return bResult; +} + +/* + MDNSResponder::instanceName +*/ +const char* MDNSResponder::instanceName(const MDNSResponder::hMDNSHost p_hMDNSHost) const +{ + return (_validateMDNSHostHandle(p_hMDNSHost) + ? (_NRH2Ptr(p_hMDNSHost)->instanceName()) + : 0); +} + +/* + MDNSResponder::addService + + Add service; using hostname if no name is explicitly provided for the service + The usual '_' underline, which is prepended to service and protocol, eg. _http, + may be given. If not, it is added automatically. + +*/ +MDNSResponder::hMDNSService MDNSResponder::addService(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcName, + const char* p_pcServiceType, + const char* p_pcProtocol, + uint16_t p_u16Port, + MDNSServiceProbeResultCallbackFn p_fnCallback /*= 0*/) +{ + hMDNSService hService = (_validateMDNSHostHandle(p_hMDNSHost) + ? (hMDNSService)_NRH2Ptr(p_hMDNSHost)->addService(p_pcName, p_pcServiceType, p_pcProtocol, p_u16Port) + : 0); + if ((p_fnCallback) && + (hService)) + { + setServiceProbeResultCallback(p_hMDNSHost, hService, p_fnCallback); + } + DEBUG_EX_ERR(if (!hService) DEBUG_OUTPUT.printf_P(PSTR("%s addService: FAILED for '%s._%s._%s.local'!\n"), _DH(p_hMDNSHost), (p_pcName ? : "-"), (p_pcServiceType ? : "-"), (p_pcProtocol ? : "-"));); + return hService; +} + +/* + MDNSResponder::removeService + + Unanounce a service (by sending a goodbye message) and remove it + from the MDNS responder + +*/ +bool MDNSResponder::removeService(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && + (_NRH2Ptr(p_hMDNSHost)->removeService(_SH2Ptr(p_hMDNSService)))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeService: FAILED!\n"), _DH(p_hMDNSHost));); + return bResult; +} + +/* + MDNSResponder::removeService +*/ +bool MDNSResponder::removeService(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcInstanceName, + const char* p_pcServiceType, + const char* p_pcProtocol) +{ + clsHost* pMDNSHost; + clsHost::stcService* pMDNSService; + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && + (pMDNSHost = (clsHost*)p_hMDNSHost) && + ((pMDNSService = _NRH2Ptr(p_hMDNSHost)->findService(p_pcInstanceName, p_pcServiceType, p_pcProtocol))) && + (_NRH2Ptr(p_hMDNSHost)->removeService(pMDNSService))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeService: FAILED for '%s._%s._%s.local'!\n"), _DH(p_hMDNSHost), (p_pcInstanceName ? : "-"), (p_pcServiceType ? : "-"), (p_pcProtocol ? : "-"));); + return bResult; +} + +/* + MDNSResponder::findService + + Find an existing service. + +*/ +MDNSResponder::hMDNSService MDNSResponder::findService(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcInstanceName, + const char* p_pcServiceType, + const char* p_pcProtocol) +{ + clsHost* pMDNSHost; + return (((_validateMDNSHostHandle(p_hMDNSHost)) && + (pMDNSHost = (clsHost*)p_hMDNSHost)) + ? _NRH2Ptr(p_hMDNSHost)->findService(p_pcInstanceName, p_pcServiceType, p_pcProtocol) + : 0); +} + +/* + MDNSResponder::setServiceName +*/ +bool MDNSResponder::setServiceName(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcInstanceName, + MDNSServiceProbeResultCallbackFn p_fnCallback /*= 0*/) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && + (_NRH2Ptr(p_hMDNSHost)->setServiceName(_SH2Ptr(p_hMDNSService), p_pcInstanceName)) && + (p_fnCallback ? setServiceProbeResultCallback(p_hMDNSHost, p_hMDNSService, p_fnCallback) : true)); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setServiceName: FAILED for '%s'!\n"), _DH(p_hMDNSHost), (p_pcInstanceName ? : "-"));); + return bResult; +} + +/* + MDNSResponder::serviceName +*/ +const char* MDNSResponder::serviceName(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const +{ + return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) + ? (_SH2Ptr(p_hMDNSService)->m_pcName) + : 0); +} + +/* + MDNSResponder::serviceType +*/ +const char* MDNSResponder::serviceType(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const +{ + return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) + ? (_SH2Ptr(p_hMDNSService)->m_pcServiceType) + : 0); +} + +/* + MDNSResponder::serviceProtocol +*/ +const char* MDNSResponder::serviceProtocol(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const +{ + return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) + ? (_SH2Ptr(p_hMDNSService)->m_pcProtocol) + : 0); +} + +/* + MDNSResponder::serviceProtocol +*/ +uint16_t MDNSResponder::servicePort(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const +{ + return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) + ? (_SH2Ptr(p_hMDNSService)->m_u16Port) + : 0); +} + +/* + MDNSResponder::setServiceProbeResultCallback + + Set a service specific callback for probe results. The callback is called, when probing + for the service domain failes or succeedes. + In the case of failure, the service name should be changed via 'setServiceName'. + When succeeded, the service domain will be announced by the MDNS responder. + +*/ +bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + MDNSResponder::MDNSServiceProbeResultCallbackFn p_fnCallback) +{ + bool bResult = false; + if ((bResult = _validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService))) + { + if (p_fnCallback) + { + _SH2Ptr(p_hMDNSService)->m_ProbeInformation.m_fnProbeResultCallback = [this, p_fnCallback](clsHost & p_rHost, + clsHost::stcService & p_rMDNSService, + const char* p_pcDomainName, + bool p_bProbeResult)->void + { + p_fnCallback(*this, (hMDNSHost)&p_rHost, (hMDNSService)&p_rMDNSService, p_pcDomainName, p_bProbeResult); + }; + } + else + { + _SH2Ptr(p_hMDNSService)->m_ProbeInformation.m_fnProbeResultCallback = 0; + } + } + return bResult; +} + +/* + MDNSResponder::serviceStatus +*/ +bool MDNSResponder::serviceStatus(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const +{ + return ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && + (_SH2Ptr(p_hMDNSService)->probeStatus())); +} + + +/* + SERVICE TXT +*/ + +/* + MDNSResponder::addServiceTxt + + Add a static service TXT item ('Key'='Value') to a service. + +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + const char* p_pcValue) +{ + hMDNSTxt hTxt = (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) + ? (hMDNSTxt)_NRH2Ptr(p_hMDNSHost)->addServiceTxt(_SH2Ptr(p_hMDNSService), p_pcKey, p_pcValue) + : 0); + DEBUG_EX_ERR(if (!hTxt) DEBUG_OUTPUT.printf_P(PSTR("%s addServiceTxt: FAILED for '%s=%s'!\n"), _DH(p_hMDNSHost), (p_pcKey ? : "-"), (p_pcValue ? : "-"));); + return hTxt; +} + +/* + MDNSRESPONDER_xxx_TO_CHAR + Formats: http://www.cplusplus.com/reference/cstdio/printf/ +*/ +#define MDNSRESPONDER_U32_TO_CHAR(BUFFERNAME, U32VALUE) \ + char BUFFERNAME[16]; /* 32-bit max 10 digits */ \ + *BUFFERNAME = 0; \ + sprintf(BUFFERNAME, "%u", U32VALUE); +#define MDNSRESPONDER_U16_TO_CHAR(BUFFERNAME, U16VALUE) \ + char BUFFERNAME[8]; /* 16-bit max 5 digits */ \ + *BUFFERNAME = 0; \ + sprintf(BUFFERNAME, "%hu", U16VALUE); +#define MDNSRESPONDER_U8_TO_CHAR(BUFFERNAME, U8VALUE) \ + char BUFFERNAME[8]; /* 8-bit max 3 digits */ \ + *BUFFERNAME = 0; \ + sprintf(BUFFERNAME, "%hhu", U8VALUE); +#define MDNSRESPONDER_I32_TO_CHAR(BUFFERNAME, I32VALUE) \ + char BUFFERNAME[16]; /* 32-bit max 10 digits */ \ + *BUFFERNAME = 0; \ + sprintf(BUFFERNAME, "%i", I32VALUE); +#define MDNSRESPONDER_I16_TO_CHAR(BUFFERNAME, I16VALUE) \ + char BUFFERNAME[8]; /* 16-bit max 5 digits */ \ + *BUFFERNAME = 0; \ + sprintf(BUFFERNAME, "%hi", I16VALUE); +#define MDNSRESPONDER_I8_TO_CHAR(BUFFERNAME, I8VALUE) \ + char BUFFERNAME[8]; /* 8-bit max 3 digits */ \ + *BUFFERNAME = 0; \ + sprintf(BUFFERNAME, "%hhi", I8VALUE); + +/* + MDNSResponder::addServiceTxt (uint32_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint32_t p_u32Value) +{ + MDNSRESPONDER_U32_TO_CHAR(acBuffer, p_u32Value); + return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addServiceTxt (uint16_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint16_t p_u16Value) +{ + MDNSRESPONDER_U16_TO_CHAR(acBuffer, p_u16Value); + return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addServiceTxt (uint8_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint8_t p_u8Value) +{ + MDNSRESPONDER_U8_TO_CHAR(acBuffer, p_u8Value); + return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addServiceTxt (int32_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int32_t p_i32Value) +{ + MDNSRESPONDER_I32_TO_CHAR(acBuffer, p_i32Value); + return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addServiceTxt (int16_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int16_t p_i16Value) +{ + MDNSRESPONDER_I16_TO_CHAR(acBuffer, p_i16Value); + return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addServiceTxt (int8_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int8_t p_i8Value) +{ + MDNSRESPONDER_I8_TO_CHAR(acBuffer, p_i8Value); + return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::removeServiceTxt + + Remove a static service TXT item from a service. +*/ +bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const MDNSResponder::hMDNSTxt p_hTxt) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && + (p_hTxt) && + (_NRH2Ptr(p_hMDNSHost)->removeServiceTxt(_SH2Ptr(p_hMDNSService), (clsHost::stcServiceTxt*)p_hTxt))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeServiceTxt: FAILED!\n"), _DH(p_hMDNSHost));); + return bResult; +} + +/* + MDNSResponder::removeServiceTxt +*/ +bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && + (p_pcKey) && + (_NRH2Ptr(p_hMDNSHost)->removeServiceTxt(_SH2Ptr(p_hMDNSService), _NRH2Ptr(p_hMDNSHost)->findServiceTxt(_SH2Ptr(p_hMDNSService), p_pcKey)))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeServiceTxt: FAILED!\n"), _DH(p_hMDNSHost));); + return bResult; +} + +/* + MDNSResponder::setDynamicServiceTxtCallback (binding) + + Set a netif binding specific callback for dynamic service TXT items. The callback is called, whenever + service TXT items are needed for any service on the netif binding. + +*/ +bool MDNSResponder::setDynamicServiceTxtCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, + MDNSResponder::MDNSDynamicServiceTxtCallbackFn p_fnCallback) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && + ((!p_fnCallback) || + (_NRH2Ptr(p_hMDNSHost)->setDynamicServiceTxtCallback([this, p_fnCallback](clsHost & p_rHost, + clsHost::stcService & p_rMDNSService)->void + { + if (p_fnCallback) + { + p_fnCallback(*this, (hMDNSHost)&p_rHost, (hMDNSService)&p_rMDNSService); + } + })))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setDynamicServiceTxtCallback: FAILED!\n"), _DH(p_hMDNSHost));); + return bResult; +} + +/* + MDNSResponder::setDynamicServiceTxtCallback (service) + + Set a service specific callback for dynamic service TXT items. The callback is called, whenever + service TXT items are needed for the given service. +*/ +bool MDNSResponder::setDynamicServiceTxtCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + MDNSResponder::MDNSDynamicServiceTxtCallbackFn p_fnCallback) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && + ((!p_fnCallback) || + (_NRH2Ptr(p_hMDNSHost)->setDynamicServiceTxtCallback(_SH2Ptr(p_hMDNSService), [this, p_fnCallback](clsHost & p_rHost, + clsHost::stcService & p_rMDNSService)->void + { + if (p_fnCallback) + { + p_fnCallback(*this, (hMDNSHost)&p_rHost, (hMDNSService)&p_rMDNSService); + } + })))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setDynamicServiceTxtCallback: FAILED!\n"), _DH(p_hMDNSHost));); + return bResult; +} + +/* + MDNSResponder::addDynamicServiceTxt +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + const char* p_pcValue) +{ + hMDNSTxt hTxt = (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) + ? (hMDNSTxt)_NRH2Ptr(p_hMDNSHost)->addDynamicServiceTxt(_SH2Ptr(p_hMDNSService), p_pcKey, p_pcValue) + : 0); + DEBUG_EX_ERR(if (!hTxt) DEBUG_OUTPUT.printf_P(PSTR("%s addServiceTxt: FAILED for '%s=%s'!\n"), _DH(p_hMDNSHost), (p_pcKey ? : "-"), (p_pcValue ? : "-"));); + return hTxt; +} + +/* + MDNSResponder::addDynamicServiceTxt (uint32_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint32_t p_u32Value) +{ + MDNSRESPONDER_U32_TO_CHAR(acBuffer, p_u32Value); + return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addDynamicServiceTxt (uint16_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint16_t p_u16Value) +{ + MDNSRESPONDER_U16_TO_CHAR(acBuffer, p_u16Value); + return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addDynamicServiceTxt (uint8_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint8_t p_u8Value) +{ + MDNSRESPONDER_U8_TO_CHAR(acBuffer, p_u8Value); + return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addDynamicServiceTxt (int32_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int32_t p_i32Value) +{ + MDNSRESPONDER_I32_TO_CHAR(acBuffer, p_i32Value); + return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addDynamicServiceTxt (int16_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int16_t p_i16Value) +{ + MDNSRESPONDER_I16_TO_CHAR(acBuffer, p_i16Value); + return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addDynamicServiceTxt (int8_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int8_t p_i8Value) +{ + MDNSRESPONDER_I8_TO_CHAR(acBuffer, p_i8Value); + return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); +} + + +/** + QUERIES +*/ + + +/** + MDNSResponder::clsMDNSAnswerAccessor + +*/ + +/* + MDNSResponder::clsMDNSAnswerAccessor::clsMDNSAnswerAccessor constructor +*/ +MDNSResponder::clsMDNSAnswerAccessor::clsMDNSAnswerAccessor(const MDNSResponder::clsHost::stcQuery::stcAnswer* p_pAnswer) + : m_pAnswer(p_pAnswer) +{ + if ((m_pAnswer) && + (txtsAvailable())) + { + // Prepare m_TxtKeyValueMap + for (const clsHost::stcServiceTxt* pTxt = m_pAnswer->m_Txts.m_pTxts; pTxt; pTxt = pTxt->m_pNext) + { + m_TxtKeyValueMap.emplace(std::pair<const char*, const char*>(pTxt->m_pcKey, pTxt->m_pcValue)); + } + } +} + +/* + MDNSResponder::clsMDNSAnswerAccessor::~clsMDNSAnswerAccessor destructor +*/ +MDNSResponder::clsMDNSAnswerAccessor::~clsMDNSAnswerAccessor(void) +{ +} + +/** + MDNSResponder::clsMDNSAnswerAccessor::stcCompareTxtKey +*/ + +/* + MDNSResponder::clsMDNSAnswerAccessor::stcCompareTxtKey::operator() +*/ +bool MDNSResponder::clsMDNSAnswerAccessor::stcCompareTxtKey::operator()(char const* p_pA, + char const* p_pB) const +{ + return (0 > strcasecmp(p_pA, p_pB)); +} + +/* + MDNSResponder::clsMDNSAnswerAccessor::serviceDomainAvailable +*/ +bool MDNSResponder::clsMDNSAnswerAccessor::serviceDomainAvailable(void) const +{ + return ((m_pAnswer) && + (m_pAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::ServiceDomain))); +} + +/* + MDNSResponder::clsMDNSAnswerAccessor::serviceDomain +*/ +const char* MDNSResponder::clsMDNSAnswerAccessor::serviceDomain(void) const +{ + return ((m_pAnswer) + ? m_pAnswer->m_ServiceDomain.c_str() + : 0); +} + +/* + MDNSResponder::clsMDNSAnswerAccessor::hostDomainAvailable +*/ +bool MDNSResponder::clsMDNSAnswerAccessor::hostDomainAvailable(void) const +{ + return ((m_pAnswer) && + (m_pAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain))); +} + +/* + MDNSResponder::clsMDNSAnswerAccessor::hostDomain +*/ +const char* MDNSResponder::clsMDNSAnswerAccessor::hostDomain(void) const +{ + return ((m_pAnswer) + ? m_pAnswer->m_HostDomain.c_str() + : 0); +} + +/* + MDNSResponder::clsMDNSAnswerAccessor::hostPortAvailable +*/ +bool MDNSResponder::clsMDNSAnswerAccessor::hostPortAvailable(void) const +{ + return ((m_pAnswer) && + (m_pAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::Port))); +} + +/* + MDNSResponder::clsMDNSAnswerAccessor::hostPort +*/ +uint16_t MDNSResponder::clsMDNSAnswerAccessor::hostPort(void) const +{ + return ((m_pAnswer) + ? (m_pAnswer->m_u16Port) + : 0); +} + +#ifdef MDNS_IPV4_SUPPORT +/* + MDNSResponder::clsMDNSAnswerAccessor::IPv4AddressAvailable +*/ +bool MDNSResponder::clsMDNSAnswerAccessor::IPv4AddressAvailable(void) const +{ + return ((m_pAnswer) && + (m_pAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address))); +} + +/* + MDNSResponder::clsMDNSAnswerAccessor::IPv4Addresses +*/ +std::vector<IPAddress> MDNSResponder::clsMDNSAnswerAccessor::IPv4Addresses(void) const +{ + std::vector<IPAddress> internalIP; + if ((m_pAnswer) && + (IPv4AddressAvailable())) + { + for (uint32_t u = 0; u < m_pAnswer->IPv4AddressCount(); ++u) + { + const clsHost::stcQuery::stcAnswer::stcIPAddress* pIPAddr = m_pAnswer->IPv4AddressAtIndex(u); + if (pIPAddr) + { + internalIP.emplace_back(pIPAddr->m_IPAddress); + } + } + } + return internalIP; +} +#endif + +#ifdef MDNS_IPV6_SUPPORT +/* + MDNSResponder::clsMDNSAnswerAccessor::IPv6AddressAvailable +*/ +bool MDNSResponder::clsMDNSAnswerAccessor::IPv6AddressAvailable(void) const +{ + return ((m_pAnswer) && + (m_pAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address))); +} + +/* + MDNSResponder::clsMDNSAnswerAccessor::IPv6Addresses +*/ +std::vector<IPAddress> MDNSResponder::clsMDNSAnswerAccessor::IPv6Addresses(void) const +{ + std::vector<IPAddress> internalIP; + if ((m_pAnswer) && + (IPv6AddressAvailable())) + { + for (uint32_t u = 0; u < m_pAnswer->IPv6AddressCount(); ++u) + { + const clsHost::stcQuery::stcAnswer::stcIPAddress* pIPAddr = m_pAnswer->IPv6AddressAtIndex(u); + if (pIPAddr) + { + internalIP.emplace_back(pIPAddr->m_IPAddress); + } + } + } + return internalIP; +} +#endif + +/* + MDNSResponder::clsMDNSAnswerAccessor::txtsAvailable +*/ +bool MDNSResponder::clsMDNSAnswerAccessor::txtsAvailable(void) const +{ + return ((m_pAnswer) && + (m_pAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts))); +} + +/* + MDNSResponder::clsMDNSAnswerAccessor::txts + + Returns all TXT items for the given service as a ';'-separated string. + If not already existing; the string is alloced, filled and attached to the answer. +*/ +const char* MDNSResponder::clsMDNSAnswerAccessor::txts(void) const +{ + return ((m_pAnswer) + ? m_pAnswer->m_Txts.c_str() + : 0); +} + +/* + MDNSResponder::clsMDNSAnswerAccessor::txtKeyValues +*/ +const MDNSResponder::clsMDNSAnswerAccessor::clsTxtKeyValueMap& MDNSResponder::clsMDNSAnswerAccessor::txtKeyValues(void) const +{ + return m_TxtKeyValueMap; +} + +/* + MDNSResponder::clsMDNSAnswerAccessor::txtValue +*/ +const char* MDNSResponder::clsMDNSAnswerAccessor::txtValue(const char* p_pcKey) const +{ + char* pcResult = 0; + + if (m_pAnswer) + { + for (const clsHost::stcServiceTxt* pTxt = m_pAnswer->m_Txts.m_pTxts; pTxt; pTxt = pTxt->m_pNext) + { + if ((p_pcKey) && + (0 == strcasecmp(pTxt->m_pcKey, p_pcKey))) + { + pcResult = pTxt->m_pcValue; + break; + } + } + } + return pcResult; +} + +/* + MDNSResponder::clsMDNSAnswerAccessor::printTo + **/ +size_t MDNSResponder::clsMDNSAnswerAccessor::printTo(Print& p_Print) const +{ + size_t stLen = 0; + const char* cpcI = " * "; + const char* cpcS = " "; + + stLen += p_Print.println(" * * * * *"); + if (hostDomainAvailable()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print("Host domain: "); + stLen += p_Print.println(hostDomain()); + } +#ifdef MDNS_IPV4_SUPPORT + if (IPv4AddressAvailable()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.println("IPv4 address(es):"); + for (const IPAddress& addr : IPv4Addresses()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print(cpcS); + stLen += p_Print.println(addr); + } + } +#endif +#ifdef MDNS_IPV6_SUPPORT + if (IPv6AddressAvailable()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.println("IPv6 address(es):"); + for (const IPAddress& addr : IPv6Addresses()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print(cpcS); + stLen += p_Print.println(addr); + } + } +#endif + if (serviceDomainAvailable()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print("Service domain: "); + stLen += p_Print.println(serviceDomain()); + } + if (hostPortAvailable()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print("Host port: "); + stLen += p_Print.println(hostPort()); + } + if (txtsAvailable()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print("TXTs:"); + for (auto const& x : txtKeyValues()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print(cpcS); + stLen += p_Print.print(x.first); + stLen += p_Print.print("="); + stLen += p_Print.println(x.second); + } + } + stLen += p_Print.println(" * * * * *"); + + return stLen; +} + +/** + STATIC QUERIES +*/ + +/* + MDNSResponder::queryService + + Perform a (blocking) static service query. + The arrived answers can be queried by calling: + - answerHostName (or 'hostname') + - answerIP (or 'IP') + - answerPort (or 'port') + +*/ +uint32_t MDNSResponder::queryService(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService '_%s._%s.local'\n"), _DH(p_hMDNSHost), p_pcService, p_pcProtocol);); + + uint32_t u32Result = ((_validateMDNSHostHandle(p_hMDNSHost)) + ? (_NRH2Ptr(p_hMDNSHost)->queryService(p_pcService, p_pcProtocol, p_u16Timeout)) + : 0); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService '_%s._%s.local' returned %u hits!\n"), _DH(p_hMDNSHost), p_pcService, p_pcProtocol, u32Result);); + return u32Result; +} + +/* + MDNSResponder::queryHost + + Perform a (blocking) static host query. + The arrived answers can be queried by calling: + - answerHostName (or 'hostname') + - answerIP (or 'IP') + - answerPort (or 'port') + +*/ +uint32_t MDNSResponder::queryHost(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcHostName, + const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost '%s.local'\n"), _DH(p_hMDNSHost), p_pcHostName);); + + uint32_t u32Result = ((_validateMDNSHostHandle(p_hMDNSHost)) + ? (_NRH2Ptr(p_hMDNSHost)->queryHost(p_pcHostName, p_u16Timeout)) + : 0); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost '%s.local' returned %u hits!\n"), _DH(p_hMDNSHost), p_pcHostName, u32Result);); + return u32Result; +} + +/* + MDNSResponder::removeQuery + + Remove the last static query (and all answers). + +*/ +bool MDNSResponder::removeQuery(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_NRH2Ptr(p_hMDNSHost)->removeQuery())); +} + +/* + MDNSResponder::hasQuery + + Return 'true', if a static query is currently installed + +*/ +bool MDNSResponder::hasQuery(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (0 != _NRH2Ptr(p_hMDNSHost)->hasQuery())); +} + +/* + MDNSResponder::getQuery + + Return handle to the last static query + +*/ +MDNSResponder::hMDNSQuery MDNSResponder::getQuery(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + return (_validateMDNSHostHandle(p_hMDNSHost) + ? (hMDNSQuery)_NRH2Ptr(p_hMDNSHost)->getQuery() + : 0); +} + + +/* + MDNSResponder::answerAccessors +*/ +MDNSResponder::clsMDNSAnswerAccessorVector MDNSResponder::answerAccessors(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + hMDNSQuery hLegacyQuery = getQuery(p_hMDNSHost); + return ((hLegacyQuery) + ? answerAccessors(p_hMDNSHost, hLegacyQuery) + : clsMDNSAnswerAccessorVector()); +} + +/* + MDNSResponder::answerCount +*/ +uint32_t MDNSResponder::answerCount(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + hMDNSQuery hLegacyQuery = getQuery(p_hMDNSHost); + return ((hLegacyQuery) + ? answerCount(p_hMDNSHost, hLegacyQuery) + : 0); +} + +/* + MDNSResponder::answerAccessor +*/ +MDNSResponder::clsMDNSAnswerAccessor MDNSResponder::answerAccessor(const MDNSResponder::hMDNSHost p_hMDNSHost, + uint32_t p_u32AnswerIndex) +{ + hMDNSQuery hLegacyQuery = getQuery(p_hMDNSHost); + return ((hLegacyQuery) + ? answerAccessor(p_hMDNSHost, hLegacyQuery, p_u32AnswerIndex) + : clsMDNSAnswerAccessor(0)); +} + + + +#ifdef NOTUSED + +/* + MDNSResponder::answerHostName +*/ +const char* MDNSResponder::answerHostName(const MDNSResponder::hMDNSHost p_hMDNSHost, + const uint32_t p_u32AnswerIndex) +{ + const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); + stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); + + if ((pSQAnswer) && + (pSQAnswer->m_HostDomain.m_u16NameLength) && + (!pSQAnswer->m_pcHostDomain)) + { + char* pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); + if (pcHostDomain) + { + pSQAnswer->m_HostDomain.c_str(pcHostDomain); + } + } + return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); +} + +#ifdef MDNS_IPV4_SUPPORT +/* + MDNSResponder::answerIPv4 +*/ +IPAddress MDNSResponder::answerIPv4(const MDNSResponder::hMDNSHost p_hMDNSHost, + const uint32_t p_u32AnswerIndex) +{ + const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); + const stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); + const stcQuery::stcAnswer::stcIPv4Address* pIPv4Address = (((pSQAnswer) && (pSQAnswer->m_pIPv4Addresses)) ? pSQAnswer->IPv4AddressAtIndex(0) : 0); + return (pIPv4Address ? pIPv4Address->m_IPAddress : IPAddress()); +} +#endif + +#ifdef MDNS_IPV6_SUPPORT +/* + MDNSResponder::answerIPv6 +*/ +IPAddress MDNSResponder::answerIPv6(const MDNSResponder::hMDNSHost p_hMDNSHost, + const uint32_t p_u32AnswerIndex) +{ + const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); + const stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); + const stcQuery::stcAnswer::stcIPv6Address* pIPv6Address = (((pSQAnswer) && (pSQAnswer->m_pIPv6Addresses)) ? pSQAnswer->IPv6AddressAtIndex(0) : 0); + return (pIPv6Address ? pIPv6Address->m_IPAddress : IPAddress()); +} +#endif + +/* + MDNSResponder::answerPort +*/ +uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSHost p_hMDNSHost, + const uint32_t p_u32AnswerIndex) +{ + const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); + const stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return (pSQAnswer ? pSQAnswer->m_u16Port : 0); +} + +#endif + + +/** + DYNAMIC SERVICE QUERY +*/ + +/* + MDNSResponder::installServiceQuery + + Add a dynamic service query and a corresponding callback to the MDNS responder. + The callback will be called for every answer update. + The answers can also be queried by calling: + - answerServiceDomain + - answerHostDomain + - answerIPv4Address/answerIPv6Address + - answerPort + - answerTxts + +*/ +MDNSResponder::hMDNSQuery MDNSResponder::installServiceQuery(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcService, + const char* p_pcProtocol, + MDNSResponder::MDNSQueryCallbackFn p_fnCallback) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService '_%s._%s.local'\n"), _DH(p_hMDNSHost), p_pcService, p_pcProtocol);); + + hMDNSQuery hResult = ((_validateMDNSHostHandle(p_hMDNSHost)) + ? (_NRH2Ptr(p_hMDNSHost)->installServiceQuery(p_pcService, p_pcProtocol, [this, p_fnCallback](clsHost & p_rHost, + const clsHost::stcQuery & p_Query, + const clsHost::stcQuery::stcAnswer & p_Answer, + clsHost::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)->void + { + if (p_fnCallback) + { + p_fnCallback(*this, (hMDNSHost)&p_rHost, (hMDNSQuery)&p_Query, clsMDNSAnswerAccessor(&p_Answer), p_QueryAnswerTypeFlags, p_bSetContent); + } + })) + : 0); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s installServiceQuery: %s for '_%s._%s.local'!\n\n"), _DH(p_hMDNSHost), (hResult ? "Succeeded" : "FAILED"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); + DEBUG_EX_ERR(if (!hResult) DEBUG_OUTPUT.printf_P(PSTR("%s installServiceQuery: FAILED for '_%s._%s.local'!\n\n"), _DH(p_hMDNSHost), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); + return hResult; +} + +/* + MDNSResponder::installHostQuery +*/ +MDNSResponder::hMDNSQuery MDNSResponder::installHostQuery(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcHostName, + MDNSResponder::MDNSQueryCallbackFn p_fnCallback) +{ + hMDNSQuery hResult = ((_validateMDNSHostHandle(p_hMDNSHost)) + ? (_NRH2Ptr(p_hMDNSHost)->installHostQuery(p_pcHostName, [this, p_fnCallback](clsHost & p_rHost, + const clsHost::stcQuery & p_Query, + const clsHost::stcQuery::stcAnswer & p_Answer, + clsHost::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)->void + { + if (p_fnCallback) + { + p_fnCallback(*this, (hMDNSHost)&p_rHost, (hMDNSQuery)&p_Query, clsMDNSAnswerAccessor(&p_Answer), p_QueryAnswerTypeFlags, p_bSetContent); + } + })) + : 0); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s installHostQuery: %s for '%s.local'!\n\n"), _DH(p_hMDNSHost), (hResult ? "Succeeded" : "FAILED"), (p_pcHostName ? : "-"));); + DEBUG_EX_ERR(if (!hResult) DEBUG_OUTPUT.printf_P(PSTR("%s installHostQuery: FAILED for '%s.local'!\n\n"), _DH(p_hMDNSHost), (p_pcHostName ? : "-"));); + return hResult; +} + +/* + MDNSResponder::removeQuery + + Remove a dynamic query (and all collected answers) from the MDNS responder + +*/ +bool MDNSResponder::removeQuery(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && + (p_hMDNSQuery) && + (_NRH2Ptr(p_hMDNSHost)->removeQuery((clsHost::stcQuery*)p_hMDNSQuery))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeQuery: FAILED!\n"), _DH(p_hMDNSHost));); + return bResult; +} + +/* + MDNSResponder::answerAccessors +*/ +MDNSResponder::clsMDNSAnswerAccessorVector MDNSResponder::answerAccessors(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery) +{ + clsMDNSAnswerAccessorVector tempVector; + for (uint32_t u = 0; u < answerCount(p_hMDNSHost, p_hMDNSQuery); ++u) + { + clsHost::stcQuery::stcAnswer* pAnswer = 0; + if ((_validateMDNSHostHandle(p_hMDNSHost)) && + (p_hMDNSQuery) && + ((pAnswer = ((clsHost::stcQuery*)p_hMDNSQuery)->answerAtIndex(u)))) + { + tempVector.emplace_back(clsMDNSAnswerAccessor(pAnswer)); + //tempVector.emplace_back(*pAnswer); + } + } + return tempVector; +} + +/* + MDNSResponder::answerCount +*/ +uint32_t MDNSResponder::answerCount(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery) +{ + _validateMDNSHostHandle(p_hMDNSHost); + return ((clsHost::stcQuery*)p_hMDNSQuery)->answerCount(); +} + +/* + MDNSResponder::answerAccessor +*/ +MDNSResponder::clsMDNSAnswerAccessor MDNSResponder::answerAccessor(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + uint32_t p_u32AnswerIndex) +{ + clsHost::stcQuery::stcAnswer* pAnswer = (((_validateMDNSHostHandle(p_hMDNSHost)) && + (p_hMDNSQuery)) + ? ((clsHost::stcQuery*)p_hMDNSQuery)->answerAtIndex(p_u32AnswerIndex) + : 0); + return MDNSResponder::clsMDNSAnswerAccessor(pAnswer); +} + +#ifdef LATER +/* + MDNSResponder::hasAnswerServiceDomain +*/ +bool MDNSResponder::hasAnswerServiceDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::ServiceDomain))); +} + + /* + MDNSResponder::answerServiceDomain + + Returns the domain for the given service. + If not already existing, the string is allocated, filled and attached to the answer. + + */ + const char* MDNSResponder::answerServiceDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + // Fill m_pcServiceDomain (if not already done) + if ((pSQAnswer) && + (pSQAnswer->m_ServiceDomain.m_u16NameLength) && + (!pSQAnswer->m_pcServiceDomain)) +{ + + pSQAnswer->m_pcServiceDomain = pSQAnswer->allocServiceDomain(pSQAnswer->m_ServiceDomain.c_strLength()); + if (pSQAnswer->m_pcServiceDomain) + { + pSQAnswer->m_ServiceDomain.c_str(pSQAnswer->m_pcServiceDomain); + } + } + return (pSQAnswer ? pSQAnswer->m_pcServiceDomain : 0); +} + +/* + MDNSResponder::hasAnswerHostDomain +*/ +bool MDNSResponder::hasAnswerHostDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain))); +} + + /* + MDNSResponder::answerHostDomain + + Returns the host domain for the given service. + If not already existing, the string is allocated, filled and attached to the answer. + + */ + const char* MDNSResponder::answerHostDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + // Fill m_pcHostDomain (if not already done) + if ((pSQAnswer) && + (pSQAnswer->m_HostDomain.m_u16NameLength) && + (!pSQAnswer->m_pcHostDomain)) +{ + + pSQAnswer->m_pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); + if (pSQAnswer->m_pcHostDomain) + { + pSQAnswer->m_HostDomain.c_str(pSQAnswer->m_pcHostDomain); + } + } + return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); +} + +#ifdef MDNS_IPV4_SUPPORT +/* + MDNSResponder::hasAnswerIPv4Address +*/ +bool MDNSResponder::hasAnswerIPv4Address(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address))); +} + + /* + MDNSResponder::answerIPv4AddressCount + */ + uint32_t MDNSResponder::answerIPv4AddressCount(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return (pSQAnswer ? pSQAnswer->IPv4AddressCount() : 0); +} + + /* + MDNSResponder::answerIPv4Address + */ + IPAddress MDNSResponder::answerIPv4Address(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + stcQuery::stcAnswer::stcIPv4Address* pIPv4Address = (pSQAnswer ? pSQAnswer->IPv4AddressAtIndex(p_u32AddressIndex) : 0); + return (pIPv4Address ? pIPv4Address->m_IPAddress : IPAddress()); +} +#endif + +#ifdef MDNS_IPV6_SUPPORT + /* + MDNSResponder::hasAnswerIPv6Address + */ + bool MDNSResponder::hasAnswerIPv6Address(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address))); +} + + /* + MDNSResponder::answerIPv6AddressCount + */ + uint32_t MDNSResponder::answerIPv6AddressCount(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return (pSQAnswer ? pSQAnswer->IPv6AddressCount() : 0); +} + + /* + MDNSResponder::answerIPv6Address + */ + IPAddress MDNSResponder::answerIPv6Address(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + stcQuery::stcAnswer::stcIPv6Address* pIPv6Address = (pSQAnswer ? pSQAnswer->IPv6AddressAtIndex(p_u32AddressIndex) : 0); + return (pIPv6Address ? pIPv6Address->m_IPAddress : IPAddress()); +} +#endif + + /* + MDNSResponder::hasAnswerPort + */ + bool MDNSResponder::hasAnswerPort(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::Port))); +} + + /* + MDNSResponder::answerPort + */ + uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return (pSQAnswer ? pSQAnswer->m_u16Port : 0); +} + + /* + MDNSResponder::hasAnswerTxts + */ + bool MDNSResponder::hasAnswerTxts(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts))); +} + + /* + MDNSResponder::answerTxts + + Returns all TXT items for the given service as a ';'-separated string. + If not already existing; the string is alloced, filled and attached to the answer. + + */ + const char* MDNSResponder::answerTxts(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + // Fill m_pcTxts (if not already done) + if ((pSQAnswer) && + (pSQAnswer->m_Txts.m_pTxts) && + (!pSQAnswer->m_pcTxts)) +{ + + pSQAnswer->m_pcTxts = pSQAnswer->allocTxts(pSQAnswer->m_Txts.c_strLength()); + if (pSQAnswer->m_pcTxts) + { + pSQAnswer->m_Txts.c_str(pSQAnswer->m_pcTxts); + } + } + return (pSQAnswer ? pSQAnswer->m_pcTxts : 0); +} + + +/* + PROBING +*/ + +/* + MDNSResponder::setHostProbeResultCallback + + Set a callback for probe results. The callback is called, when probing + for the host domain failes or succeedes. + In the case of failure, the domain name should be changed via 'setHostName' + When succeeded, the host domain will be announced by the MDNS responder. + +*/ +bool MDNSResponder::setHostProbeResultCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, + MDNSResponder::MDNSHostProbeResultCallbackFn p_fnCallback) +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (((clsHost*)p_hMDNSHost)->m_HostProbeInformation.m_fnProbeResultCallback = p_fnCallback, true)); +} + + +/* + MISC +*/ + +/* + MDNSResponder::notifyNetIfChange + + Should be called, whenever the AP for the MDNS responder changes. + A bit of this is caught by the event callbacks installed in the constructor. + +*/ +bool MDNSResponder::notifyNetIfChange(netif* p_pNetIf) +{ + clsHost* pMDNSHost; + return (((pMDNSHost = _findHost(p_pNetIf))) && + (_restart(*pMDNSHost))); +} + +/* + MDNSResponder::update + + Should be called in every 'loop'. + +*/ +bool MDNSResponder::update(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_process(*(clsHost*)p_hMDNSHost, true))); +} + +/* + MDNSResponder::update (convenience) +*/ +bool MDNSResponder::update(void) +{ + bool bResult = true; + for (clsHost*& pMDNSHost : m_HostList) + { + if (!_process(*it, true)) + { + bResult = false; + } + } + return bResult; +} + +/* + MDNSResponder::announce (convenience) + + Should be called, if the 'configuration' changes. Mainly this will be changes in the TXT items... +*/ +bool MDNSResponder::announce(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_announce(*(clsHost*)p_hMDNSHost, true, true))); +} + +/* + MDNSResponder::announce (convenience) +*/ +bool MDNSResponder::announce(void) +{ + bool bResult = true; + for (clsHost*& pMDNSHost : m_HostList) + { + if (!_announce(*it, true, true)) + { + bResult = false; + } + } + return bResult; +} + +/* + MDNSResponder::enableArduino + + Enable the OTA update service. + +*/ +MDNSResponder::hMDNSService MDNSResponder::enableArduino(const MDNSResponder::hMDNSHost p_hMDNSHost, + uint16_t p_u16Port, + bool p_bAuthUpload /*= false*/) +{ + hMDNSService hService = addService(p_hMDNSHost, 0, "arduino", "tcp", p_u16Port); + if (hService) + { + if ((!addServiceTxt(p_hMDNSHost, hService, "tcp_check", "no")) || + (!addServiceTxt(p_hMDNSHost, hService, "ssh_upload", "no")) || + (!addServiceTxt(p_hMDNSHost, hService, "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD))) || + (!addServiceTxt(p_hMDNSHost, hService, "auth_upload", (p_bAuthUpload) ? "yes" : "no"))) + { + + removeService(p_hMDNSHost, hService); + hService = 0; + } + } + return hService; +} +#endif // LATER + +#ifdef __MDNS_USE_LEGACY + +/** + INTERFACE +*/ + +/** + MDNSResponder::MDNSResponder +*/ +MDNSResponder::MDNSResponder(void) + : m_pUDPContext(0) +{ +} + +/* + MDNSResponder::~MDNSResponder +*/ +MDNSResponder::~MDNSResponder(void) +{ + close(); +} + + +/* + MDNSResponder::getHost (netif) +*/ +MDNSResponder::hMDNSHost MDNSResponder::getHost(netif* p_pNetIf) const +{ + return (hMDNSHost)(p_pNetIf ? _findHost(p_pNetIf) : 0); +} + +/* + MDNSResponder::getHost (WiFiMode) +*/ +MDNSResponder::hMDNSHost MDNSResponder::getHost(WiFiMode_t p_WiFiMode) const +{ + hMDNSHost hResult = 0; + + if (WIFI_STA == p_WiFiMode) + { + hResult = getHost(netif_get_by_index(WIFI_STA)); + } + else if (WIFI_AP == p_WiFiMode) + { + hResult = getHost(netif_get_by_index(WIFI_AP)); + } + return hResult; +} + +/* + MDNSResponder::begin (hostname, netif, probe_callback) +*/ +MDNSResponder::hMDNSHost MDNSResponder::begin(const char* p_pcHostName, + netif* p_pNetIf, + MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s, netif: %u)\n"), _DH(), (p_pcHostName ? : "_"), (p_pNetIf ? netif_get_index(p_pNetIf) : 0));); + + return (hMDNSHost)_begin(p_pcHostName, p_pNetIf, p_fnCallback); +} + +/* + MDNSResponder::begin (hostname, probe_callback) +*/ +bool MDNSResponder::begin(const char* p_pcHostName, + MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s)\n"), _DH(), (p_pcHostName ? : "_"));); + + return begin(p_pcHostName, (WiFiMode_t)wifi_get_opmode(), p_fnCallback); +} + +/* + MDNSResponder::begin (hostname, WiFiMode, probe_callback) +*/ +bool MDNSResponder::begin(const char* p_pcHostName, + WiFiMode_t p_WiFiMode, + MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s, opmode: %u)\n"), _DH(), (p_pcHostName ? : "_"), (uint32_t)p_WiFiMode);); + + bool bResult = true; + + if ((bResult) && + (p_WiFiMode & WIFI_STA)) + { + bResult = (0 != _begin(p_pcHostName, netif_get_by_index(WIFI_STA), p_fnCallback)); + } + if ((bResult) && + (p_WiFiMode & WIFI_AP)) + { + bResult = (0 != _begin(p_pcHostName, netif_get_by_index(WIFI_AP), p_fnCallback)); + } + return bResult; +} + +/* + MDNSResponder::close +*/ +bool MDNSResponder::close(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_close(*(clsHost*)p_hMDNSHost))); +} + +/* + MDNSResponder::close (convenience) +*/ +bool MDNSResponder::close(void) +{ + clsHostList::iterator it(m_HostList.begin()); + while (m_HostList.end() != it) + { + _close(**it++); + } + + _releaseUDPContext(); + + return true; +} + +/* + MDNSResponder::end (ESP32) +*/ +bool MDNSResponder::end(void) +{ + return close(); +} + +/* + MDNSResponder::setHostName +*/ +bool MDNSResponder::setHostName(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcHostName) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_setHostName(*(clsHost*)p_hMDNSHost, p_pcHostName))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setHostName: FAILED for '%s'!\n"), _DH(), (p_pcHostName ? : "-"));); + return bResult; +} + +/* + MDNSResponder::setHostname (LEGACY 2) + + Set the host name in all netif bindings + +*/ +bool MDNSResponder::setHostname(const char* p_pcHostName) +{ + bool bResult = true; + for (clsHost*& pMDNSHost : m_HostList) + { + if (!setHostName((hMDNSHost)pMDNSHost, p_pcHostName)) + { + bResult = false; + } + } + return bResult; +} + +/* + MDNSResponder::setHostname (LEGACY) +*/ +bool MDNSResponder::setHostname(String p_strHostName) +{ + return setHostname(p_strHostName.c_str()); +} + +/* + MDNSResponder::hostName +*/ +const char* MDNSResponder::hostName(const MDNSResponder::hMDNSHost p_hMDNSHost) const +{ + return (_validateMDNSHostHandle(p_hMDNSHost) + ? (((clsHost*)p_hMDNSHost)->m_pcHostName) + : 0); +} + +/* + MDNSResponder::hostname (LEGACY 2) +*/ +const char* MDNSResponder::hostname(void) const +{ + return ((!m_HostList.empty()) + ? hostName((hMDNSHost)m_HostList.front()) + : 0); +} + +/* + MDNSResponder::status +*/ +bool MDNSResponder::status(const MDNSResponder::hMDNSHost p_hMDNSHost) const +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (enuProbingStatus::Done == ((clsHost*)p_hMDNSHost)->m_HostProbeInformation.m_ProbingStatus)); +} + +/* + MDNSResponder::status (LEGACY 2) +*/ +bool MDNSResponder::status(void) const +{ + bool bResult = true; + for (clsHost * const& pMDNSHost : m_HostList) + { + if (!((bResult = status((hMDNSHost)pMDNSHost)))) + { + break; + } + } + return bResult; +} + + +/* + SERVICES +*/ + +/* + MDNSResponder::setInstanceName +*/ +bool MDNSResponder::setInstanceName(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcInstanceName) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_setInstanceName(*(clsHost*)p_hMDNSHost, p_pcInstanceName))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setInstanceName: FAILED for '%s'!\n"), _DH(), (p_pcInstanceName ? : "-"));); + return bResult; +} + +/* + MDNSResponder::setInstanceName (LEGACY 2) + + Set the instance name in all netif bindings + +*/ +bool MDNSResponder::setInstanceName(const char* p_pcInstanceName) +{ + bool bResult = true; + for (clsHost*& pMDNSHost : m_HostList) + { + if (!setInstanceName((hMDNSHost)pMDNSHost, p_pcInstanceName)) + { + bResult = false; + } + } + return bResult; +} + +/* + MDNSResponder::setInstanceName (LEGACY 2) +*/ +bool MDNSResponder::setInstanceName(const String& p_strInstanceName) +{ + return setInstanceName(p_strInstanceName.c_str()); +} + +/* + MDNSResponder::addService + + Add service; using hostname if no name is explicitly provided for the service + The usual '_' underline, which is prepended to service and protocol, eg. _http, + may be given. If not, it is added automatically. + +*/ +MDNSResponder::hMDNSService MDNSResponder::addService(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + uint16_t p_u16Port) +{ + hMDNSService hService = (_validateMDNSHostHandle(p_hMDNSHost) + ? (hMDNSService)_addService(*(clsHost*)p_hMDNSHost, p_pcName, p_pcService, p_pcProtocol, p_u16Port) + : 0); + DEBUG_EX_ERR(if (!hService) DEBUG_OUTPUT.printf_P(PSTR("%s addService: FAILED for '%s._%s._%s.local'!\n"), _DH((clsHost*)p_hMDNSHost), (p_pcName ? : "-"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); + return hService; +} + +/* + MDNSResponder::addService (LEGACY 2) + + Add a service to all netif bindings. + (Only) the first service (handle) is returned. + +*/ +MDNSResponder::hMDNSService MDNSResponder::addService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + uint16_t p_u16Port) +{ + hMDNSService hResult = 0; + for (clsHost*& pMDNSHost : m_HostList) + { + hMDNSService hNewService = addService((hMDNSHost)pMDNSHost, p_pcName, p_pcService, p_pcProtocol, p_u16Port); + if (!hResult) + { + hResult = hNewService; + } + } + return hResult; +} + +/* + MDNSResponder::removeService + + Unanounce a service (by sending a goodbye message) and remove it + from the MDNS responder + +*/ +bool MDNSResponder::removeService(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && + (_removeService(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeService: FAILED!\n"), _DH((clsHost*)p_hMDNSHost));); + return bResult; +} + +/* + MDNSResponder::removeService (LEGACY 2) + + Find and remove the service from one netif binding +*/ +bool MDNSResponder::removeService(const MDNSResponder::hMDNSService p_hMDNSService) +{ + clsHost* pHost = 0; + return ((_validateMDNSHostHandle(p_hMDNSService, &pHost)) && + (removeService((hMDNSHost)pHost, p_hMDNSService))); +} + +/* + MDNSResponder::removeService +*/ +bool MDNSResponder::removeService(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol) +{ + clsHost* pMDNSHost; + stcService* pMDNSService; + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && + (pMDNSHost = (clsHost*)p_hMDNSHost) && + ((pMDNSService = _findService(*pMDNSHost, (p_pcName ? : (pMDNSHost->m_pcInstanceName ? : pMDNSHost->m_pcHostName)), p_pcService, p_pcProtocol))) && + (_removeService(*(clsHost*)p_hMDNSHost, *pMDNSService))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeService: FAILED for '%s._%s._%s.local'!\n"), _DH((clsHost*)p_hMDNSHost), (p_pcName ? : "-"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); + return bResult; +} + +/* + MDNSResponder::removeService (LEGACY 2) +*/ +bool MDNSResponder::removeService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol) +{ + bool bResult = true; + + for (clsHost*& pMDNSHost : m_HostList) + { + if (!removeService((hMDNSHost)pMDNSHost, p_pcName, p_pcService, p_pcProtocol)) + { + bResult = false; + } + } + return bResult; +} + +/* + MDNSResponder::addService (LEGACY) +*/ +bool MDNSResponder::addService(String p_strService, + String p_strProtocol, + uint16_t p_u16Port) +{ + return (0 != addService(0, p_strService.c_str(), p_strProtocol.c_str(), p_u16Port)); +} + +/* + MDNSResponder::findService + + Find an existing service. + +*/ +MDNSResponder::hMDNSService MDNSResponder::findService(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol) +{ + clsHost* pMDNSHost; + return (((_validateMDNSHostHandle(p_hMDNSHost)) && + (pMDNSHost = (clsHost*)p_hMDNSHost)) + ? _findService(*pMDNSHost, (p_pcName ? : (pMDNSHost->m_pcInstanceName ? : pMDNSHost->m_pcHostName)), p_pcService, p_pcProtocol) + : 0); +} + +/* + MDNSResponder::findService (LEGACY 2) + + (Only) the first service handle is returned. + +*/ +MDNSResponder::hMDNSService MDNSResponder::findService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol) +{ + hMDNSService hResult = 0; + for (clsHost*& pMDNSHost : m_HostList) + { + if ((hResult = findService((hMDNSHost)pMDNSHost, p_pcName, p_pcService, p_pcProtocol))) + { + break; + } + } + return hResult; +} + +/* + MDNSResponder::setServiceName +*/ +bool MDNSResponder::setServiceName(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcInstanceName) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && + (_setServiceName(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService, p_pcInstanceName))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setServiceName: FAILED for '%s'!\n"), _DH((clsHost*)p_hMDNSHost), (p_pcInstanceName ? : "-"));); + return bResult; +} + +/* + MDNSResponder::setServiceName (LEGACY 2) +*/ +bool MDNSResponder::setServiceName(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcInstanceName) +{ + clsHost* pHost = 0; + return ((_validateMDNSServiceHandle(p_hMDNSService, &pHost)) && + (setServiceName((hMDNSHost)pHost, p_hMDNSService, p_pcInstanceName))); +} + +/* + MDNSResponder::serviceName +*/ +const char* MDNSResponder::serviceName(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const +{ + return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) + ? ((stcService*)p_hMDNSService)->m_pcName + : 0); +} + +/* + MDNSResponder::serviceName (LEGACY 2) +*/ +const char* MDNSResponder::serviceName(const hMDNSService p_hMDNSService) const +{ + clsHost* pHost = 0; + return (_validateMDNSServiceHandle(p_hMDNSService, &pHost) + ? serviceName((hMDNSHost)pHost, p_hMDNSService) + : 0); +} + +/* + MDNSResponder::service +*/ +const char* MDNSResponder::service(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const +{ + return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) + ? ((stcService*)p_hMDNSService)->m_pcService + : 0); +} + +/* + MDNSResponder::service (LEGACY 2) +*/ +const char* MDNSResponder::service(const hMDNSService p_hMDNSService) const +{ + clsHost* pHost = 0; + return (_validateMDNSServiceHandle(p_hMDNSService, &pHost) + ? service((hMDNSHost)pHost, p_hMDNSService) + : 0); +} + +/* + MDNSResponder::serviceProtocol +*/ +const char* MDNSResponder::serviceProtocol(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const +{ + return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) + ? ((stcService*)p_hMDNSService)->m_pcProtocol + : 0); +} + +/* + MDNSResponder::serviceProtocol (LEGACY) +*/ +const char* MDNSResponder::serviceProtocol(const hMDNSService p_hMDNSService) const +{ + clsHost* pHost = 0; + return (_validateMDNSServiceHandle(p_hMDNSService, &pHost) + ? serviceProtocol((hMDNSHost)pHost, p_hMDNSService) + : 0); +} + +/* + MDNSResponder::serviceStatus +*/ +bool MDNSResponder::serviceStatus(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const +{ + return ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && + (enuProbingStatus::Done == ((stcService*)p_hMDNSService)->m_ProbeInformation.m_ProbingStatus)); +} + +/* + MDNSResponder::serviceStatus (LEGACY 2) + + Returns 'true' if probing for the service 'hMDNSService' is done + +*/ +bool MDNSResponder::serviceStatus(const hMDNSService p_hMDNSService) const +{ + clsHost* pHost = 0; + return (_validateMDNSServiceHandle(p_hMDNSService, &pHost) + ? serviceStatus((hMDNSHost)pHost, p_hMDNSService) + : false); +} + + +/* + SERVICE TXT +*/ + +/* + MDNSResponder::addServiceTxt + + Add a static service TXT item ('Key'='Value') to a service. + +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + const char* p_pcValue) +{ + hMDNSTxt hTxt = (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) + ? (hMDNSTxt)_addServiceTxt((clsHost*)p_hMDNSHost, (stcService*)p_hMDNSService, p_pcKey, p_pcValue, false) + : 0); + DEBUG_EX_ERR(if (!hTxt) DEBUG_OUTPUT.printf_P(PSTR("%s addServiceTxt: FAILED for '%s=%s'!\n"), _DH(), (p_pcKey ? : "-"), (p_pcValue ? : "-"));); + return hTxt; +} + +/* + MDNSResponder::addServiceTxt (LEGACY 2) + + Add a static service TXT item ('Key'='Value') to a service. + +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + const char* p_pcValue) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_pcValue) + : 0); +} + +/* + MDNSRESPONDER_xxx_TO_CHAR + Formats: http://www.cplusplus.com/reference/cstdio/printf/ +*/ +#define MDNSRESPONDER_U32_TO_CHAR(BUFFERNAME, U32VALUE) \ + char BUFFERNAME[16]; /* 32-bit max 10 digits */ \ + *BUFFERNAME = 0; \ + sprintf(BUFFERNAME, "%u", U32VALUE); +#define MDNSRESPONDER_U16_TO_CHAR(BUFFERNAME, U16VALUE) \ + char BUFFERNAME[8]; /* 16-bit max 5 digits */ \ + *BUFFERNAME = 0; \ + sprintf(BUFFERNAME, "%hu", U16VALUE); +#define MDNSRESPONDER_U8_TO_CHAR(BUFFERNAME, U8VALUE) \ + char BUFFERNAME[8]; /* 8-bit max 3 digits */ \ + *BUFFERNAME = 0; \ + sprintf(BUFFERNAME, "%hhu", U8VALUE); +#define MDNSRESPONDER_I32_TO_CHAR(BUFFERNAME, I32VALUE) \ + char BUFFERNAME[16]; /* 32-bit max 10 digits */ \ + *BUFFERNAME = 0; \ + sprintf(BUFFERNAME, "%i", I32VALUE); +#define MDNSRESPONDER_I16_TO_CHAR(BUFFERNAME, I16VALUE) \ + char BUFFERNAME[8]; /* 16-bit max 5 digits */ \ + *BUFFERNAME = 0; \ + sprintf(BUFFERNAME, "%hi", I16VALUE); +#define MDNSRESPONDER_I8_TO_CHAR(BUFFERNAME, I8VALUE) \ + char BUFFERNAME[8]; /* 8-bit max 3 digits */ \ + *BUFFERNAME = 0; \ + sprintf(BUFFERNAME, "%hhi", I8VALUE); + + +/* + MDNSResponder::addServiceTxt (uint32_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint32_t p_u32Value) +{ + MDNSRESPONDER_U32_TO_CHAR(acBuffer, p_u32Value); + return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): + } + + /* + MDNSResponder::addServiceTxt (uint32_t) (LEGACY 2) + */ + MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint32_t p_u32Value) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_u32Value) + : 0); +} + +/* + MDNSResponder::addServiceTxt (uint16_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint16_t p_u16Value) +{ + MDNSRESPONDER_U16_TO_CHAR(acBuffer, p_u16Value); + return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): + } + + /* + MDNSResponder::addServiceTxt (uint16_t) (LEGACY 2) + */ + MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint16_t p_u16Value) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_u16Value) + : 0); +} + +/* + MDNSResponder::addServiceTxt (uint8_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint8_t p_u8Value) +{ + MDNSRESPONDER_U8_TO_CHAR(acBuffer, p_u8Value); + return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): + } + + /* + MDNSResponder::addServiceTxt (uint8_t) (LEGACY 2) + */ + MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint8_t p_u8Value) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_u8Value) + : 0); +} + +/* + MDNSResponder::addServiceTxt (int32_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int32_t p_i32Value) +{ + MDNSRESPONDER_I32_TO_CHAR(acBuffer, p_i32Value); + return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): + } + + /* + MDNSResponder::addServiceTxt (int32_t) (LEGACY 2) + */ + MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int32_t p_i32Value) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_i32Value) + : 0); +} + +/* + MDNSResponder::addServiceTxt (int16_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int16_t p_i16Value) +{ + MDNSRESPONDER_I16_TO_CHAR(acBuffer, p_i16Value); + return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): + } + + /* + MDNSResponder::addServiceTxt (int16_t) (LEGACY 2) + */ + MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int16_t p_i16Value) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_i16Value) + : 0); +} + +/* + MDNSResponder::addServiceTxt (int8_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int8_t p_i8Value) +{ + MDNSRESPONDER_I8_TO_CHAR(acBuffer, p_i8Value); + return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): + } + + /* + MDNSResponder::addServiceTxt (int8_t) (LEGACY 2) + */ + MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int8_t p_i8Value) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_i8Value) + : 0); +} + +/* + MDNSResponder::removeServiceTxt + + Remove a static service TXT item from a service. +*/ +bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const MDNSResponder::hMDNSTxt p_hTxt) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && + (p_hTxt) && + (_findServiceTxt(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService, p_hTxt)) && + (_releaseServiceTxt(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService, (stcServiceTxt*)p_hTxt))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeServiceTxt: FAILED!\n"), _DH((clsHost*)p_hMDNSHost));); + return bResult; +} + +/* + MDNSResponder::removeServiceTxt (LEGACY 2) +*/ +bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const MDNSResponder::hMDNSTxt p_hTxt) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? removeServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_hTxt) + : false); +} + +/* + MDNSResponder::removeServiceTxt +*/ +bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey) +{ + stcServiceTxt* pTxt; + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && + (p_pcKey) && + ((pTxt = _findServiceTxt(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService, p_pcKey))) && + (_releaseServiceTxt(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService, pTxt))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeServiceTxt: FAILED!\n"), _DH((clsHost*)p_hMDNSHost));); + return bResult; +} + +/* + MDNSResponder::removeServiceTxt (LEGACY 2) +*/ +bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? removeServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey) + : false); +} + +/* + MDNSResponder::removeServiceTxt (LEGACY) +*/ +bool MDNSResponder::removeServiceTxt(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + const char* p_pcKey) +{ + hMDNSService hService; + return (((hService = findService(p_pcName, p_pcService, p_pcProtocol))) + ? removeServiceTxt(hService, p_pcKey) + : false); +} + +/* + MDNSResponder::addServiceTxt (LEGACY) +*/ +bool MDNSResponder::addServiceTxt(const char* p_pcService, + const char* p_pcProtocol, + const char* p_pcKey, + const char* p_pcValue) +{ + hMDNSService hService; + return (((hService = findService(p_pcName, p_pcService, p_pcProtocol))) + ? addServiceTxt(hService, p_pcKey, p_pcValue) + : false); +} + +/* + MDNSResponder::addServiceTxt (LEGACY) +*/ +bool MDNSResponder::addServiceTxt(String p_strService, + String p_strProtocol, + String p_strKey, + String p_strValue) +{ + return addServiceTxt(p_strService.c_str(), p_strProtocol.c_str(), p_strKey.c_str(), p_strValue.c_str()); +} + +/* + MDNSResponder::setDynamicServiceTxtCallback (binding) + + Set a netif binding specific callback for dynamic service TXT items. The callback is called, whenever + service TXT items are needed for any service on the netif binding. + +*/ +bool MDNSResponder::setDynamicServiceTxtCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, + MDNSResponder::MDNSDynamicServiceTxtCallbackFn p_fnCallback) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && + ((!p_fnCallback) || + ((((clsHost*)p_hMDNSHost)->m_fnServiceTxtCallback = p_fnCallback)))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setDynamicServiceTxtCallback: FAILED!\n"), _DH((clsHost*)p_hMDNSHost));); + return bResult; +} + +/* + MDNSResponder::setDynamicServiceTxtCallback (service) + + Set a service specific callback for dynamic service TXT items. The callback is called, whenever + service TXT items are needed for the given service. +*/ +bool MDNSResponder::setDynamicServiceTxtCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + MDNSResponder::MDNSDynamicServiceTxtCallbackFn p_fnCallback) +{ + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && + ((!p_fnCallback) || + ((((stcService*)p_hMDNSService)->m_fnServiceTxtCallback = p_fnCallback)))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setDynamicServiceTxtCallback: FAILED!\n"), _DH((clsHost*)p_hMDNSHost));); + return bResult; +} + +/* + MDNSResponder::setDynamicServiceTxtCallback (global) (LEGACY 2) + + Set a global callback for dynamic service TXT items. The callback is called, whenever + service TXT items are needed. + +*/ +bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::MDNSDynamicServiceTxtCallbackFn1 p_fnCallback) +{ + for (clsHostList : .iterator it : m_HostList) + { + setDynamicServiceTxtCallback((hMDNSHost)it, p_fnCallback); + } + return true; +} + +/* + MDNSResponder::setDynamicServiceTxtCallback (global) (LEGACY 2 (Fn2)) +*/ +bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::MDNSDynamicServiceTxtCallbackFn2 p_fnCallback) +{ + return setDynamicServiceTxtCallback([p_fnCallback](MDNSResponder*, const hMDNSService p_hMDNSService) + { + if (p_fnCallback) + { + p_fnCallback(p_hMDNSService); + } + }); +} + +/* + MDNSResponder::setDynamicServiceTxtCallback (service) (LEGACY 2) +*/ +bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::hMDNSService p_hMDNSService, + MDNSResponder::MDNSDynamicServiceTxtCallbackFn1 p_fnCallback) +{ + clsHost* pHost; + return ((_validateMDNSHostHandle(p_hMDNSService, &pHost)) && + (setDynamicServiceTxtCallback((hMDNSHost)pHost, hMDNSService, p_fnCallback))); +} + +/* + MDNSResponder::setDynamicServiceTxtCallback (service) (LEGACY 2 (Fn2)) +*/ +bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::hMDNSService p_hMDNSService, + MDNSResponder::MDNSDynamicServiceTxtCallbackFn2 p_fnCallback) +{ + return setDynamicServiceTxtCallback(p_hMDNSService, [p_fnCallback](MDNSResponder*, const hMDNSService p_hMDNSService) + { + if (p_fnCallback) + { + p_fnCallback(p_hMDNSService); + } + }); +} + +/* + MDNSResponder::addDynamicServiceTxt +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + const char* p_pcValue) +{ + hMDNSTxt hTxt = (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) + ? _addServiceTxt(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService, p_pcKey, p_pcValue, true) + : 0); + DEBUG_EX_ERR(if (!hTxt) DEBUG_OUTPUT.printf_P(PSTR("%s addDynamicServiceTxt: FAILED for '%s=%s'!\n"), _DH(), (p_pcKey ? : "-"), (p_pcValue ? : "-"));); + return hTxt; +} + +/* + MDNSResponder::addDynamicServiceTxt (LEGACY 2) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + const char* p_pcValue) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_pcValue) + : 0); +} + +/* + MDNSResponder::addDynamicServiceTxt (uint32_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint32_t p_u32Value) +{ + MDNSRESPONDER_U32_TO_CHAR(acBuffer, p_u32Value); + return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): + } + + /* + MDNSResponder::addDynamicServiceTxt (uint32_t) (LEGACY 2) + */ + MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint32_t p_u32Value) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_u32Value) + : 0); +} + +/* + MDNSResponder::addDynamicServiceTxt (uint16_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint16_t p_u16Value) +{ + MDNSRESPONDER_U16_TO_CHAR(acBuffer, p_u16Value); + return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): + } + + /* + MDNSResponder::addDynamicServiceTxt (uint16_t) (LEGACY 2) + */ + MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint16_t p_u16Value) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_u16Value) + : 0); +} + +/* + MDNSResponder::addDynamicServiceTxt (uint8_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint8_t p_u8Value) +{ + MDNSRESPONDER_U8_TO_CHAR(acBuffer, p_u8Value); + return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): + } + + /* + MDNSResponder::addDynamicServiceTxt (uint8_t) (LEGACY 2) + */ + MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint8_t p_u8Value) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_u8Value) + : 0); +} + +/* + MDNSResponder::addDynamicServiceTxt (int32_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int32_t p_i32Value) +{ + MDNSRESPONDER_I32_TO_CHAR(acBuffer, p_i32Value); + return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): + } + + /* + MDNSResponder::addDynamicServiceTxt (int32_t) (LEGACY 2) + */ + MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint32_t p_i32Value) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_i32Value) + : 0); +} + +/* + MDNSResponder::addDynamicServiceTxt (int16_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int16_t p_i16Value) +{ + MDNSRESPONDER_I16_TO_CHAR(acBuffer, p_i16Value); + return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): + } + + /* + MDNSResponder::addDynamicServiceTxt (int16_t) (LEGACY 2) + */ + MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint16_t p_i16Value) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_i16Value) + : 0); +} + +/* + MDNSResponder::addDynamicServiceTxt (int8_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + int8_t p_i8Value) +{ + MDNSRESPONDER_I8_TO_CHAR(acBuffer, p_i8Value); + return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): + } + + /* + MDNSResponder::addDynamicServiceTxt (int8_t) (LEGACY 2) + */ + MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, + const char* p_pcKey, + uint8_t p_i8Value) +{ + clsHost* pHost = 0; + return (_validateMDNSHostHandle(p_hMDNSService, &pHost) + ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_i8Value) + : 0); +} + + +/** + STATIC QUERIES +*/ + +/* + MDNSResponder::queryService + + Perform a (blocking) static service query. + The arrived answers can be queried by calling: + - answerHostName (or 'hostname') + - answerIP (or 'IP') + - answerPort (or 'port') + +*/ +uint32_t MDNSResponder::queryService(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService '%s.%s'\n"), _DH(), p_pcService, p_pcProtocol);); + + uint32_t u32Result = 0; + + stcQuery* pMDNSQuery = 0; + if ((_validateMDNSHostHandle(p_hMDNSHost)) && + (p_pcService) && + (os_strlen(p_pcService)) && + (p_pcProtocol) && + (os_strlen(p_pcProtocol)) && + (p_u16Timeout) && + (_removeLegacyQuery()) && + ((pMDNSQuery = _allocQuery(*(clsHost*)p_hMDNSHost, stcQuery::enuQueryType::Service))) && + (_buildDomainForService(p_pcService, p_pcProtocol, pMDNSQuery->m_Domain))) + { + pMDNSQuery->m_bLegacyQuery = true; + + if (_sendMDNSQuery(*(clsHost*)p_hMDNSHost, *pMDNSQuery)) + { + // Wait for answers to arrive + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); + delay(p_u16Timeout); + + // All answers should have arrived by now -> stop adding new answers + pMDNSQuery->m_bAwaitingAnswers = false; + u32Result = pMDNSQuery->answerCount(); + } + else // FAILED to send query + { + _removeQuery(*(clsHost*)p_hMDNSHost, pMDNSQuery); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: INVALID input data!\n"), _DH());); + } + return u32Result; +} + +/* + MDNSResponder::queryService (LEGACY 2) +*/ +uint32_t MDNSResponder::queryService(const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) +{ + return ((!m_HostList.empty()) + ? queryService((hMDNSHost)m_HostList.front(), p_pcService, p_pcProtocol, p_u16Timeout) + : 0); +} + +/* + MDNSResponder::queryService (LEGACY) +*/ +uint32_t MDNSResponder::queryService(const String& p_strService, + const String& p_strProtocol) +{ + return queryService(p_strService.c_str(), p_strProtocol.c_str()); +} + +/* + MDNSResponder::queryHost + + Perform a (blocking) static host query. + The arrived answers can be queried by calling: + - answerHostName (or 'hostname') + - answerIP (or 'IP') + - answerPort (or 'port') + +*/ +uint32_t MDNSResponder::queryHost(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcHostName, + const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost '%s.local'\n"), _DH(), p_pcHostName);); + + uint32_t u32Result = 0; + + stcQuery* pHostQuery = 0; + if ((_validateMDNSHostHandle(p_hMDNSHost)) && + (p_pcHostName) && + (os_strlen(p_pcHostName)) && + (p_u16Timeout) && + (_removeLegacyQuery()) && + ((pHostQuery = _allocQuery(*(clsHost*)p_hMDNSHost, stcQuery::enuQueryType::Host))) && + (_buildDomainForHost(p_pcHostName, pHostQuery->m_Domain))) + { + + pHostQuery->m_bLegacyQuery = true; + + if (_sendMDNSQuery(*(clsHost*)p_hMDNSHost, *pHostQuery)) + { + // Wait for answers to arrive + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); + delay(p_u16Timeout); + + // All answers should have arrived by now -> stop adding new answers + pHostQuery->m_bAwaitingAnswers = false; + u32Result = pHostQuery->answerCount(); + } + else // FAILED to send query + { + _removeQuery(*(clsHost*)p_hMDNSHost, pHostQuery); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: INVALID input data!\n"), _DH());); + } + return u32Result; +} + +/* + queryHost (LEGACY 2) +*/ +uint32_t MDNSResponder::queryHost(const char* p_pcHostName, + const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) +{ + return ((!m_HostList.empty()) + ? queryHost((hMDNSHost)m_HostList.front(), p_pcService, p_pcProtocol, p_u16Timeout) + : 0); +} + +/* + MDNSResponder::removeQuery + + Remove the last static query (and all answers). + +*/ +bool MDNSResponder::removeQuery(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_removeLegacyQuery(*(clsHost*)p_hMDNSHost))); +} + +/* + MDNSResponder::removeQuery (LEGACY 2) +*/ +bool MDNSResponder::removeQuery(void) +{ + return ((!m_HostList.empty()) + ? removeQuery((hMDNSHost)m_HostList.front()) + : false); +} + +/* + MDNSResponder::hasQuery + + Return 'true', if a static query is currently installed + +*/ +bool MDNSResponder::hasQuery(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (0 != _findLegacyQuery(*(clsHost*)p_hMDNSHost))); +} + +/* + MDNSResponder::hasQuery (LEGACY 2) +*/ +bool MDNSResponder::hasQuery(void) +{ + return ((!m_HostList.empty()) + ? hasQuery((hMDNSHost)m_HostList.front()) + : false); +} + +/* + MDNSResponder::getQuery + + Return handle to the last static query + +*/ +MDNSResponder::hMDNSQuery MDNSResponder::getQuery(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + return (_validateMDNSHostHandle(p_hMDNSHost) + ? (hMDNSQuery)_findLegacyQuery() + : 0); +} + +/* + MDNSResponder::getQuery (LEGACY 2) +*/ +MDNSResponder::hMDNSQuery MDNSResponder::getQuery(void) +{ + return ((!m_HostList.empty()) + ? getQuery((hMDNSHost)m_HostList.front()) + : false); +} + +/* + MDNSResponder::answerHostName +*/ +const char* MDNSResponder::answerHostName(const MDNSResponder::hMDNSHost p_hMDNSHost, + const uint32_t p_u32AnswerIndex) +{ + const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); + stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); + + if ((pSQAnswer) && + (pSQAnswer->m_HostDomain.m_u16NameLength) && + (!pSQAnswer->m_pcHostDomain)) + { + char* pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); + if (pcHostDomain) + { + pSQAnswer->m_HostDomain.c_str(pcHostDomain); + } + } + return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); +} + +/* + MDNSResponder::answerHostName (LEGACY 2) +*/ +const char* MDNSResponder::answerHostName(const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? answerHostName((hMDNSHost)m_HostList.front(), p_u32AnswerIndex) + : 0); +} + +/* + MDNSResponder::hostname (LEGACY) +*/ +String MDNSResponder::hostname(const uint32_t p_u32AnswerIndex) +{ + return String(answerHostName(p_u32AnswerIndex)); +} + +#ifdef MDNS_IPV4_SUPPORT +/* + MDNSResponder::answerIPv4 +*/ +IPAddress MDNSResponder::answerIPv4(const MDNSResponder::hMDNSHost p_hMDNSHost, + const uint32_t p_u32AnswerIndex) +{ + const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); + const stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); + const stcQuery::stcAnswer::stcIPv4Address* pIPv4Address = (((pSQAnswer) && (pSQAnswer->m_pIPv4Addresses)) ? pSQAnswer->IPv4AddressAtIndex(0) : 0); + return (pIPv4Address ? pIPv4Address->m_IPAddress : IPAddress()); +} + +/* + MDNSResponder::answerIPv4 (LEGACY 2) +*/ +IPAddress MDNSResponder::answerIPv4(const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? answerIPv4((hMDNSHost)m_HostList.front(), p_u32AnswerIndex) + : IPAddress()); +} + +/* + MDNSResponder::answerIP (LEGACY 2) +*/ +IPAddress MDNSResponder::answerIP(const uint32_t p_u32AnswerIndex) +{ + return answerIPv4(p_u32AnswerIndex); +} + +/* + MDNSResponder::IP (LEGACY) +*/ +IPAddress MDNSResponder::IP(const uint32_t p_u32AnswerIndex) +{ + return answerIPv4(p_u32AnswerIndex); +} +#endif + +#ifdef MDNS_IPV6_SUPPORT +/* + MDNSResponder::answerIPv6 +*/ +IPAddress MDNSResponder::answerIPv6(const MDNSResponder::hMDNSHost p_hMDNSHost, + const uint32_t p_u32AnswerIndex) +{ + const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); + const stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); + const stcQuery::stcAnswer::stcIPv6Address* pIPv6Address = (((pSQAnswer) && (pSQAnswer->m_pIPv6Addresses)) ? pSQAnswer->IPv6AddressAtIndex(0) : 0); + return (pIPv6Address ? pIPv6Address->m_IPAddress : IPAddress()); +} + +/* + MDNSResponder::answerIPv6 (LEGACY 2) +*/ +IPAddress MDNSResponder::answerIPv6(const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? answerIPv6((hMDNSHost)m_HostList.front(), p_u32AnswerIndex) + : IPAddress()); +} +#endif + +/* + MDNSResponder::answerPort +*/ +uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSHost p_hMDNSHost, + const uint32_t p_u32AnswerIndex) +{ + const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); + const stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return (pSQAnswer ? pSQAnswer->m_u16Port : 0); +} + +/* + MDNSResponder::answerPort (LEGACY 2) +*/ +uint16_t MDNSResponder::answerPort(const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? answerPort((hMDNSHost)m_HostList.front(), p_u32AnswerIndex) + : 0); +} + +/* + MDNSResponder::port (LEGACY) +*/ +uint16_t MDNSResponder::port(const uint32_t p_u32AnswerIndex) +{ + return answerPort(p_u32AnswerIndex); +} + + +/** + DYNAMIC SERVICE QUERY +*/ + +/* + MDNSResponder::installServiceQuery + + Add a dynamic service query and a corresponding callback to the MDNS responder. + The callback will be called for every answer update. + The answers can also be queried by calling: + - answerServiceDomain + - answerHostDomain + - answerIPv4Address/answerIPv6Address + - answerPort + - answerTxts + +*/ +MDNSResponder::hMDNSQuery MDNSResponder::installServiceQuery(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcService, + const char* p_pcProtocol, + MDNSResponder::MDNSQueryCallbackFn p_fnCallback) +{ + hMDNSQuery hResult = 0; + + stcQuery* pMDNSQuery = 0; + if ((_validateMDNSHostHandle(p_hMDNSHost)) && + (p_pcService) && + (os_strlen(p_pcService)) && + (p_pcProtocol) && + (os_strlen(p_pcProtocol)) && + (p_fnCallback) && + ((pMDNSQuery = _allocQuery(*(clsHost*)p_hMDNSHost, stcQuery::enuQueryType::Service))) && + (_buildDomainForService(p_pcService, p_pcProtocol, pMDNSQuery->m_Domain))) + { + + pMDNSQuery->m_fnCallback = p_fnCallback; + pMDNSQuery->m_bLegacyQuery = false; + + if (_sendMDNSQuery(*(clsHost*)p_hMDNSHost, *pMDNSQuery)) + { + pMDNSQuery->m_u8SentCount = 1; + pMDNSQuery->m_ResendTimeout.reset(MDNS_DYNAMIC_QUERY_RESEND_DELAY); + + hResult = (hMDNSQuery)pMDNSQuery; + } + else + { + _removeQuery(*(clsHost*)p_hMDNSHost, pMDNSQuery); + } + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s installServiceQuery: %s for '%s.%s'!\n\n"), _DH(), (hResult ? "Succeeded" : "FAILED"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); + DEBUG_EX_ERR(if (!hResult) DEBUG_OUTPUT.printf_P(PSTR("%s installServiceQuery: FAILED for '%s.%s'!\n\n"), _DH(), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); + return hResult; +} + +/* + MDNSResponder::installServiceQuery (LEGACY 2) +*/ +MDNSResponder::hMDNSQuery MDNSResponder::installServiceQuery(const char* p_pcService, + const char* p_pcProtocol, + MDNSResponder::MDNSQueryCallbackFn1 p_fnCallback) +{ + return ((!m_HostList.empty()) + ? installServiceQuery((hMDNSHost)m_HostList.front(), p_pcService, p_pcProtocol, [p_fnCallback])(MDNSResponder * p_pMDNSResponder, + MDNSResponder::hMDNSHost, + const stcAnswerAccessor & p_MDNSAnswerAccessor, + typeQueryAnswerType p_QueryAnswerTypeFlags, + bool p_bSetContent) + { + if (p_fnCallback) + { + p_fnCallback(p_pMDNSResponder, p_MDNSAnswerAccessor, p_QueryAnswerTypeFlags, p_bSetContent); + } + }) + : 0); + } + + /* + MDNSResponder::installServiceQuery (LEGACY 2) + */ + MDNSResponder::hMDNSQuery MDNSResponder::installServiceQuery(const char* p_pcService, + const char* p_pcProtocol, + MDNSResponder::MDNSQueryCallbackFn2 p_fnCallback) +{ + return ((!m_HostList.empty()) + ? installServiceQuery((hMDNSHost)m_HostList.front(), p_pcService, p_pcProtocol, [p_fnCallback])(MDNSResponder*, + MDNSResponder::hMDNSHost, + const stcAnswerAccessor & p_MDNSAnswerAccessor, + typeQueryAnswerType p_QueryAnswerTypeFlags, + bool p_bSetContent) + { + if (p_fnCallback) + { + p_fnCallback(p_MDNSAnswerAccessor, p_QueryAnswerTypeFlags, p_bSetContent); + } + }) + : 0); + } + + /* + MDNSResponder::installHostQuery + */ + MDNSResponder::hMDNSQuery MDNSResponder::installHostQuery(const MDNSResponder::hMDNSHost p_hMDNSHost, + const char* p_pcHostName, + MDNSResponder::MDNSQueryCallbackFn p_fnCallback) +{ + hMDNSQuery hResult = 0; + + if ((_validateMDNSHostHandle(p_hMDNSHost)) && + (p_pcHostName) && + (os_strlen(p_pcHostName))) + { + stcRRDomain domain; + hResult = ((_buildDomainForHost(p_pcHostName, domain)) + ? _installDomainQuery(*(clsHost*)p_hMDNSHost, domain, stcQuery::enuQueryType::Host, p_fnCallback) + : 0); + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s installHostQuery: %s for '%s.local'!\n\n"), _DH(), (hResult ? "Succeeded" : "FAILED"), (p_pcHostName ? : "-"));); + DEBUG_EX_ERR(if (!hResult) DEBUG_OUTPUT.printf_P(PSTR("%s installHostQuery: FAILED for '%s.local'!\n\n"), _DH(), (p_pcHostName ? : "-"));); + return hResult; +} + +/* + MDNSResponder::installHostQuery (LEGACY 2) +*/ +MDNSResponder::hMDNSQuery MDNSResponder::installHostQuery(const char* p_pcHostName, + MDNSResponder::MDNSQueryCallbackFn1 p_fnCallback) +{ + return installHostQuery(p_pcHostName, [p_fnCallback](MDNSResponder * p_pMDNSResponder, + hMDNSHost, + const stcAnswerAccessor & p_MDNSAnswerAccessor, + typeQueryAnswerType p_QueryAnswerTypeFlags, + bool p_bSetContent) + { + if (p_fnCallback) + { + p_fnCallback(p_pMDNSResponder, p_MDNSAnswerAccessor, p_QueryAnswerTypeFlags, p_bSetContent); + } + }); +} + +/* + MDNSResponder::installHostQuery (LEGACY 2) +*/ +MDNSResponder::hMDNSQuery MDNSResponder::installHostQuery(const char* p_pcHostName, + MDNSResponder::MDNSQueryCallbackFn2 p_fnCallback) +{ + return installHostQuery(p_pcHostName, [p_fnCallback](MDNSResponder*, + hMDNSHost, + const stcAnswerAccessor & p_MDNSAnswerAccessor, + typeQueryAnswerType p_QueryAnswerTypeFlags, + bool p_bSetContent) + { + if (p_fnCallback) + { + p_fnCallback(p_MDNSAnswerAccessor, p_QueryAnswerTypeFlags, p_bSetContent); + } + }); +} + +/* + MDNSResponder::removeQuery + + Remove a dynamic query (and all collected answers) from the MDNS responder + +*/ +bool MDNSResponder::removeQuery(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery) +{ + stcQuery* pMDNSQuery = 0; + bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && + ((pMDNSQuery = _findQuery(*(clsHost*)p_hMDNSHost, p_hQuery))) && + (_removeQuery(*(clsHost*)p_hMDNSHost, pMDNSQuery))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeQuery: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::removeQuery (LEGACY 2) +*/ +bool MDNSResponder::removeQuery(const MDNSResponder::hMDNSQuery p_hMDNSQuery) +{ + return ((!m_HostList.empty()) + ? removeQuery((hMDNSHost)m_HostList.front(), p_hMDNSQuery) + : false); +} + +/* + MDNSResponder::answerAccessors +*/ +MDNSResponder::clsMDNSAnswerAccessorVector MDNSResponder::answerAccessors(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery) +{ + MDNSResponder::clsMDNSAnswerAccessorVector tempVector; + for (uint32_t u = 0; u < answerCount(p_hMDNSHost, p_hMDNSQuery); ++u) + { + tempVector.emplace_back(*this, p_hMDNSQuery, u); + } + return tempVector; +} + +/* + MDNSResponder::answerAccessors (LEGACY 2) +*/ +MDNSResponder::clsMDNSAnswerAccessorVector MDNSResponder::answerAccessors(const MDNSResponder::hMDNSQuery p_hMDNSQuery) +{ + return ((!m_HostList.empty()) + ? answerAccessors((hMDNSHost)m_HostList.front(), p_hMDNSQuery) + : MDNSResponder::clsMDNSAnswerAccessorVector()); +} + +/* + MDNSResponder::answerCount +*/ +uint32_t MDNSResponder::answerCount(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery) : 0); + return (pMDNSQuery ? pMDNSQuery->answerCount() : 0); +} + +/* + MDNSResponder::answerCount (LEGACY 2) +*/ +uint32_t MDNSResponder::answerCount(const MDNSResponder::hMDNSQuery p_hMDNSQuery) +{ + return ((!m_HostList.empty()) + ? answerCount((hMDNSHost)m_HostList.front(), p_hMDNSQuery) + : 0); +} + +/* + MDNSResponder::hasAnswerServiceDomain +*/ +bool MDNSResponder::hasAnswerServiceDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::ServiceDomain))); +} + + /* + MDNSResponder::hasAnswerServiceDomain (LEGACY 2) + */ + bool MDNSResponder::hasAnswerServiceDomain(const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? hasAnswerServiceDomain((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) + : false); +} + +/* + MDNSResponder::answerServiceDomain + + Returns the domain for the given service. + If not already existing, the string is allocated, filled and attached to the answer. + +*/ +const char* MDNSResponder::answerServiceDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + // Fill m_pcServiceDomain (if not already done) + if ((pSQAnswer) && + (pSQAnswer->m_ServiceDomain.m_u16NameLength) && + (!pSQAnswer->m_pcServiceDomain)) +{ + + pSQAnswer->m_pcServiceDomain = pSQAnswer->allocServiceDomain(pSQAnswer->m_ServiceDomain.c_strLength()); + if (pSQAnswer->m_pcServiceDomain) + { + pSQAnswer->m_ServiceDomain.c_str(pSQAnswer->m_pcServiceDomain); + } + } + return (pSQAnswer ? pSQAnswer->m_pcServiceDomain : 0); +} + +/* + MDNSResponder::answerServiceDomain (LEGACY 2) +*/ +const char* MDNSResponder::answerServiceDomain(const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? answerServiceDomain((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) + : 0); +} + +/* + MDNSResponder::hasAnswerHostDomain +*/ +bool MDNSResponder::hasAnswerHostDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain))); +} + + /* + MDNSResponder::hasAnswerHostDomain (LEGACY 2) + */ + bool MDNSResponder::hasAnswerHostDomain(const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? hasAnswerHostDomain((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) + : false); +} + +/* + MDNSResponder::answerHostDomain + + Returns the host domain for the given service. + If not already existing, the string is allocated, filled and attached to the answer. + +*/ +const char* MDNSResponder::answerHostDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + // Fill m_pcHostDomain (if not already done) + if ((pSQAnswer) && + (pSQAnswer->m_HostDomain.m_u16NameLength) && + (!pSQAnswer->m_pcHostDomain)) +{ + + pSQAnswer->m_pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); + if (pSQAnswer->m_pcHostDomain) + { + pSQAnswer->m_HostDomain.c_str(pSQAnswer->m_pcHostDomain); + } + } + return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); +} + +/* + MDNSResponder::answerHostDomain (LEGACY 2) +*/ +const char* MDNSResponder::answerHostDomain(const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? answerHostDomain((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) + : 0); +} + +#ifdef MDNS_IPV4_SUPPORT +/* + MDNSResponder::hasAnswerIPv4Address +*/ +bool MDNSResponder::hasAnswerIPv4Address(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address))); +} + + /* + MDNSResponder::hasAnswerIPv4Address (LEGACY 2) + */ + bool MDNSResponder::hasAnswerIPv4Address(const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? hasAnswerIPv4Address((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) + : false); +} + +/* + MDNSResponder::answerIPv4AddressCount +*/ +uint32_t MDNSResponder::answerIPv4AddressCount(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return (pSQAnswer ? pSQAnswer->IPv4AddressCount() : 0); +} + + /* + MDNSResponder::answerIPv4AddressCount (LEGACY 2) + */ + uint32_t MDNSResponder::answerIPv4AddressCount(const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? answerIPv4AddressCount((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) + : 0); +} + +/* + MDNSResponder::answerIPv4Address +*/ +IPAddress MDNSResponder::answerIPv4Address(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + stcQuery::stcAnswer::stcIPv4Address* pIPv4Address = (pSQAnswer ? pSQAnswer->IPv4AddressAtIndex(p_u32AddressIndex) : 0); + return (pIPv4Address ? pIPv4Address->m_IPAddress : IPAddress()); +} + + /* + MDNSResponder::answerIPv4Address (LEGACY 2) + */ + IPAddress MDNSResponder::answerIPv4Address(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex) +{ + return ((!m_HostList.empty()) + ? answerIPv4Address((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex, p_u32AddressIndex) + : IPAddress()); +} +#endif + +#ifdef MDNS_IPV6_SUPPORT +/* + MDNSResponder::hasAnswerIPv6Address +*/ +bool MDNSResponder::hasAnswerIPv6Address(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address))); +} + + /* + MDNSResponder::hasAnswerIPv6Address (LEGACY 2) + */ + bool MDNSResponder::hasAnswerIPv6Address(const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? hasAnswerIPv6Address((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) + : false); +} + +/* + MDNSResponder::answerIPv6AddressCount +*/ +uint32_t MDNSResponder::answerIPv6AddressCount(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return (pSQAnswer ? pSQAnswer->IPv6AddressCount() : 0); +} + + /* + MDNSResponder::answerIPv6AddressCount (LEGACY 2) + */ + uint32_t MDNSResponder::answerIPv6AddressCount(const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? answerIPv6AddressCount((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) + : 0); +} + +/* + MDNSResponder::answerIPv6Address +*/ +IPAddress MDNSResponder::answerIPv6Address(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + stcQuery::stcAnswer::stcIPv6Address* pIPv6Address = (pSQAnswer ? pSQAnswer->IPv6AddressAtIndex(p_u32AddressIndex) : 0); + return (pIPv6Address ? pIPv6Address->m_IPAddress : IPAddress()); +} + + /* + MDNSResponder::answerIPv6Address (LEGACY 2) + */ + IPAddress MDNSResponder::answerIPv6Address(const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex) +{ + return ((!m_HostList.empty()) + ? answerIPv6Address((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) + : IPAddress()); +} +#endif + +/* + MDNSResponder::hasAnswerPort +*/ +bool MDNSResponder::hasAnswerPort(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::Port))); +} + + /* + MDNSResponder::hasAnswerPort (LEGACY 2) + */ + bool MDNSResponder::hasAnswerPort(const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? hasAnswerPort((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) + : false); +} + +/* + MDNSResponder::answerPort +*/ +uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return (pSQAnswer ? pSQAnswer->m_u16Port : 0); +} + + /* + MDNSResponder::answerPort (LEGACY 2) + */ + uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? answerPort((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) + : 0); +} + +/* + MDNSResponder::hasAnswerTxts +*/ +bool MDNSResponder::hasAnswerTxts(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts))); +} + + /* + MDNSResponder::hasAnswerTxts (LEGACY 2) + */ + bool MDNSResponder::hasAnswerTxts(const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? hasAnswerTxts((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) + : false); +} + +/* + MDNSResponder::answerTxts + + Returns all TXT items for the given service as a ';'-separated string. + If not already existing; the string is alloced, filled and attached to the answer. + +*/ +const char* MDNSResponder::answerTxts(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); + stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); + // Fill m_pcTxts (if not already done) + if ((pSQAnswer) && + (pSQAnswer->m_Txts.m_pTxts) && + (!pSQAnswer->m_pcTxts)) +{ + + pSQAnswer->m_pcTxts = pSQAnswer->allocTxts(pSQAnswer->m_Txts.c_strLength()); + if (pSQAnswer->m_pcTxts) + { + pSQAnswer->m_Txts.c_str(pSQAnswer->m_pcTxts); + } + } + return (pSQAnswer ? pSQAnswer->m_pcTxts : 0); +} + +/* + MDNSResponder::answerTxts (LEGACY 2) +*/ +const char* MDNSResponder::answerTxts(const MDNSResponder::hMDNSQuery p_hMDNSQuery, + const uint32_t p_u32AnswerIndex) +{ + return ((!m_HostList.empty()) + ? answerTxts((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) + : 0); +} + + +/* + PROBING +*/ + +/* + MDNSResponder::setHostProbeResultCallback + + Set a callback for probe results. The callback is called, when probing + for the host domain failes or succeedes. + In the case of failure, the domain name should be changed via 'setHostName' + When succeeded, the host domain will be announced by the MDNS responder. + +*/ +bool MDNSResponder::setHostProbeResultCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, + MDNSResponder::MDNSHostProbeResultCallbackFn p_fnCallback) +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (((clsHost*)p_hMDNSHost)->m_HostProbeInformation.m_fnProbeResultCallback = p_fnCallback, true)); +} + +/* + MDNSResponder::setHostProbeResultCallback (LEGACY 2) +*/ +bool MDNSResponder::setHostProbeResultCallback(MDNSResponder::MDNSHostProbeResultCallbackFn1 p_fnCallback) +{ + return setHostProbeResultCallback([p_fnCallback](MDNSResponder * p_pMDNSResponder, + hMDNSHost, + const char* p_pcDomainName, + bool p_bProbeResult) + { + if (p_fnCallback) + { + p_fnCallback(p_pMDNSResponder, p_pcDomainName, p_bProbeResult); + } + }); +} + +/* + MDNSResponder::setHostProbeResultCallback (LEGACY 2) +*/ +bool MDNSResponder::setHostProbeResultCallback(MDNSResponder::MDNSHostProbeResultCallbackFn2 p_fnCallback) +{ + return setHostProbeResultCallback([p_fnCallback](MDNSResponder*, + hMDNSHost, + const char* p_pcDomainName, + bool p_bProbeResult) + { + if (p_fnCallback) + { + p_fnCallback(p_pcDomainName, p_bProbeResult); + } + }); +} + +/* + MDNSResponder::setServiceProbeResultCallback + + Set a service specific callback for probe results. The callback is called, when probing + for the service domain failes or succeedes. + In the case of failure, the service name should be changed via 'setServiceName'. + When succeeded, the service domain will be announced by the MDNS responder. + +*/ +bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, + const MDNSResponder::hMDNSService p_hMDNSService, + MDNSResponder::MDNSServiceProbeResultCallbackFn p_fnCallback) +{ + return ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && + (((stcService*)p_hMDNSService)->m_ProbeInformation.m_fnProbeResultCallback = p_fnCallback, true)); +} + +/* + MDNSResponder::setServiceProbeResultCallback (LEGACY 2) +*/ +bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hMDNSService, + MDNSResponder::MDNSServiceProbeResultCallbackFn1 p_fnCallback) +{ + return setServiceProbeResultCallback(p_hMDNSService, [p_fnCallback](MDNSResponder * p_pMDNSResponder, + hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcServiceName, + bool p_bProbeResult) + { + if (p_fnCallback) + { + p_fnCallback(p_pMDNSResponder, p_hMDNSService, p_pcServiceName, p_bProbeResult); + } + }); +} + +/* + MDNSResponder::setServiceProbeResultCallback (LEGACY 2) +*/ +bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hMDNSService, + MDNSResponder::MDNSServiceProbeResultCallbackFn2 p_fnCallback) +{ + return setServiceProbeResultCallback(p_hMDNSService, [p_fnCallback](MDNSResponder*, + hMDNSHost, + const hMDNSService p_hMDNSService, + const char* p_pcServiceName, + bool p_bProbeResult) + { + if (p_fnCallback) + { + p_fnCallback(p_hMDNSService, p_pcServiceName, p_bProbeResult); + } + }); +} +#endif + +/* + MISC +*/ + +/* + MDNSResponder::notifyNetIfChange + + Should be called, whenever the AP for the MDNS responder changes. + A bit of this is caught by the event callbacks installed in the constructor. + +*/ +bool MDNSResponder::notifyNetIfChange(netif* p_pNetIf) +{ + clsHost* pMDNSHost; + return (((pMDNSHost = _findHost(p_pNetIf))) && + (pMDNSHost->restart())); +} + +/* + MDNSResponder::update + + Should be called in every 'loop'. + +*/ +bool MDNSResponder::update(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_NRH2Ptr(p_hMDNSHost)->update())); +} + +/* + MDNSResponder::update (convenience) +*/ +bool MDNSResponder::update(void) +{ + bool bResult = true; + for (clsHost* pMDNSHost : m_HostList) + { + if (!pMDNSHost->update()) + { + bResult = false; + } + } + return bResult; +} + +/* + MDNSResponder::announce + + Should be called, if the 'configuration' changes. Mainly this will be changes in the TXT items... +*/ +bool MDNSResponder::announce(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_NRH2Ptr(p_hMDNSHost)->announce(true, true))); +} + +/* + MDNSResponder::announce (convenience) +*/ +bool MDNSResponder::announce(void) +{ + bool bResult = true; + for (clsHost* pMDNSHost : m_HostList) + { + if (!pMDNSHost->announce(true, true)) + { + bResult = false; + } + } + return bResult; +} + +/* + MDNSResponder::enableArduino + + Enable the OTA update service. + +*/ +MDNSResponder::hMDNSService MDNSResponder::enableArduino(const MDNSResponder::hMDNSHost p_hMDNSHost, + uint16_t p_u16Port, + bool p_bAuthUpload /*= false*/) +{ + hMDNSService hService = addService(p_hMDNSHost, 0, "arduino", "tcp", p_u16Port); + if (hService) + { + if ((!addServiceTxt(p_hMDNSHost, hService, "tcp_check", "no")) || + (!addServiceTxt(p_hMDNSHost, hService, "ssh_upload", "no")) || + (!addServiceTxt(p_hMDNSHost, hService, "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD))) || + (!addServiceTxt(p_hMDNSHost, hService, "auth_upload", (p_bAuthUpload) ? "yes" : "no"))) + { + + removeService(p_hMDNSHost, hService); + hService = 0; + } + } + return hService; +} + +#ifdef LATER + +/* + MDNSResponder::enableArduino (LEGACY 2) +*/ +MDNSResponder::hMDNSService MDNSResponder::enableArduino(uint16_t p_u16Port, + bool p_bAuthUpload /*= false*/) +{ + hMDNSService hMDNSService = 0; + for (clsHost*& pMDNSHost : m_HostList) + { + hMDNSService hLastMDNSService = enableArduino((hMDNSHost)it, p_u16Port, p_bAuthUpload); + if ((hLastMDNSService) && + (!hMDNSService)) + { + hMDNSService = hLastMDNSService; + } + } + return hMDNSService; +} + +#endif + +} //namespace MDNSImplementation + +} //namespace esp8266 + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_APIHelpers.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_APIHelpers.cpp new file mode 100755 index 0000000000..7c144499e4 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_APIHelpers.cpp @@ -0,0 +1,354 @@ +/* + LEAmDNS2_APIHelpers.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#include <arch/cc.h> +#include <sys/time.h> +#include <HardwareSerial.h> +#include <IPAddress.h> +#include <lwip/ip_addr.h> +#include <WString.h> +#include <cstdint> + +/* + ESP8266mDNS Control.cpp +*/ + +extern "C" { +#include "user_interface.h" +} + +#include "LEAmDNS2_lwIPdefs.h" +#include "LEAmDNS2_Priv.h" + +namespace esp8266 +{ +/* + LEAmDNS +*/ +namespace experimental +{ + +/* + MDNSResponder::_allocUDPContext +*/ +bool MDNSResponder::_allocUDPContext(void) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext\n"), _DH());); + if (_releaseUDPContext()) + { + m_pUDPContext = new UdpContext; + if (m_pUDPContext) + { + m_pUDPContext->ref(); + + ip_set_option(m_pUDPContext->pcb(), SOF_REUSEADDR); + //udp_bind_netif(m_pUDPContext->pcb(), m_pNetIf); + + if (m_pUDPContext->listen(IP_ANY_TYPE, DNS_MQUERY_PORT)) + { + //m_pUDPContext->setMulticastInterface(m_pNetIf); + m_pUDPContext->setMulticastTTL(MDNS_MULTICAST_TTL); + m_pUDPContext->onRx(std::bind(&MDNSResponder::_processUDPInput, this)); + m_pUDPContext->connect(IP_ANY_TYPE, DNS_MQUERY_PORT); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: Succeeded to alloc UDPContext!\n"), _DH());); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: FAILED to make UDPContext listening!\n"), _DH());); + _releaseUDPContext(); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: FAILED to alloc UDPContext!\n"), _DH());); + } + } + DEBUG_EX_ERR(if (!m_pUDPContext) DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: FAILED!\n"), _DH());); + return (0 != m_pUDPContext); +} + +/* + MDNSResponder::_releaseUDPContext +*/ +bool MDNSResponder::_releaseUDPContext(void) +{ + if (m_pUDPContext) + { + m_pUDPContext->unref(); + m_pUDPContext = 0; + } + return true; +} + +/* + MDNSResponder::_processUDPInput + + Called in SYS context! + +*/ +bool MDNSResponder::_processUDPInput(void) +{ + //DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput\n"), _DH());); + + if (m_pUDPContext->next()) + { + netif* pNetIf = ip_current_input_netif(); + MDNSResponder::clsHost* pHost = 0; + if ((pNetIf) && + ((pHost = _findHost(pNetIf)))) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: netif:%u,src:%s,dest:%s\n"), _DH(), netif_get_index(pNetIf), IPAddress(ip_current_src_addr()).toString().c_str(), IPAddress(ip_current_dest_addr()).toString().c_str());); + pHost->processUDPInput(/*IPAddress(ip_current_src_addr()), IPAddress(ip_current_dest_addr())*/); + } + else + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Received UDP datagramm for unused netif at index: %u\n"), _DH(), (pNetIf ? netif_get_index(pNetIf) : (-1)));); + } + m_pUDPContext->flush(); + } + return true; +} + +/* + MDNSResponder::_createHost +*/ +MDNSResponder::clsHost* MDNSResponder::_createHost(netif* p_pNetIf) +{ + clsHost* pHost = 0; + + if ((p_pNetIf) && + (!((pHost = _findHost(p_pNetIf)))) && + (m_pUDPContext) && + ((pHost = new clsHost(*p_pNetIf, *m_pUDPContext)))) + { + if (pHost->init()) + { + //pHost->setHostProbeResultCallback(_defaultHostProbeResultCallback); + m_HostList.push_back(pHost); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: FAILED!\n"), _DH());); + _releaseHost(pHost); + pHost = 0; + } + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: Attaching to netif %s!\n"), _DH(), (pHost ? "succeeded" : "FAILED"));); + return pHost; +} + +/* + MDNSResponder::_releaseHost +*/ +bool MDNSResponder::_releaseHost(MDNSResponder::clsHost* p_pHost) +{ + bool bResult = false; + + if ((p_pHost) && + (m_HostList.end() != std::find(m_HostList.begin(), m_HostList.end(), p_pHost))) + { + // Delete and remove Responder object + delete p_pHost; + m_HostList.remove(p_pHost); + bResult = true; + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _releaseHost: %s to release netif Responder!\n"), _DH(), (bResult ? "Succeeded" : "FAILED"));); + return bResult; +} + +/* + MDNSResponder::_findHost +*/ +const MDNSResponder::clsHost* MDNSResponder::_findHost(netif* p_pNetIf) const +{ + const clsHost* pResult = 0; + for (const clsHost* pHost : m_HostList) + { + if ((p_pNetIf) && + (&(pHost->m_rNetIf) == p_pNetIf)) + { + pResult = pHost; + break; + } + } + return pResult; +} + +/* + MDNSResponder::_findHost +*/ +MDNSResponder::clsHost* MDNSResponder::_findHost(netif* p_pNetIf) +{ + return (clsHost*)(((const MDNSResponder*)this)->_findHost(p_pNetIf)); +} + +/* + MDNSResponder::_findHost +*/ +const MDNSResponder::clsHost* MDNSResponder::_findHost(const MDNSResponder::hMDNSHost p_hMDNSHost) const +{ + clsHostList::const_iterator it(std::find(m_HostList.begin(), m_HostList.end(), _NRH2Ptr(p_hMDNSHost))); + return ((m_HostList.end() != it) ? *it : 0); +} + +/* + MDNSResponder::_findHost +*/ +MDNSResponder::clsHost* MDNSResponder::_findHost(const MDNSResponder::hMDNSHost p_hMDNSHost) +{ + return (clsHost*)(((const MDNSResponder*)this)->_findHost(p_hMDNSHost)); +} + + +/* + HANDLE HELPERS +*/ + +/* + MDNSResponder::_validateMDNSHostHandle +*/ +bool MDNSResponder::_validateMDNSHostHandle(const hMDNSHost p_hMDNSHost) const +{ + return (0 != _findHost(_NRH2Ptr(p_hMDNSHost))); +} + +/* + MDNSResponder::_validateMDNSHostHandle +*/ +bool MDNSResponder::_validateMDNSHostHandle(const hMDNSHost p_hMDNSHost, + const hMDNSService p_hMDNSService) const +{ + return ((_validateMDNSHostHandle(p_hMDNSHost)) && + (_NRH2Ptr(p_hMDNSHost)->validateService(_SH2Ptr(p_hMDNSService)))); +} + +/* + MDNSResponder::_NRH2Ptr +*/ +MDNSResponder::clsHost* MDNSResponder::_NRH2Ptr(const hMDNSHost p_hMDNSHost) +{ + return (clsHost*)p_hMDNSHost; +} + +/* + MDNSResponder::_NRH2Ptr +*/ +const MDNSResponder::clsHost* MDNSResponder::_NRH2Ptr(const hMDNSHost p_hMDNSHost) const +{ + return (const clsHost*)p_hMDNSHost; +} + +/* + MDNSResponder::_SH2Ptr +*/ +MDNSResponder::clsHost::stcService* MDNSResponder::_SH2Ptr(const hMDNSService p_hMDNSService) +{ + return (clsHost::stcService*)p_hMDNSService; +} + +/* + MDNSResponder::_SH2Ptr +*/ +const MDNSResponder::clsHost::stcService* MDNSResponder::_SH2Ptr(const hMDNSService p_hMDNSService) const +{ + return (const clsHost::stcService*)p_hMDNSService; +} + +/* + MDNSResponder::_begin + + Creates a new netif responder (adding the netif to the multicast groups), + sets up the instance data (hostname, ...) and starts the probing process + +*/ +MDNSResponder::clsHost* MDNSResponder::_begin(const char* p_pcHostName, + netif* p_pNetIf, + MDNSHostProbeResultCallbackFn p_fnCallback) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _begin(%s, netif: %u)\n"), _DH(), (p_pcHostName ?: "_"), (p_pNetIf ? netif_get_index(p_pNetIf) : 0));); + + clsHost* pHost = 0; + if ((!m_pUDPContext) || + (!p_pNetIf) || + (!((pHost = _createHost(p_pNetIf)))) || + (p_fnCallback ? !setHostProbeResultCallback((hMDNSHost)pHost, p_fnCallback) : false) || + (!pHost->setHostName(p_pcHostName)) || + (!pHost->restart())) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _begin: FAILED for '%s'!\n"), _DH(), (p_pcHostName ? : "-"));); + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _begin: %s to init netif with hostname %s!\n"), _DH(), (pHost ? "Succeeded" : "FAILED"), (p_pcHostName ? : "-"));); + return pHost; +} + +/* + MDNSResponder::_close + + The announced host and services are unannounced (by multicasting a goodbye message) + All connected objects and finally the netif Responder is removed. + +*/ +bool MDNSResponder::_close(MDNSResponder::clsHost& p_rHost) +{ + _releaseHost(&p_rHost); // Will call 'delete' on the pHost object! + + return true; +} + + +/* + MISC +*/ + +#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER + +/* + MDNSResponder::_DH +*/ +const char* MDNSResponder::_DH(const hMDNSHost p_hMDNSHost /*= 0*/) const +{ + static char acBuffer[64]; + + *acBuffer = 0; + if (p_hMDNSHost) + { + sprintf_P(acBuffer, PSTR("[MDNSResponder %s]"), ((WIFI_STA == netif_get_index(&((clsHost*)p_hMDNSHost)->m_rNetIf)) + ? "STA" + : ((WIFI_AP == netif_get_index(&((clsHost*)p_hMDNSHost)->m_rNetIf)) + ? "AP" + : "??"))); + } + else + { + sprintf_P(acBuffer, PSTR("[MDNSResponder]")); + } + return acBuffer; +} + +#endif + + +} // namespace MDNSImplementation + +} // namespace esp8266 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Host.cpp new file mode 100755 index 0000000000..b9df26ce8f --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Host.cpp @@ -0,0 +1,1336 @@ +/* + LEAmDNS2_Host.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#include <arch/cc.h> +#include <sys/time.h> +#include <HardwareSerial.h> +#include <IPAddress.h> +#include <lwip/ip_addr.h> +#include <lwip/netif.h> +#include <WString.h> +#include <cstdint> + +/* + ESP8266mDNS Control.cpp +*/ + +extern "C" { +#include "user_interface.h" +} + +#include "LEAmDNS2_lwIPdefs.h" +#include "LEAmDNS2_Priv.h" + +#ifdef MDNS_IPV4_SUPPORT +#include <lwip/igmp.h> +#endif +#ifdef MDNS_IPV6_SUPPORT +#include <lwip/mld6.h> +#endif + + +namespace esp8266 +{ + +/* + LEAmDNS +*/ +namespace experimental +{ + +/* + MDNSResponder::clsHost::clsHost constructor +*/ +MDNSResponder::clsHost::clsHost(netif& p_rNetIf, + UdpContext& p_rUDPContext) + : m_rNetIf(p_rNetIf), + m_NetIfState(static_cast<typeNetIfState>(enuNetIfState::None)), + m_rUDPContext(p_rUDPContext), + m_pcHostName(0), + m_pcInstanceName(0), + m_pServices(0), + m_pQueries(0), + m_fnServiceTxtCallback(0), + m_HostProbeInformation() +{ +} + +/* + MDNSResponder::clsHost::~clsHost destructor +*/ +MDNSResponder::clsHost::~clsHost(void) +{ + _close(); +} + +/* + MDNSResponder::clsHost::init +*/ +bool MDNSResponder::clsHost::init(void) +{ + bool bResult = true; + + // Join multicast group(s) +#ifdef MDNS_IPV4_SUPPORT + ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; + if (!(m_rNetIf.flags & NETIF_FLAG_IGMP)) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: Setting flag: flags & NETIF_FLAG_IGMP\n"), _DH());); + m_rNetIf.flags |= NETIF_FLAG_IGMP; + + if (ERR_OK != igmp_start(&m_rNetIf)) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: igmp_start FAILED!\n"), _DH());); + } + } + + bResult = ((bResult) && + (ERR_OK == igmp_joingroup_netif(&m_rNetIf, ip_2_ip4(&multicast_addr_V4)))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: igmp_joingroup_netif(%s) FAILED!\n"), _DH(), IPAddress(multicast_addr_V4).toString().c_str());); +#endif + +#ifdef MDNS_IPV6_SUPPORT + ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; + bResult = ((bResult) && + (ERR_OK == mld6_joingroup_netif(&m_rNetIf, ip_2_ip6(&multicast_addr_V6)))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: mld6_joingroup_netif FAILED!\n"), _DH());); +#endif + return bResult; +} + +/* + MDNSResponder::clsHost::setHostName +*/ +bool MDNSResponder::clsHost::setHostName(const char* p_pcHostName) +{ + bool bResult; + if ((bResult = _allocHostName(p_pcHostName))) + { + m_HostProbeInformation.m_ProbingStatus = enuProbingStatus::ReadyToStart; + + // Replace 'auto-set' service names + for (stcService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + { + if ((pService->m_bAutoName) && + (!m_pcInstanceName)) + { + bResult = pService->setName(p_pcHostName); + pService->m_ProbeInformation.m_ProbingStatus = enuProbingStatus::ReadyToStart; + } + } + } + return bResult; +} + +/* + MDNSResponder::clsHost::setHostName +*/ +const char* MDNSResponder::clsHost::hostName(void) const +{ + return m_pcHostName; +} + +/* + MDNSResponder::clsHost::setHostProbeResultCallback +*/ +bool MDNSResponder::clsHost::setHostProbeResultCallback(HostProbeResultCallbackFn p_fnCallback) +{ + m_HostProbeInformation.m_fnProbeResultCallback = p_fnCallback; + return true; +} + +/* + MDNSResponder::clsHost::probeStatus +*/ +bool MDNSResponder::clsHost::probeStatus(void) const +{ + return (enuProbingStatus::Done == m_HostProbeInformation.m_ProbingStatus); +} + + +/* + SERVICE +*/ + +/* + MDNSResponder::clsHost::setInstanceName +*/ +bool MDNSResponder::clsHost::setInstanceName(const char* p_pcInstanceName) +{ + bool bResult; + if ((bResult = _allocInstanceName(p_pcInstanceName))) + { + // Replace 'auto-set' service names + for (stcService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + { + if (pService->m_bAutoName) + { + bResult = pService->setName(p_pcInstanceName); + pService->m_ProbeInformation.m_ProbingStatus = enuProbingStatus::ReadyToStart; + } + } + } + return bResult; +} + +/* + MDNSResponder::clsHost::instanceName +*/ +const char* MDNSResponder::clsHost::instanceName(void) const +{ + return m_pcInstanceName; +} + +/* + MDNSResponder::clsHost::addService +*/ +MDNSResponder::clsHost::stcService* MDNSResponder::clsHost::addService(const char* p_pcInstanceName, + const char* p_pcServiceType, + const char* p_pcProtocol, + uint16_t p_u16Port) +{ + stcService* pService = 0; + + if (((!p_pcInstanceName) || // NO name OR + (MDNS_DOMAIN_LABEL_MAXLENGTH >= os_strlen(p_pcInstanceName))) && // Fitting name + (p_pcServiceType) && + (MDNS_SERVICE_NAME_LENGTH >= os_strlen(p_pcServiceType)) && + (p_pcProtocol) && + ((MDNS_SERVICE_PROTOCOL_LENGTH - 1) != os_strlen(p_pcProtocol)) && + (p_u16Port)) + { + if (!((pService = findService((p_pcInstanceName ? : (m_pcInstanceName ? : m_pcHostName)), p_pcServiceType, p_pcProtocol, p_u16Port)))) // Not already used + { + if (0 != (pService = _allocService(p_pcInstanceName, p_pcServiceType, p_pcProtocol, p_u16Port))) + { + // Init probing + pService->m_ProbeInformation.m_ProbingStatus = enuProbingStatus::ReadyToStart; + } + } + } // else: bad arguments + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s addService: %s to add service '%s.%s.%s.local'!\n"), _DH(pService), (pService ? "Succeeded" : "FAILED"), (p_pcInstanceName ? : (m_pcInstanceName ? : (m_pcHostName ? : "-"))), (p_pcServiceType ? : ""), (p_pcProtocol ? : ""));); + DEBUG_EX_ERR(if (!pService) DEBUG_OUTPUT.printf_P(PSTR("%s addService: FAILED to add service '%s.%s.%s.local'!\n"), _DH(pService), (p_pcInstanceName ? : (m_pcInstanceName ? : (m_pcHostName ? : "-"))), (p_pcServiceType ? : ""), (p_pcProtocol ? : ""));); + return pService; +} + +/* + MDNSResponder::clsHost::removeService +*/ +bool MDNSResponder::clsHost::removeService(MDNSResponder::clsHost::stcService* p_pMDNSService) +{ + bool bResult = ((p_pMDNSService) && + (_announceService(*p_pMDNSService, false)) && + (_releaseService(p_pMDNSService))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _removeService: FAILED!\n"), _DH(p_pMDNSService));); + return bResult; +} + +/* + MDNSResponder::clsHost::findService (const) +*/ +const MDNSResponder::clsHost::stcService* MDNSResponder::clsHost::findService(const char* p_pcInstanceName, + const char* p_pcServiceType, + const char* p_pcProtocol, + uint16_t p_u16Port /*= 0*/) const +{ + stcService* pService = m_pServices; + while (pService) + { + if ((0 == strcmp(pService->m_pcName, p_pcInstanceName)) && + (0 == strcmp(pService->m_pcServiceType, p_pcServiceType)) && + (0 == strcmp(pService->m_pcProtocol, p_pcProtocol)) && + ((!p_u16Port) || + (p_u16Port == pService->m_u16Port))) + { + + break; + } + pService = pService->m_pNext; + } + return pService; +} + +/* + MDNSResponder::clsHost::findService +*/ +MDNSResponder::clsHost::stcService* MDNSResponder::clsHost::findService(const char* p_pcInstanceName, + const char* p_pcServiceType, + const char* p_pcProtocol, + uint16_t p_u16Port /*= 0*/) +{ + return (stcService*)((const clsHost*)this)->findService(p_pcInstanceName, p_pcServiceType, p_pcProtocol, p_u16Port); +} + +/* + MDNSResponder::clsHost::validateService +*/ +bool MDNSResponder::clsHost::validateService(const MDNSResponder::clsHost::stcService* p_pService) const +{ + const stcService* pService = m_pServices; + while (pService) + { + if (pService == p_pService) + { + break; + } + pService = pService->m_pNext; + } + return (0 != pService); +} + +/* + MDNSResponder::clsHost::setServiceName +*/ +bool MDNSResponder::clsHost::setServiceName(MDNSResponder::clsHost::stcService* p_pMDNSService, + const char* p_pcInstanceName) +{ + p_pcInstanceName = p_pcInstanceName ? : m_pcInstanceName; + + bool bResult = ((p_pMDNSService) && + ((!p_pcInstanceName) || + (MDNS_DOMAIN_LABEL_MAXLENGTH >= os_strlen(p_pcInstanceName))) && + (p_pMDNSService->setName(p_pcInstanceName)) && + ((p_pMDNSService->m_ProbeInformation.m_ProbingStatus = enuProbingStatus::ReadyToStart), true)); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _setServiceName: FAILED for '%s'!\n"), _DH(p_pMDNSService), (p_pcInstanceName ? : "-"));); + return bResult; +} + +/* + MDNSResponder::clsHost::setServiceName +*/ +const char* MDNSResponder::clsHost::serviceName(const stcService* p_pMDNSService) const +{ + return ((p_pMDNSService) + ? (p_pMDNSService->m_pcName) + : 0); +} + +/* + MDNSResponder::clsHost::serviceType +*/ +const char* MDNSResponder::clsHost::serviceType(const stcService* p_pMDNSService) const +{ + return ((p_pMDNSService) + ? (p_pMDNSService->m_pcServiceType) + : 0); +} + +/* + MDNSResponder::clsHost::serviceProtocol +*/ +const char* MDNSResponder::clsHost::serviceProtocol(const stcService* p_pMDNSService) const +{ + return ((p_pMDNSService) + ? (p_pMDNSService->m_pcProtocol) + : 0); +} + +/* + MDNSResponder::clsHost::servicePort +*/ +uint16_t MDNSResponder::clsHost::servicePort(const stcService* p_pMDNSService) const +{ + return ((p_pMDNSService) + ? (p_pMDNSService->m_u16Port) + : 0); +} + + +/* + MDNSResponder::clsHost::setServiceProbeResultCallback +*/ +bool MDNSResponder::clsHost::setServiceProbeResultCallback(stcService* p_pMDNSService, + ServiceProbeResultCallbackFn p_fnCallback) +{ + return ((p_pMDNSService) + ? ((p_pMDNSService->m_ProbeInformation.m_fnProbeResultCallback = p_fnCallback), true) + : false); +} + +/* + MDNSResponder::clsHost::setServiceName +*/ +bool MDNSResponder::clsHost::serviceProbeStatus(const stcService* p_pMDNSService) const +{ + return ((p_pMDNSService) && + (enuProbingStatus::Done == p_pMDNSService->m_ProbeInformation.m_ProbingStatus)); +} + + +/* + SERVICE TXT +*/ + +/* + MDNSResponder::clsHost::addServiceTxt +*/ +MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::addServiceTxt(stcService* p_pMDNSService, + const char* p_pcKey, + const char* p_pcValue) +{ + return _addServiceTxt(p_pMDNSService, p_pcKey, p_pcValue, false); +} + +/* + MDNSResponder::clsHost::removeServiceTxt +*/ +bool MDNSResponder::clsHost::removeServiceTxt(stcService* p_pMDNSService, + stcServiceTxt* p_pTxt) +{ + bool bResult = ((p_pMDNSService) && + (p_pTxt) && + (_releaseServiceTxt(p_pMDNSService, p_pTxt))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeServiceTxt: FAILED!\n"), _DH(p_pMDNSService));); + return bResult; +} + +/* + MDNSResponder::clsHost::findServiceTxt (const) +*/ +const MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::findServiceTxt(MDNSResponder::clsHost::stcService* p_pMDNSService, + const char* p_pcKey) const +{ + return (const stcServiceTxt*)((const clsHost*)this)->findServiceTxt(p_pMDNSService, p_pcKey); +} + +/* + MDNSResponder::clsHost::findServiceTxt +*/ +MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::findServiceTxt(MDNSResponder::clsHost::stcService* p_pMDNSService, + const char* p_pcKey) +{ + return _findServiceTxt(p_pMDNSService, p_pcKey); +} + +/* + MDNSResponder::clsHost::setDynamicServiceTxtCallback +*/ +bool MDNSResponder::clsHost::setDynamicServiceTxtCallback(DynamicServiceTxtCallbackFn p_fnCallback) +{ + m_fnServiceTxtCallback = p_fnCallback; + return true; +} + +/* + MDNSResponder::clsHost::setDynamicServiceTxtCallback +*/ +bool MDNSResponder::clsHost::setDynamicServiceTxtCallback(stcService* p_pMDNSService, + DynamicServiceTxtCallbackFn p_fnCallback) +{ + return ((p_pMDNSService) + ? ((p_pMDNSService->m_fnTxtCallback = p_fnCallback), true) + : false); +} + +/* + MDNSResponder::clsHost::addDynamicServiceTxt + + Add a (dynamic) MDNS TXT item ('key' = 'value') to the service + Dynamic TXT items are removed right after one-time use. So they need to be added + every time the value s needed (via callback). +*/ +MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::addDynamicServiceTxt(stcService* p_pMDNSService, + const char* p_pcKey, + const char* p_pcValue) +{ + return _addServiceTxt(p_pMDNSService, p_pcKey, p_pcValue, true); +} + + +/* + QUERIES +*/ +/* + MDNSResponder::clsHost::queryService +*/ +uint32_t MDNSResponder::clsHost::queryService(const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService '_%s._%s.local'\n"), _DH(), p_pcService, p_pcProtocol);); + + stcQuery* pMDNSQuery = 0; + if ((p_pcService) && (*p_pcService) && + (p_pcProtocol) && (*p_pcProtocol) && + (p_u16Timeout) && + ((pMDNSQuery = _allocQuery(stcQuery::enuQueryType::Service))) && + (_buildDomainForService(p_pcService, p_pcProtocol, pMDNSQuery->m_Domain))) + { + if ((_removeLegacyQuery()) && + ((pMDNSQuery->m_bLegacyQuery = true)) && + (_sendMDNSQuery(*pMDNSQuery))) + { + // Wait for answers to arrive + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); + delay(p_u16Timeout); + + // All answers should have arrived by now -> stop adding new answers + pMDNSQuery->m_bAwaitingAnswers = false; + } + else // FAILED to send query + { + _removeQuery(pMDNSQuery); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: INVALID input data!\n"), _DH());); + } + return ((pMDNSQuery) + ? pMDNSQuery->answerCount() + : 0); +} + +/* + MDNSResponder::clsHost::queryHost +*/ +uint32_t MDNSResponder::clsHost::queryHost(const char* p_pcHostName, + const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost '%s.local'\n"), _DH(), p_pcHostName);); + + stcQuery* pMDNSQuery = 0; + if ((p_pcHostName) && (*p_pcHostName) && + (p_u16Timeout) && + ((pMDNSQuery = _allocQuery(stcQuery::enuQueryType::Host))) && + (_buildDomainForHost(p_pcHostName, pMDNSQuery->m_Domain))) + { + if ((_removeLegacyQuery()) && + ((pMDNSQuery->m_bLegacyQuery = true)) && + (_sendMDNSQuery(*pMDNSQuery))) + { + // Wait for answers to arrive + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); + delay(p_u16Timeout); + + // All answers should have arrived by now -> stop adding new answers + pMDNSQuery->m_bAwaitingAnswers = false; + } + else // FAILED to send query + { + _removeQuery(pMDNSQuery); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: INVALID input data!\n"), _DH());); + } + return ((pMDNSQuery) + ? pMDNSQuery->answerCount() + : 0); +} + +/* + MDNSResponder::clsHost::removeQuery +*/ +bool MDNSResponder::clsHost::removeQuery(void) +{ + return _removeLegacyQuery(); +} + +/* + MDNSResponder::clsHost::hasQuery +*/ +bool MDNSResponder::clsHost::hasQuery(void) +{ + return (0 != _findLegacyQuery()); +} + +/* + MDNSResponder::clsHost::getQuery +*/ +MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::getQuery(void) +{ + return _findLegacyQuery(); +} + +/* + MDNSResponder::clsHost::installServiceQuery +*/ +MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::installServiceQuery(const char* p_pcService, + const char* p_pcProtocol, + MDNSResponder::clsHost::QueryCallbackFn p_fnCallback) +{ + stcQuery* pMDNSQuery = 0; + if ((p_pcService) && (*p_pcService) && + (p_pcProtocol) && (*p_pcProtocol) && + (p_fnCallback) && + ((pMDNSQuery = _allocQuery(stcQuery::enuQueryType::Service))) && + (_buildDomainForService(p_pcService, p_pcProtocol, pMDNSQuery->m_Domain))) + { + + pMDNSQuery->m_fnCallback = p_fnCallback; + pMDNSQuery->m_bLegacyQuery = false; + + if (_sendMDNSQuery(*pMDNSQuery)) + { + pMDNSQuery->m_u8SentCount = 1; + pMDNSQuery->m_ResendTimeout.reset(MDNS_DYNAMIC_QUERY_RESEND_DELAY); + } + else + { + _removeQuery(pMDNSQuery); + } + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s installServiceQuery: %s for '_%s._%s.local'!\n\n"), _DH(), (pMDNSQuery ? "Succeeded" : "FAILED"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); + DEBUG_EX_ERR(if (!pMDNSQuery) DEBUG_OUTPUT.printf_P(PSTR("%s installServiceQuery: FAILED for '_%s._%s.local'!\n\n"), _DH(), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); + return pMDNSQuery; +} + +/* + MDNSResponder::clsHost::installHostQuery +*/ +MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::installHostQuery(const char* p_pcHostName, + MDNSResponder::clsHost::QueryCallbackFn p_fnCallback) +{ + stcQuery* pMDNSQuery = 0; + if ((p_pcHostName) && (*p_pcHostName)) + { + stcRRDomain domain; + pMDNSQuery = ((_buildDomainForHost(p_pcHostName, domain)) + ? _installDomainQuery(domain, stcQuery::enuQueryType::Host, p_fnCallback) + : 0); + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s installHostQuery: %s for '%s.local'!\n\n"), _DH(), (pMDNSQuery ? "Succeeded" : "FAILED"), (p_pcHostName ? : "-"));); + DEBUG_EX_ERR(if (!pMDNSQuery) DEBUG_OUTPUT.printf_P(PSTR("%s installHostQuery: FAILED for '%s.local'!\n\n"), _DH(), (p_pcHostName ? : "-"));); + return pMDNSQuery; +} + +/* + MDNSResponder::clsHost::removeQuery +*/ +bool MDNSResponder::clsHost::removeQuery(MDNSResponder::clsHost::stcQuery* p_pMDNSQuery) +{ + bool bResult = ((p_pMDNSQuery) && + (_removeQuery(p_pMDNSQuery))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeQuery: FAILED!\n"), _DH());); + return bResult; +} + + +/* + PROCESSING +*/ + +/* + MDNSResponder::clsHost::processUDPInput +*/ +bool MDNSResponder::clsHost::processUDPInput() +{ + bool bResult = false; + + bResult = ((_checkNetIfState()) && // Any changes in the netif state? + (_parseMessage())); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR(""));); + + return bResult; +} + +/* + MDNSResponder::clsHost::update +*/ +bool MDNSResponder::clsHost::update(void) +{ + return ((_checkNetIfState()) && // Any changes in the netif state? + (_updateProbeStatus()) && // Probing + (_checkQueryCache())); +} + +/* + MDNSResponder::clsHost::restart +*/ +bool MDNSResponder::clsHost::restart(void) +{ + return (_resetProbeStatus(true)); // Stop and restart probing +} + + + + + +/* + P R O T E C T E D +*/ + +/* + MDNSResponder::clsHost::_close +*/ +bool MDNSResponder::clsHost::_close(void) +{ + /* _resetProbeStatus(false); // Stop probing + + _releaseQueries(); + _releaseServices(); + _releaseHostName();*/ + + // Leave multicast group(s) +#ifdef MDNS_IPV4_SUPPORT + ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; + if (ERR_OK != igmp_leavegroup_netif(&m_rNetIf, ip_2_ip4(&multicast_addr_V4)/*(const struct ip4_addr *)&multicast_addr_V4.u_addr.ip4*/)) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); + } +#endif +#ifdef MDNS_IPV6_SUPPORT + ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; + if (ERR_OK != mld6_leavegroup_netif(&m_rNetIf, ip_2_ip6(&multicast_addr_V6)/*&(multicast_addr_V6.u_addr.ip6)*/)) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); + } +#endif + return true; +} + + +/* + NETIF +*/ + +/* + MDNSResponder::clsHost::_getNetIfState + + Returns the current netif state. + +*/ +MDNSResponder::clsHost::typeNetIfState MDNSResponder::clsHost::_getNetIfState(void) const +{ + typeNetIfState curNetIfState = static_cast<typeNetIfState>(enuNetIfState::None); + + if (netif_is_up(&m_rNetIf)) + { + curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::IsUp); + + // Check if netif link is up + if ((netif_is_link_up(&m_rNetIf)) && + ((&m_rNetIf != netif_get_by_index(WIFI_STA)) || + (STATION_GOT_IP == wifi_station_get_connect_status()))) + { + curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::LinkIsUp); + } + + // Check for IPv4 address + if (_getResponderIPAddress(enuIPProtocolType::V4).isSet()) + { + curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::IPv4); + } + // Check for IPv6 address + if (_getResponderIPAddress(enuIPProtocolType::V6).isSet()) + { + curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::IPv6); + } + } + return curNetIfState; +} + +/* + MDNSResponder::clsHost::_checkNetIfState + + Checks the netif state. + If eg. a new address appears, the announcing is restarted. + +*/ +bool MDNSResponder::clsHost::_checkNetIfState(void) +{ + typeNetIfState curNetIfState; + if (m_NetIfState != ((curNetIfState = _getNetIfState()))) + { + // Some state change happened + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: DID CHANGE NETIF STATE\n\n"), _DH());); + DEBUG_EX_INFO( + if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IsUp)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IsUp))) + { + DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Netif is up: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IsUp)) ? "YES" : "NO")); + } + if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp))) + { + DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Netif link is up: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp)) ? "YES" : "NO")); + } + if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4))) + { + DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv4 address is set: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4)) ? "YES" : "NO")); + if (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4)) + { + DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv4 address: %s\n"), _DH(), _getResponderIPAddress(enuIPProtocolType::V4).toString().c_str()); + } + } + if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6))) + { + DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv6 address is set: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6)) ? "YES" : "NO")); + if (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6)) + { + DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv6 address: %s\n"), _DH(), _getResponderIPAddress(enuIPProtocolType::V6).toString().c_str()); + } + } + ); + + if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask))) + { + // Link came up (restart() will alloc a m_pUDPContext, ...) or down (_restart() will remove an existing m_pUDPContext, ...) + restart(); + } + else if (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp)) + { + // Link is up (unchanged) + if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask))) + { + // IP state changed + // TODO: If just a new IP address was added, a simple re-announcement should be enough + restart(); + } + } + /* if (enuProbingStatus::Done == m_HostProbeInformation.m_ProbingStatus) { + // Probing is done, prepare to (re)announce host + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Preparing to (re)announce host.\n"));); + //m_HostProbeInformation.m_ProbingStatus = enuProbingStatus::Done; + m_HostProbeInformation.m_u8SentCount = 0; + m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + }*/ + m_NetIfState = curNetIfState; + } + + bool bResult = ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask)) && // Continue if Link is UP + (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask))); // AND has any IP + //DEBUG_EX_INFO(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Link is DOWN or NO IP address!\n"), _DH());); + return bResult; +} + + +/* + DOMAIN NAMES +*/ + +/* + MDNSResponder::clsHost::_allocDomainName +*/ +bool MDNSResponder::clsHost::_allocDomainName(const char* p_pcNewDomainName, + char*& p_rpcDomainName) +{ + bool bResult = false; + + _releaseDomainName(p_rpcDomainName); + + size_t stLength = 0; + if ((p_pcNewDomainName) && + (MDNS_DOMAIN_LABEL_MAXLENGTH >= (stLength = strlen(p_pcNewDomainName)))) // char max size for a single label + { + // Copy in hostname characters as lowercase + if ((bResult = (0 != (p_rpcDomainName = new char[stLength + 1])))) + { +#ifdef MDNS_FORCE_LOWERCASE_HOSTNAME + size_t i = 0; + for (; i < stLength; ++i) + { + p_rpcDomainName[i] = (isupper(p_pcNewDomainName[i]) ? tolower(p_pcNewDomainName[i]) : p_pcNewDomainName[i]); + } + p_rpcDomainName[i] = 0; +#else + strncpy(p_rpcDomainName, p_pcNewDomainName, (stLength + 1)); +#endif + } + } + return bResult; +} + +/* + MDNSResponder::clsHost::_releaseDomainName +*/ +bool MDNSResponder::clsHost::_releaseDomainName(char*& p_rpcDomainName) +{ + bool bResult; + if ((bResult = (0 != p_rpcDomainName))) + { + delete[] p_rpcDomainName; + p_rpcDomainName = 0; + } + return bResult; +} + +/* + MDNSResponder::clsHost::_allocHostName +*/ +bool MDNSResponder::clsHost::_allocHostName(const char* p_pcHostName) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocHostName (%s)\n"), _DH(), p_pcHostName);); + return _allocDomainName(p_pcHostName, m_pcHostName); +} + +/* + MDNSResponder::clsHost::_releaseHostName +*/ +bool MDNSResponder::clsHost::_releaseHostName(void) +{ + return _releaseDomainName(m_pcHostName); +} + +/* + MDNSResponder::clsHost::_allocInstanceName +*/ +bool MDNSResponder::clsHost::_allocInstanceName(const char* p_pcInstanceName) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocInstanceName (%s)\n"), _DH(), p_pcHostName);); + return _allocDomainName(p_pcInstanceName, m_pcInstanceName); +} + +/* + MDNSResponder::clsHost::_releaseInstanceName +*/ +bool MDNSResponder::clsHost::_releaseInstanceName(void) +{ + return _releaseDomainName(m_pcInstanceName); +} + + +/* + SERVICE +*/ + +/* + MDNSResponder::clsHost::_allocService +*/ +MDNSResponder::clsHost::stcService* MDNSResponder::clsHost::_allocService(const char* p_pcName, + const char* p_pcServiceType, + const char* p_pcProtocol, + uint16_t p_u16Port) +{ + stcService* pService = 0; + if (((!p_pcName) || + (MDNS_DOMAIN_LABEL_MAXLENGTH >= strlen(p_pcName))) && + (p_pcServiceType) && + (MDNS_SERVICE_NAME_LENGTH >= strlen(p_pcServiceType)) && + (p_pcProtocol) && + (MDNS_SERVICE_PROTOCOL_LENGTH >= strlen(p_pcProtocol)) && + (p_u16Port) && + (0 != ((pService = new stcService))) && + (pService->setName(p_pcName ? : (m_pcInstanceName ? : m_pcHostName))) && + (pService->setServiceType(p_pcServiceType)) && + (pService->setProtocol(p_pcProtocol))) + { + pService->m_bAutoName = (0 == p_pcName); + pService->m_u16Port = p_u16Port; + + // Add to list (or start list) + pService->m_pNext = m_pServices; + m_pServices = pService; + } + return pService; +} + +/* + MDNSResponder::clsHost::_releaseService +*/ +bool MDNSResponder::clsHost::_releaseService(MDNSResponder::clsHost::stcService* p_pService) +{ + bool bResult = false; + + if (p_pService) + { + stcService* pPred = m_pServices; + while ((pPred) && + (pPred->m_pNext != p_pService)) + { + pPred = pPred->m_pNext; + } + if (pPred) + { + pPred->m_pNext = p_pService->m_pNext; + delete p_pService; + bResult = true; + } + else // No predecesor + { + if (m_pServices == p_pService) + { + m_pServices = p_pService->m_pNext; + delete p_pService; + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _releaseService: INVALID service!"), _DH(p_pService));); + } + } + } + return bResult; +} + + +/* + SERVICE TXT +*/ + +/* + MDNSResponder::clsHost::_allocServiceTxt +*/ +MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::_allocServiceTxt(MDNSResponder::clsHost::stcService* p_pService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp) +{ + stcServiceTxt* pTxt = 0; + + if ((p_pService) && + (p_pcKey) && + (MDNS_SERVICE_TXT_MAXLENGTH > (p_pService->m_Txts.length() + + 1 + // Length byte + (p_pcKey ? strlen(p_pcKey) : 0) + + 1 + // '=' + (p_pcValue ? strlen(p_pcValue) : 0)))) + { + + pTxt = new stcServiceTxt; + if (pTxt) + { + size_t stLength = (p_pcKey ? strlen(p_pcKey) : 0); + pTxt->m_pcKey = new char[stLength + 1]; + if (pTxt->m_pcKey) + { + strncpy(pTxt->m_pcKey, p_pcKey, stLength); pTxt->m_pcKey[stLength] = 0; + } + + if (p_pcValue) + { + stLength = (p_pcValue ? strlen(p_pcValue) : 0); + pTxt->m_pcValue = new char[stLength + 1]; + if (pTxt->m_pcValue) + { + strncpy(pTxt->m_pcValue, p_pcValue, stLength); pTxt->m_pcValue[stLength] = 0; + } + } + pTxt->m_bTemp = p_bTemp; + + // Add to list (or start list) + p_pService->m_Txts.add(pTxt); + } + } + return pTxt; +} + +/* + MDNSResponder::clsHost::_releaseServiceTxt +*/ +bool MDNSResponder::clsHost::_releaseServiceTxt(MDNSResponder::clsHost::stcService* p_pService, + MDNSResponder::clsHost::stcServiceTxt* p_pTxt) +{ + return ((p_pService) && + (p_pTxt) && + (p_pService->m_Txts.remove(p_pTxt))); +} + +/* + MDNSResponder::clsHost::_updateServiceTxt +*/ +MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::_updateServiceTxt(MDNSResponder::clsHost::stcService* p_pService, + MDNSResponder::clsHost::stcServiceTxt* p_pTxt, + const char* p_pcValue, + bool p_bTemp) +{ + if ((p_pService) && + (p_pTxt) && + (MDNS_SERVICE_TXT_MAXLENGTH > (p_pService->m_Txts.length() - + (p_pTxt->m_pcValue ? strlen(p_pTxt->m_pcValue) : 0) + + (p_pcValue ? strlen(p_pcValue) : 0)))) + { + p_pTxt->update(p_pcValue); + p_pTxt->m_bTemp = p_bTemp; + } + return p_pTxt; +} + +/* + MDNSResponder::clsHost::_findServiceTxt +*/ +MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::_findServiceTxt(MDNSResponder::clsHost::stcService* p_pService, + const char* p_pcKey) +{ + return (p_pService ? p_pService->m_Txts.find(p_pcKey) : 0); +} + +/* + MDNSResponder::clsHost::_addServiceTxt +*/ +MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::_addServiceTxt(MDNSResponder::clsHost::stcService* p_pService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp) +{ + stcServiceTxt* pResult = 0; + + if ((p_pService) && + (p_pcKey) && + (strlen(p_pcKey))) + { + + stcServiceTxt* pTxt = p_pService->m_Txts.find(p_pcKey); + if (pTxt) + { + pResult = _updateServiceTxt(p_pService, pTxt, p_pcValue, p_bTemp); + } + else + { + pResult = _allocServiceTxt(p_pService, p_pcKey, p_pcValue, p_bTemp); + } + } + return pResult; +} + +/* + MDNSResponder::clsHost::_answerKeyValue + / + MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::_answerKeyValue(const MDNSResponder::clsHost::stcQuery p_pQuery, + const uint32_t p_u32AnswerIndex) + { + stcQuery::stcAnswer* pSQAnswer = (p_pQuery ? p_pQuery->answerAtIndex(p_u32AnswerIndex) : 0); + // Fill m_pcTxts (if not already done) + return (pSQAnswer) ? pSQAnswer->m_Txts.m_pTxts : 0; + }*/ + +/* + MDNSResponder::clsHost::_collectServiceTxts +*/ +bool MDNSResponder::clsHost::_collectServiceTxts(MDNSResponder::clsHost::stcService& p_rService) +{ + if (m_fnServiceTxtCallback) + { + //m_fnServiceTxtCallback(*this, p_pService); + } + if (p_rService.m_fnTxtCallback) + { + //p_pService->m_fnTxtCallback(*this, p_pService); + } + return true; +} + +/* + MDNSResponder::clsHost::_releaseTempServiceTxts +*/ +bool MDNSResponder::clsHost::_releaseTempServiceTxts(MDNSResponder::clsHost::stcService& p_rService) +{ + return (p_rService.m_Txts.removeTempTxts()); +} + + +/* + QUERIES +*/ + +/* + MDNSResponder::_allocQuery +*/ +MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::_allocQuery(MDNSResponder::clsHost::stcQuery::enuQueryType p_QueryType) +{ + stcQuery* pQuery = new stcQuery(p_QueryType); + if (pQuery) + { + // Link to query list + pQuery->m_pNext = m_pQueries; + m_pQueries = pQuery; + } + return m_pQueries; +} + +/* + MDNSResponder:clsHost:::_removeQuery +*/ +bool MDNSResponder::clsHost::_removeQuery(MDNSResponder::clsHost::stcQuery* p_pQuery) +{ + bool bResult = false; + + if (p_pQuery) + { + stcQuery* pPred = m_pQueries; + while ((pPred) && + (pPred->m_pNext != p_pQuery)) + { + pPred = pPred->m_pNext; + } + if (pPred) + { + pPred->m_pNext = p_pQuery->m_pNext; + delete p_pQuery; + bResult = true; + } + else // No predecesor + { + if (m_pQueries == p_pQuery) + { + m_pQueries = p_pQuery->m_pNext; + delete p_pQuery; + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _releaseQuery: INVALID query!"), _DH());); + } + } + } + return bResult; +} + +/* + MDNSResponder::clsHost::_removeLegacyQuery +*/ +bool MDNSResponder::clsHost::_removeLegacyQuery(void) +{ + stcQuery* pLegacyQuery = 0; + return (((pLegacyQuery = _findLegacyQuery())) + ? _removeQuery(pLegacyQuery) + : false); +} + +/* + MDNSResponder::clsHost::_findLegacyQuery +*/ +MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::_findLegacyQuery(void) +{ + stcQuery* pLegacyQuery = m_pQueries; + while (pLegacyQuery) + { + if (pLegacyQuery->m_bLegacyQuery) + { + break; + } + pLegacyQuery = pLegacyQuery->m_pNext; + } + return pLegacyQuery; +} + +/* + MDNSResponder::clsHost::_releaseQueries +*/ +bool MDNSResponder::clsHost::_releaseQueries(void) +{ + while (m_pQueries) + { + stcQuery* pNext = m_pQueries->m_pNext; + delete m_pQueries; + m_pQueries = pNext; + } + return true; +} + +/* + MDNSResponder::clsHost::_findNextQueryByDomain +*/ +MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::_findNextQueryByDomain(const MDNSResponder::clsHost::stcRRDomain& p_Domain, + const MDNSResponder::clsHost::stcQuery::enuQueryType p_QueryType, + const stcQuery* p_pPrevQuery) +{ + stcQuery* pMatchingQuery = 0; + + stcQuery* pQuery = (p_pPrevQuery ? p_pPrevQuery->m_pNext : m_pQueries); + while (pQuery) + { + if (((stcQuery::enuQueryType::None == p_QueryType) || + (pQuery->m_QueryType == p_QueryType)) && + (p_Domain == pQuery->m_Domain)) + { + + pMatchingQuery = pQuery; + break; + } + pQuery = pQuery->m_pNext; + } + return pMatchingQuery; +} + +/* + MDNSResponder::clsHost::_installDomainQuery +*/ +MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::_installDomainQuery(MDNSResponder::clsHost::stcRRDomain& p_Domain, + MDNSResponder::clsHost::stcQuery::enuQueryType p_QueryType, + MDNSResponder::clsHost::QueryCallbackFn p_fnCallback) +{ + stcQuery* pQuery = 0; + + if ((p_fnCallback) && + ((pQuery = _allocQuery(p_QueryType)))) + { + pQuery->m_Domain = p_Domain; + pQuery->m_fnCallback = p_fnCallback; + pQuery->m_bLegacyQuery = false; + + if (_sendMDNSQuery(*pQuery)) + { + pQuery->m_u8SentCount = 1; + pQuery->m_ResendTimeout.reset(MDNS_DYNAMIC_QUERY_RESEND_DELAY); + } + else + { + _removeQuery(pQuery); + } + } + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _installDomainQuery: %s for "), (pQuery ? "Succeeded" : "FAILED"), _DH()); + _printRRDomain(p_Domain); + DEBUG_OUTPUT.println(); + ); + DEBUG_EX_ERR( + if (!pQuery) +{ + DEBUG_OUTPUT.printf_P(PSTR("%s _installDomainQuery: FAILED for "), _DH()); + _printRRDomain(p_Domain); + DEBUG_OUTPUT.println(); + } + ); + return pQuery; +} + +/* + MDNSResponder::clsHost::_hasQueriesWaitingForAnswers +*/ +bool MDNSResponder::clsHost::_hasQueriesWaitingForAnswers(void) const +{ + bool bOpenQueries = false; + + for (stcQuery* pQuery = m_pQueries; pQuery; pQuery = pQuery->m_pNext) + { + if (pQuery->m_bAwaitingAnswers) + { + bOpenQueries = true; + break; + } + } + return bOpenQueries; +} + +/* + MDNSResponder::clsHost::_executeQueryCallback +*/ +bool MDNSResponder::clsHost::_executeQueryCallback(const stcQuery& p_Query, + const stcQuery::stcAnswer& p_Answer, + typeQueryAnswerType p_QueryAnswerTypeFlags, + bool p_bSetContent) +{ + if (p_Query.m_fnCallback) + { + p_Query.m_fnCallback(*this, p_Query, p_Answer, p_QueryAnswerTypeFlags, p_bSetContent); + } + return true; +} + + + +} // namespace MDNSImplementation + +} // namespace esp8266 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Host.hpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Host.hpp new file mode 100755 index 0000000000..4a5ff6f39d --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Host.hpp @@ -0,0 +1,1177 @@ +/* + LEAmDNS2_Host.hpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +/** + clsHost & clsHostList +*/ +class clsHost +{ +public: + + // File: ..._Host_Structs + /** + typeIPProtocolType & enuIPProtocolType + */ + using typeIPProtocolType = uint8_t; + enum class enuIPProtocolType : typeIPProtocolType + { +#ifdef MDNS_IPV4_SUPPORT + V4 = 0x01, +#endif +#ifdef MDNS_IPV6_SUPPORT + V6 = 0x02, +#endif + }; + + /** + typeNetIfState & enuNetIfState + */ + using typeNetIfState = uint8_t; + enum class enuNetIfState : typeNetIfState + { + None = 0x00, + + IsUp = 0x01, + UpMask = (IsUp), + + LinkIsUp = 0x02, + LinkMask = (LinkIsUp), + + IPv4 = 0x04, + IPv6 = 0x08, + IPMask = (IPv4 | IPv6), + }; + + /** + stcServiceTxt + */ + struct stcServiceTxt + { + stcServiceTxt* m_pNext; + char* m_pcKey; + char* m_pcValue; + bool m_bTemp; + + stcServiceTxt(const char* p_pcKey = 0, + const char* p_pcValue = 0, + bool p_bTemp = false); + stcServiceTxt(const stcServiceTxt& p_Other); + ~stcServiceTxt(void); + + stcServiceTxt& operator=(const stcServiceTxt& p_Other); + bool clear(void); + + char* allocKey(size_t p_stLength); + bool setKey(const char* p_pcKey, + size_t p_stLength); + bool setKey(const char* p_pcKey); + bool releaseKey(void); + + char* allocValue(size_t p_stLength); + bool setValue(const char* p_pcValue, + size_t p_stLength); + bool setValue(const char* p_pcValue); + bool releaseValue(void); + + bool set(const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp = false); + + bool update(const char* p_pcValue); + + size_t length(void) const; + }; + + /** + stcServiceTxts + */ + struct stcServiceTxts + { + stcServiceTxt* m_pTxts; + char* m_pcCache; + + stcServiceTxts(void); + stcServiceTxts(const stcServiceTxts& p_Other); + ~stcServiceTxts(void); + + stcServiceTxts& operator=(const stcServiceTxts& p_Other); + + bool clear(void); + bool clearCache(void); + + bool add(stcServiceTxt* p_pTxt); + bool remove(stcServiceTxt* p_pTxt); + + bool removeTempTxts(void); + + stcServiceTxt* find(const char* p_pcKey); + const stcServiceTxt* find(const char* p_pcKey) const; + stcServiceTxt* find(const stcServiceTxt* p_pTxt); + + uint16_t length(void) const; + + size_t c_strLength(void) const; + bool c_str(char* p_pcBuffer); + const char* c_str(void) const; + + size_t bufferLength(void) const; + bool buffer(char* p_pcBuffer); + + bool compare(const stcServiceTxts& p_Other) const; + bool operator==(const stcServiceTxts& p_Other) const; + bool operator!=(const stcServiceTxts& p_Other) const; + }; + + /** + typeProbingStatus & enuProbingStatus + */ + using typeProbingStatus = uint8_t; + enum class enuProbingStatus : typeProbingStatus + { + WaitingForData, + ReadyToStart, + InProgress, + Done + }; + + /** + stcProbeInformation_Base + */ + struct stcProbeInformation_Base + { + enuProbingStatus m_ProbingStatus; + uint8_t m_u8SentCount; // Used for probes and announcements + esp8266::polledTimeout::oneShot m_Timeout; // Used for probes and announcements + bool m_bConflict; + bool m_bTiebreakNeeded; + + stcProbeInformation_Base(void); + + bool clear(void); // No 'virtual' needed, no polymorphic use (save 4 bytes) + }; + + /** + HostProbeResultCallbackFn + Callback function for host domain probe results + */ + using HostProbeResultCallbackFn = std::function<void(clsHost& p_rHost, + const char* p_pcDomainName, + bool p_bProbeResult)>; + /** + MDNSServiceProbeResultCallbackFn + Callback function for service domain probe results + */ + struct stcService; + using ServiceProbeResultCallbackFn = std::function<void(clsHost& p_rHost, + stcService& p_rMDNSService, + const char* p_pcDomainName, + bool p_bProbeResult)>; + + /** + stcProbeInformation_Host + */ + struct stcProbeInformation_Host : public stcProbeInformation_Base + { + HostProbeResultCallbackFn m_fnProbeResultCallback; + + stcProbeInformation_Host(void); + + bool clear(bool p_bClearUserdata = false); + }; + + /** + stcProbeInformation_Service + */ + struct stcProbeInformation_Service : public stcProbeInformation_Base + { + ServiceProbeResultCallbackFn m_fnProbeResultCallback; + + stcProbeInformation_Service(void); + + bool clear(bool p_bClearUserdata = false); + }; + + /** + DynamicServiceTxtCallbackFn + Callback function for dynamic MDNS TXT items + */ + struct stcService; + using DynamicServiceTxtCallbackFn = std::function<void(clsHost& p_rHost, + stcService& p_rMDNSService)>; + + /** + stcService + */ + struct stcService + { + stcService* m_pNext; + char* m_pcName; + bool m_bAutoName; // Name was set automatically to hostname (if no name was supplied) + char* m_pcServiceType; + char* m_pcProtocol; + uint16_t m_u16Port; + uint32_t m_u32ReplyMask; + stcServiceTxts m_Txts; + DynamicServiceTxtCallbackFn m_fnTxtCallback; + stcProbeInformation_Service m_ProbeInformation; + + stcService(const char* p_pcName = 0, + const char* p_pcServiceType = 0, + const char* p_pcProtocol = 0); + ~stcService(void); + + bool setName(const char* p_pcName); + bool releaseName(void); + + bool setServiceType(const char* p_pcService); + bool releaseServiceType(void); + + bool setProtocol(const char* p_pcProtocol); + bool releaseProtocol(void); + + bool probeStatus(void) const; + }; + + /** + typeContentFlag & enuContentFlag + */ + using typeContentFlag = uint16_t; + enum class enuContentFlag : typeContentFlag + { + // Host + A = 0x0001, + PTR_IPv4 = 0x0002, + PTR_IPv6 = 0x0004, + AAAA = 0x0008, + // Service + PTR_TYPE = 0x0010, + PTR_NAME = 0x0020, + TXT = 0x0040, + SRV = 0x0080, + // DNSSEC + NSEC = 0x0100, + + PTR = (PTR_IPv4 | PTR_IPv6 | PTR_TYPE | PTR_NAME) + }; + + /** + stcMsgHeader + */ + struct stcMsgHeader + { + uint16_t m_u16ID; // Identifier + bool m_1bQR : 1; // Query/Response flag + uint8_t m_4bOpcode : 4; // Operation code + bool m_1bAA : 1; // Authoritative Answer flag + bool m_1bTC : 1; // Truncation flag + bool m_1bRD : 1; // Recursion desired + bool m_1bRA : 1; // Recursion available + uint8_t m_3bZ : 3; // Zero + uint8_t m_4bRCode : 4; // Response code + uint16_t m_u16QDCount; // Question count + uint16_t m_u16ANCount; // Answer count + uint16_t m_u16NSCount; // Authority Record count + uint16_t m_u16ARCount; // Additional Record count + + stcMsgHeader(uint16_t p_u16ID = 0, + bool p_bQR = false, + uint8_t p_u8Opcode = 0, + bool p_bAA = false, + bool p_bTC = false, + bool p_bRD = false, + bool p_bRA = false, + uint8_t p_u8RCode = 0, + uint16_t p_u16QDCount = 0, + uint16_t p_u16ANCount = 0, + uint16_t p_u16NSCount = 0, + uint16_t p_u16ARCount = 0); + }; + + /** + stcRRDomain + */ + struct stcRRDomain + { + char m_acName[MDNS_DOMAIN_MAXLENGTH]; // Encoded domain name + uint16_t m_u16NameLength; // Length (incl. '\0') + char* m_pcDecodedName; + + stcRRDomain(void); + stcRRDomain(const stcRRDomain& p_Other); + ~stcRRDomain(void); + + stcRRDomain& operator=(const stcRRDomain& p_Other); + + bool clear(void); + bool clearNameCache(void); + + bool addLabel(const char* p_pcLabel, + bool p_bPrependUnderline = false); + + bool compare(const stcRRDomain& p_Other) const; + bool operator==(const stcRRDomain& p_Other) const; + bool operator!=(const stcRRDomain& p_Other) const; + bool operator>(const stcRRDomain& p_Other) const; + + size_t c_strLength(void) const; + bool c_str(char* p_pcBuffer) const; + const char* c_str(void) const; + }; + + /** + stcRRAttributes + */ + struct stcRRAttributes + { + uint16_t m_u16Type; // Type + uint16_t m_u16Class; // Class, nearly always 'IN' + + stcRRAttributes(uint16_t p_u16Type = 0, + uint16_t p_u16Class = 1 /*DNS_RRCLASS_IN Internet*/); + stcRRAttributes(const stcRRAttributes& p_Other); + + stcRRAttributes& operator=(const stcRRAttributes& p_Other); + }; + + /** + stcRRHeader + */ + struct stcRRHeader + { + stcRRDomain m_Domain; + stcRRAttributes m_Attributes; + + stcRRHeader(void); + stcRRHeader(const stcRRHeader& p_Other); + + stcRRHeader& operator=(const stcRRHeader& p_Other); + + bool clear(void); + }; + + /** + stcRRQuestion + */ + struct stcRRQuestion + { + stcRRQuestion* m_pNext; + stcRRHeader m_Header; + bool m_bUnicast; // Unicast reply requested + + stcRRQuestion(void); + }; + + /** + stcNSECBitmap + */ + struct stcNSECBitmap + { + uint8_t m_au8BitmapData[6]; // 6 bytes data + + stcNSECBitmap(void); + + bool clear(void); + uint16_t length(void) const; + bool setBit(uint16_t p_u16Bit); + bool getBit(uint16_t p_u16Bit) const; + }; + + /** + typeAnswerType & enuAnswerType + */ + using typeAnswerType = uint8_t; + enum class enuAnswerType : typeAnswerType + { + A, + PTR, + TXT, + AAAA, + SRV, + //NSEC, + Generic + }; + + /** + stcRRAnswer + */ + struct stcRRAnswer + { + stcRRAnswer* m_pNext; + const enuAnswerType m_AnswerType; + stcRRHeader m_Header; + bool m_bCacheFlush; // Cache flush command bit + uint32_t m_u32TTL; // Validity time in seconds + + virtual ~stcRRAnswer(void); + + enuAnswerType answerType(void) const; + + bool clear(void); + + protected: + stcRRAnswer(enuAnswerType p_AnswerType, + const stcRRHeader& p_Header, + uint32_t p_u32TTL); + }; + +#ifdef MDNS_IPV4_SUPPORT + /** + stcRRAnswerA + */ + struct stcRRAnswerA : public stcRRAnswer + { + IPAddress m_IPAddress; + + stcRRAnswerA(const stcRRHeader& p_Header, + uint32_t p_u32TTL); + ~stcRRAnswerA(void); + + bool clear(void); + }; +#endif + + /** + stcRRAnswerPTR + */ + struct stcRRAnswerPTR : public stcRRAnswer + { + stcRRDomain m_PTRDomain; + + stcRRAnswerPTR(const stcRRHeader& p_Header, + uint32_t p_u32TTL); + ~stcRRAnswerPTR(void); + + bool clear(void); + }; + + /** + stcRRAnswerTXT + */ + struct stcRRAnswerTXT : public stcRRAnswer + { + stcServiceTxts m_Txts; + + stcRRAnswerTXT(const stcRRHeader& p_Header, + uint32_t p_u32TTL); + ~stcRRAnswerTXT(void); + + bool clear(void); + }; + +#ifdef MDNS_IPV6_SUPPORT + /** + stcRRAnswerAAAA + */ + struct stcRRAnswerAAAA : public stcRRAnswer + { + IPAddress m_IPAddress; + + stcRRAnswerAAAA(const stcRRHeader& p_Header, + uint32_t p_u32TTL); + ~stcRRAnswerAAAA(void); + + bool clear(void); + }; +#endif + + /** + stcRRAnswerSRV + */ + struct stcRRAnswerSRV : public stcRRAnswer + { + uint16_t m_u16Priority; + uint16_t m_u16Weight; + uint16_t m_u16Port; + stcRRDomain m_SRVDomain; + + stcRRAnswerSRV(const stcRRHeader& p_Header, + uint32_t p_u32TTL); + ~stcRRAnswerSRV(void); + + bool clear(void); + }; + + /** + stcRRAnswerGeneric + */ + struct stcRRAnswerGeneric : public stcRRAnswer + { + uint16_t m_u16RDLength; // Length of variable answer + uint8_t* m_pu8RDData; // Offset of start of variable answer in packet + + stcRRAnswerGeneric(const stcRRHeader& p_Header, + uint32_t p_u32TTL); + ~stcRRAnswerGeneric(void); + + bool clear(void); + }; + + + /** + stcSendParameter + */ + struct stcSendParameter + { + protected: + /** + stcDomainCacheItem + */ + struct stcDomainCacheItem + { + stcDomainCacheItem* m_pNext; + const void* m_pHostNameOrService; // Opaque id for host or service domain (pointer) + bool m_bAdditionalData; // Opaque flag for special info (service domain included) + uint16_t m_u16Offset; // Offset in UDP output buffer + + stcDomainCacheItem(const void* p_pHostNameOrService, + bool p_bAdditionalData, + uint32_t p_u16Offset); + }; + + public: + /** + typeResponseType & enuResponseType + */ + using typeResponseType = uint8_t; + enum class enuResponseType : typeResponseType + { + None, + Response, + Unsolicited + }; + + uint16_t m_u16ID; // Query ID (used only in lagacy queries) + stcRRQuestion* m_pQuestions; // A list of queries + uint32_t m_u32HostReplyMask; // Flags for reply components/answers + bool m_bLegacyQuery; // Flag: Legacy query + enuResponseType m_Response; // Enum: Response to a query + bool m_bAuthorative; // Flag: Authorative (owner) response + bool m_bCacheFlush; // Flag: Clients should flush their caches + bool m_bUnicast; // Flag: Unicast response + bool m_bUnannounce; // Flag: Unannounce service + + // Temp content; created while processing _prepareMessage + uint16_t m_u16Offset; // Current offset in UDP write buffer (mainly for domain cache) + stcDomainCacheItem* m_pDomainCacheItems; // Cached host and service domains + + stcSendParameter(void); + ~stcSendParameter(void); + + bool clear(void); + bool flushQuestions(void); + bool flushDomainCache(void); + bool flushTempContent(void); + + bool shiftOffset(uint16_t p_u16Shift); + + bool addDomainCacheItem(const void* p_pHostNameOrService, + bool p_bAdditionalData, + uint16_t p_u16Offset); + uint16_t findCachedDomainOffset(const void* p_pHostNameOrService, + bool p_bAdditionalData) const; + }; + + + // QUERIES & ANSWERS + /** + typeQueryAnswerType & enuQueryAnswerType + */ + using typeQueryAnswerType = uint8_t; + enum class enuQueryAnswerType : typeQueryAnswerType + { + Unknown = 0x00, + ServiceDomain = 0x01, // Service domain + HostDomain = 0x02, // Host domain + Port = 0x04, // Port + Txts = 0x08, // TXT items +#ifdef MDNS_IPV4_SUPPORT + IPv4Address = 0x10, // IPv4 address +#endif +#ifdef MDNS_IPV6_SUPPORT + IPv6Address = 0x20, // IPv6 address +#endif + }; + + /** + stcQuery + */ + struct stcQuery + { + /** + stcAnswer + */ + struct stcAnswer + { + /** + stcTTL + */ + struct stcTTL + { + /** + typeTimeoutLevel & enuTimeoutLevel + */ + using typeTimeoutLevel = uint8_t; + enum class enuTimeoutLevel : typeTimeoutLevel + { + None = 0, + Base = 80, + Interval = 5, + Final = 100 + }; + + uint32_t m_u32TTL; + esp8266::polledTimeout::oneShot m_TTLTimeout; + typeTimeoutLevel m_TimeoutLevel; + + stcTTL(void); + bool set(uint32_t p_u32TTL); + + bool flagged(void) const; + bool restart(void); + + bool prepareDeletion(void); + bool finalTimeoutLevel(void) const; + + unsigned long timeout(void) const; + }; + /** + stcIPAddress + */ + struct stcIPAddress + { + stcIPAddress* m_pNext; + IPAddress m_IPAddress; + stcTTL m_TTL; + + stcIPAddress(IPAddress p_IPAddress, + uint32_t p_u32TTL = 0); + }; + + stcAnswer* m_pNext; + // The service domain is the first 'answer' (from PTR answer, using service and protocol) to be set + // Defines the key for additional answer, like host domain, etc. + stcRRDomain m_ServiceDomain; // 1. level answer (PTR), eg. MyESP._http._tcp.local + stcTTL m_TTLServiceDomain; + stcRRDomain m_HostDomain; // 2. level answer (SRV, using service domain), eg. esp8266.local + uint16_t m_u16Port; // 2. level answer (SRV, using service domain), eg. 5000 + stcTTL m_TTLHostDomainAndPort; + stcServiceTxts m_Txts; // 2. level answer (TXT, using service domain), eg. c#=1 + stcTTL m_TTLTxts; +#ifdef MDNS_IPV4_SUPPORT + stcIPAddress* m_pIPv4Addresses; // 3. level answer (A, using host domain), eg. 123.456.789.012 +#endif +#ifdef MDNS_IPV6_SUPPORT + stcIPAddress* m_pIPv6Addresses; // 3. level answer (AAAA, using host domain), eg. 1234::09 +#endif + typeQueryAnswerType m_QueryAnswerFlags; // enuQueryAnswerType + + stcAnswer(void); + ~stcAnswer(void); + + bool clear(void); + +#ifdef MDNS_IPV4_SUPPORT + bool releaseIPv4Addresses(void); + bool addIPv4Address(stcIPAddress* p_pIPAddress); + bool removeIPv4Address(stcIPAddress* p_pIPAddress); + const stcIPAddress* findIPv4Address(const IPAddress& p_IPAddress) const; + stcIPAddress* findIPv4Address(const IPAddress& p_IPAddress); + uint32_t IPv4AddressCount(void) const; + const stcIPAddress* IPv4AddressAtIndex(uint32_t p_u32Index) const; + stcIPAddress* IPv4AddressAtIndex(uint32_t p_u32Index); +#endif +#ifdef MDNS_IPV6_SUPPORT + bool releaseIPv6Addresses(void); + bool addIPv6Address(stcIPAddress* p_pIPAddress); + bool removeIPv6Address(stcIPAddress* p_pIPAddress); + const stcIPAddress* findIPv6Address(const IPAddress& p_IPAddress) const; + stcIPAddress* findIPv6Address(const IPAddress& p_IPAddress); + uint32_t IPv6AddressCount(void) const; + const stcIPAddress* IPv6AddressAtIndex(uint32_t p_u32Index) const; + stcIPAddress* IPv6AddressAtIndex(uint32_t p_u32Index); +#endif + }; //stcAnswer + + /** + typeQueryType & enuQueryType + */ + using typeQueryType = uint8_t; + enum class enuQueryType : typeQueryType + { + None, + Service, + Host + }; + using _QueryCallbackFn = std::function<void(clsHost& p_rHost, + const stcQuery& p_Query, + const stcAnswer& p_Answer, + typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)>; // true: Answer component set, false: component deleted + + stcQuery* m_pNext; + enuQueryType m_QueryType; + stcRRDomain m_Domain; // Type:Service -> _http._tcp.local; Type:Host -> esp8266.local + _QueryCallbackFn m_fnCallback; + bool m_bLegacyQuery; + uint8_t m_u8SentCount; + esp8266::polledTimeout::oneShot m_ResendTimeout; + bool m_bAwaitingAnswers; + stcAnswer* m_pAnswers; + + stcQuery(const enuQueryType p_QueryType); + ~stcQuery(void); + + bool clear(void); + + uint32_t answerCount(void) const; + const stcAnswer* answerAtIndex(uint32_t p_u32Index) const; + stcAnswer* answerAtIndex(uint32_t p_u32Index); + uint32_t indexOfAnswer(const stcAnswer* p_pAnswer) const; + + bool addAnswer(stcAnswer* p_pAnswer); + bool removeAnswer(stcAnswer* p_pAnswer); + + stcAnswer* findAnswerForServiceDomain(const stcRRDomain& p_ServiceDomain); + stcAnswer* findAnswerForHostDomain(const stcRRDomain& p_HostDomain); + }; + /** + QueryCallbackFn + + Callback function for received answers for dynamic queries + */ + using QueryCallbackFn = stcQuery::_QueryCallbackFn; + +public: + clsHost(netif& p_rNetIf, + UdpContext& p_rUDPContext); + ~clsHost(void); + + bool init(void); + + // HOST + bool setHostName(const char* p_pcHostName); + const char* hostName(void) const; + + bool setHostProbeResultCallback(HostProbeResultCallbackFn p_fnCallback); + + // Returns 'true' is host domain probing is done + bool probeStatus(void) const; + + // SERVICE + bool setInstanceName(const char* p_pcInstanceName); + const char* instanceName(void) const; + + stcService* addService(const char* p_pcInstanceName, + const char* p_pcServiceType, + const char* p_pcProtocol, + uint16_t p_u16Port); + bool removeService(stcService* p_pMDNSService); + + const stcService* findService(const char* p_pcInstanceName, + const char* p_pcServiceType, + const char* p_pcProtocol, + uint16_t p_u16Port = 0) const; + stcService* findService(const char* p_pcInstanceName, + const char* p_pcServiceType, + const char* p_pcProtocol, + uint16_t p_u16Port = 0); + bool validateService(const stcService* p_pService) const; + + bool setServiceName(stcService* p_pMDNSService, + const char* p_pcInstanceName); + const char* serviceName(const stcService* p_pMDNSService) const; + const char* serviceType(const stcService* p_pMDNSService) const; + const char* serviceProtocol(const stcService* p_pMDNSService) const; + uint16_t servicePort(const stcService* p_pMDNSService) const; + + // Set a service specific probe result callcack + bool setServiceProbeResultCallback(stcService* p_pMDNSService, + ServiceProbeResultCallbackFn p_fnCallback); + + bool serviceProbeStatus(const stcService* p_pMDNSService) const; + + // SERVICE TXT + // Add a (static) MDNS TXT item ('key' = 'value') to the service + stcServiceTxt* addServiceTxt(stcService* p_pMDNSService, + const char* p_pcKey, + const char* p_pcValue); + bool removeServiceTxt(stcService* p_pMDNSService, + stcServiceTxt* p_pTxt); + const stcServiceTxt* findServiceTxt(stcService* p_pMDNSService, + const char* p_pcKey) const; + stcServiceTxt* findServiceTxt(stcService* p_pMDNSService, + const char* p_pcKey); + + bool setDynamicServiceTxtCallback(DynamicServiceTxtCallbackFn p_fnCallback); + bool setDynamicServiceTxtCallback(stcService* p_pMDNSService, + DynamicServiceTxtCallbackFn p_fnCallback); + + // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service + // Dynamic TXT items are removed right after one-time use. So they need to be added + // every time the value s needed (via callback). + stcServiceTxt* addDynamicServiceTxt(stcService* p_pMDNSService, + const char* p_pcKey, + const char* p_pcValue); + + // QUERIES + + // - STATIC + // Perform a (static) service/host query. The function returns after p_u16Timeout milliseconds + // The answers (the number of received answers is returned) can be retrieved by calling + // - answerHostName (or hostname) + // - answerIP (or IP) + // - answerPort (or port) + uint32_t queryService(const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); + uint32_t queryHost(const char* p_pcHostName, + const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); + bool removeQuery(void); + bool hasQuery(void); + stcQuery* getQuery(void); + + // - DYNAMIC + // Install a dynamic service/host query. For every received answer (part) the given callback + // function is called. The query will be updated every time, the TTL for an answer + // has timed-out. + // The answers can also be retrieved by calling + // - answerCount service/host (for host queries, this should never be >1) + // - answerServiceDomain service + // - hasAnswerHostDomain/answerHostDomain service/host + // - hasAnswerIPv4Address/answerIPv4Address service/host + // - hasAnswerIPv6Address/answerIPv6Address service/host + // - hasAnswerPort/answerPort service + // - hasAnswerTxts/answerTxts service + stcQuery* installServiceQuery(const char* p_pcServiceType, + const char* p_pcProtocol, + QueryCallbackFn p_fnCallback); + stcQuery* installHostQuery(const char* p_pcHostName, + QueryCallbackFn p_fnCallback); + // Remove a dynamic service query + bool removeQuery(stcQuery* p_pMDNSQuery); + + + + + + // PROCESSING + bool processUDPInput(void); + bool update(void); + + bool announce(bool p_bAnnounce, + bool p_bIncludeServices); + bool announceService(stcService* p_pService, + bool p_bAnnounce = true); + + bool restart(void); + +protected: + // File: ..._Host + bool _close(void); + + // NETIF + typeNetIfState _getNetIfState(void) const; + bool _checkNetIfState(void); + + // DOMAIN NAMES + bool _allocDomainName(const char* p_pcNewDomainName, + char*& p_rpcDomainName); + bool _releaseDomainName(char*& p_rpcDomainName); + bool _allocHostName(const char* p_pcHostName); + bool _releaseHostName(void); + bool _allocInstanceName(const char* p_pcInstanceName); + bool _releaseInstanceName(void); + + // SERVICE + stcService* _allocService(const char* p_pcName, + const char* p_pcServiceType, + const char* p_pcProtocol, + uint16_t p_u16Port); + bool _releaseService(stcService* p_pService); + + // SERVICE TXT + stcServiceTxt* _allocServiceTxt(stcService* p_pService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp); + bool _releaseServiceTxt(stcService* p_pService, + stcServiceTxt* p_pTxt); + stcServiceTxt* _updateServiceTxt(stcService* p_pService, + stcServiceTxt* p_pTxt, + const char* p_pcValue, + bool p_bTemp); + stcServiceTxt* _findServiceTxt(stcService* p_pService, + const char* p_pcKey); + stcServiceTxt* _addServiceTxt(stcService* p_pService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp); + stcServiceTxt* _answerKeyValue(const stcQuery p_pQuery, + const uint32_t p_u32AnswerIndex); + bool _collectServiceTxts(stcService& p_rService); + bool _releaseTempServiceTxts(stcService& p_rService); + + // QUERIES + stcQuery* _allocQuery(stcQuery::enuQueryType p_QueryType); + bool _removeQuery(stcQuery* p_pQuery); + bool _removeLegacyQuery(void); + stcQuery* _findLegacyQuery(void); + bool _releaseQueries(void); + stcQuery* _findNextQueryByDomain(const stcRRDomain& p_Domain, + const stcQuery::enuQueryType p_QueryType, + const stcQuery* p_pPrevQuery); + stcQuery* _installDomainQuery(stcRRDomain& p_Domain, + stcQuery::enuQueryType p_QueryType, + QueryCallbackFn p_fnCallback); + bool _hasQueriesWaitingForAnswers(void) const; + bool _executeQueryCallback(const stcQuery& p_Query, + const stcQuery::stcAnswer& p_Answer, + typeQueryAnswerType p_QueryAnswerTypeFlags, + bool p_SetContent); + + + // File: ..._Host_Control + // RECEIVING + bool _parseMessage(void); + bool _parseQuery(const stcMsgHeader& p_Header); + + bool _parseResponse(const stcMsgHeader& p_Header); + bool _processAnswers(const stcRRAnswer* p_pPTRAnswers); + bool _processPTRAnswer(const stcRRAnswerPTR* p_pPTRAnswer, + bool& p_rbFoundNewKeyAnswer); + bool _processSRVAnswer(const stcRRAnswerSRV* p_pSRVAnswer, + bool& p_rbFoundNewKeyAnswer); + bool _processTXTAnswer(const stcRRAnswerTXT* p_pTXTAnswer); +#ifdef MDNS_IPV4_SUPPORT + bool _processAAnswer(const stcRRAnswerA* p_pAAnswer); +#endif +#ifdef MDNS_IPV6_SUPPORT + bool _processAAAAAnswer(const stcRRAnswerAAAA* p_pAAAAAnswer); +#endif + + // PROBING + bool _updateProbeStatus(void); + bool _resetProbeStatus(bool p_bRestart = true); + bool _hasProbesWaitingForAnswers(void) const; + bool _sendHostProbe(void); + bool _sendServiceProbe(stcService& p_rService); + bool _cancelProbingForHost(void); + bool _cancelProbingForService(stcService& p_rService); + bool _callHostProbeResultCallback(bool p_bResult); + bool _callServiceProbeResultCallback(stcService& p_rService, + bool p_bResult); + + // ANNOUNCE + bool _announce(bool p_bAnnounce, + bool p_bIncludeServices); + bool _announceService(stcService& p_pService, + bool p_bAnnounce = true); + + // QUERY CACHE + bool _checkQueryCache(void); + + uint32_t _replyMaskForHost(const stcRRHeader& p_RRHeader, + bool* p_pbFullNameMatch = 0) const; + uint32_t _replyMaskForService(const stcRRHeader& p_RRHeader, + const stcService& p_Service, + bool* p_pbFullNameMatch = 0) const; + + + // File: ..._Host_Transfer + // SENDING + bool _sendMDNSMessage(stcSendParameter& p_SendParameter); + bool _sendMDNSMessage_Multicast(stcSendParameter& p_rSendParameter, + uint8_t p_IPProtocolTypes); + bool _prepareMDNSMessage(stcSendParameter& p_SendParameter); + bool _addMDNSQueryRecord(stcSendParameter& p_rSendParameter, + const stcRRDomain& p_QueryDomain, + uint16_t p_u16QueryType); + bool _sendMDNSQuery(const stcQuery& p_Query, + stcQuery::stcAnswer* p_pKnownAnswers = 0); + bool _sendMDNSQuery(const stcRRDomain& p_QueryDomain, + uint16_t p_u16RecordType, + stcQuery::stcAnswer* p_pKnownAnswers = 0); + + IPAddress _getResponderIPAddress(enuIPProtocolType p_IPProtocolType) const; + + // RESOURCE RECORD + bool _readRRQuestion(stcRRQuestion& p_rQuestion); + bool _readRRAnswer(stcRRAnswer*& p_rpAnswer); +#ifdef MDNS_IPV4_SUPPORT + bool _readRRAnswerA(stcRRAnswerA& p_rRRAnswerA, + uint16_t p_u16RDLength); +#endif + bool _readRRAnswerPTR(stcRRAnswerPTR& p_rRRAnswerPTR, + uint16_t p_u16RDLength); + bool _readRRAnswerTXT(stcRRAnswerTXT& p_rRRAnswerTXT, + uint16_t p_u16RDLength); +#ifdef MDNS_IPV6_SUPPORT + bool _readRRAnswerAAAA(stcRRAnswerAAAA& p_rRRAnswerAAAA, + uint16_t p_u16RDLength); +#endif + bool _readRRAnswerSRV(stcRRAnswerSRV& p_rRRAnswerSRV, + uint16_t p_u16RDLength); + bool _readRRAnswerGeneric(stcRRAnswerGeneric& p_rRRAnswerGeneric, + uint16_t p_u16RDLength); + + bool _readRRHeader(stcRRHeader& p_rHeader); + bool _readRRDomain(stcRRDomain& p_rRRDomain); + bool _readRRDomain_Loop(stcRRDomain& p_rRRDomain, + uint8_t p_u8Depth); + bool _readRRAttributes(stcRRAttributes& p_rAttributes); + + // DOMAIN NAMES + bool _buildDomainForHost(const char* p_pcHostName, + stcRRDomain& p_rHostDomain) const; + bool _buildDomainForDNSSD(stcRRDomain& p_rDNSSDDomain) const; + bool _buildDomainForService(const stcService& p_Service, + bool p_bIncludeName, + stcRRDomain& p_rServiceDomain) const; + bool _buildDomainForService(const char* p_pcService, + const char* p_pcProtocol, + stcRRDomain& p_rServiceDomain) const; +#ifdef MDNS_IPV4_SUPPORT + bool _buildDomainForReverseIPv4(IPAddress p_IPv4Address, + stcRRDomain& p_rReverseIPv4Domain) const; +#endif +#ifdef MDNS_IPV6_SUPPORT + bool _buildDomainForReverseIPv6(IPAddress p_IPv4Address, + stcRRDomain& p_rReverseIPv6Domain) const; +#endif + + // UDP + bool _udpReadBuffer(unsigned char* p_pBuffer, + size_t p_stLength); + bool _udpRead8(uint8_t& p_ru8Value); + bool _udpRead16(uint16_t& p_ru16Value); + bool _udpRead32(uint32_t& p_ru32Value); + + bool _udpAppendBuffer(const unsigned char* p_pcBuffer, + size_t p_stLength); + bool _udpAppend8(uint8_t p_u8Value); + bool _udpAppend16(uint16_t p_u16Value); + bool _udpAppend32(uint32_t p_u32Value); + +#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER + bool _udpDump(bool p_bMovePointer = false); + bool _udpDump(unsigned p_uOffset, + unsigned p_uLength); +#endif + + // READ/WRITE MDNS STRUCTS + bool _readMDNSMsgHeader(stcMsgHeader& p_rMsgHeader); + + bool _write8(uint8_t p_u8Value, + stcSendParameter& p_rSendParameter); + bool _write16(uint16_t p_u16Value, + stcSendParameter& p_rSendParameter); + bool _write32(uint32_t p_u32Value, + stcSendParameter& p_rSendParameter); + + bool _writeMDNSMsgHeader(const stcMsgHeader& p_MsgHeader, + stcSendParameter& p_rSendParameter); + bool _writeMDNSRRAttributes(const stcRRAttributes& p_Attributes, + stcSendParameter& p_rSendParameter); + bool _writeMDNSRRDomain(const stcRRDomain& p_Domain, + stcSendParameter& p_rSendParameter); + bool _writeMDNSHostDomain(const char* m_pcHostName, + bool p_bPrependRDLength, + uint16_t p_u16AdditionalLength, + stcSendParameter& p_rSendParameter); + bool _writeMDNSServiceDomain(const stcService& p_Service, + bool p_bIncludeName, + bool p_bPrependRDLength, + uint16_t p_u16AdditionalLength, + stcSendParameter& p_rSendParameter); + + bool _writeMDNSQuestion(stcRRQuestion& p_Question, + stcSendParameter& p_rSendParameter); + +#ifdef MDNS_IPV4_SUPPORT + bool _writeMDNSAnswer_A(IPAddress p_IPAddress, + stcSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_PTR_IPv4(IPAddress p_IPAddress, + stcSendParameter& p_rSendParameter); +#endif + bool _writeMDNSAnswer_PTR_TYPE(stcService& p_rService, + stcSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_PTR_NAME(stcService& p_rService, + stcSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_TXT(stcService& p_rService, + stcSendParameter& p_rSendParameter); +#ifdef MDNS_IPV6_SUPPORT + bool _writeMDNSAnswer_AAAA(IPAddress p_IPAddress, + stcSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_PTR_IPv6(IPAddress p_IPAddress, + stcSendParameter& p_rSendParameter); +#endif + bool _writeMDNSAnswer_SRV(stcService& p_rService, + stcSendParameter& p_rSendParameter); + stcNSECBitmap* _createNSECBitmap(uint32_t p_u32NSECContent); + bool _writeMDNSNSECBitmap(const stcNSECBitmap& p_NSECBitmap, + stcSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_NSEC(uint32_t p_u32NSECContent, + stcSendParameter& p_rSendParameter); +#ifdef MDNS_IPV4_SUPPORT + bool _writeMDNSAnswer_NSEC_PTR_IPv4(IPAddress p_IPAddress, + stcSendParameter& p_rSendParameter); +#endif +#ifdef MDNS_IPV6_SUPPORT + bool _writeMDNSAnswer_NSEC_PTR_IPv6(IPAddress p_IPAddress, + stcSendParameter& p_rSendParameter); +#endif + bool _writeMDNSAnswer_NSEC(stcService& p_rService, + uint32_t p_u32NSECContent, + stcSendParameter& p_rSendParameter); + + + // File: ..._Host_Debug +#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER + const char* _DH(const stcService* p_pMDNSService = 0) const; + const char* _service2String(const stcService* p_pMDNSService) const; + + bool _printRRDomain(const stcRRDomain& p_rRRDomain) const; + bool _printRRAnswer(const stcRRAnswer& p_RRAnswer) const; + const char* _RRType2Name(uint16_t p_u16RRType) const; + const char* _RRClass2String(uint16_t p_u16RRClass, + bool p_bIsQuery) const; + const char* _replyFlags2String(uint32_t p_u32ReplyFlags) const; + const char* _NSECBitmap2String(const stcNSECBitmap* p_pNSECBitmap) const; +#endif + + +public: + netif& m_rNetIf; + typeNetIfState m_NetIfState; + UdpContext& m_rUDPContext; + + char* m_pcHostName; + char* m_pcInstanceName; + stcService* m_pServices; + stcQuery* m_pQueries; + DynamicServiceTxtCallbackFn m_fnServiceTxtCallback; + stcProbeInformation_Host m_HostProbeInformation; +}; +using clsHostList = std::list<clsHost*>; + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Control.cpp new file mode 100755 index 0000000000..7b4402c587 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Control.cpp @@ -0,0 +1,2207 @@ +/* + LEAmDNS2_Host_Control.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#include <arch/cc.h> +#include <sys/time.h> +#include <HardwareSerial.h> +#include <IPAddress.h> +#include <lwip/ip_addr.h> +#include <WString.h> +#include <cstdint> + +/* + ESP8266mDNS Control.cpp +*/ + +extern "C" { +#include "user_interface.h" +} + +#include "LEAmDNS2_lwIPdefs.h" +#include "LEAmDNS2_Priv.h" + +namespace esp8266 +{ +/* + LEAmDNS +*/ +namespace experimental +{ + +/** + RECEIVING +*/ + +/* + MDNSResponder::clsHost::_parseMessage +*/ +bool MDNSResponder::clsHost::_parseMessage(void) +{ + DEBUG_EX_INFO( + unsigned long ulStartTime = millis(); + unsigned uStartMemory = ESP.getFreeHeap(); + DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage (Time: %lu ms, heap: %u bytes, from %s, to %s)\n"), _DH(), ulStartTime, uStartMemory, + m_rUDPContext.getRemoteAddress().toString().c_str(), + m_rUDPContext.getDestAddress().toString().c_str()); + ); + //DEBUG_EX_INFO(_udpDump();); + + bool bResult = false; + + stcMsgHeader header; + if (_readMDNSMsgHeader(header)) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), + _DH(), + (unsigned)header.m_u16ID, + (unsigned)header.m_1bQR, (unsigned)header.m_4bOpcode, (unsigned)header.m_1bAA, (unsigned)header.m_1bTC, (unsigned)header.m_1bRD, + (unsigned)header.m_1bRA, (unsigned)header.m_4bRCode, + (unsigned)header.m_u16QDCount, + (unsigned)header.m_u16ANCount, + (unsigned)header.m_u16NSCount, + (unsigned)header.m_u16ARCount)); + if (0 == header.m_4bOpcode) // A standard query + { + if (header.m_1bQR) // Received a response -> answers to a query + { + //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: Reading answers: ID:%u, Q:%u, A:%u, NS:%u, AR:%u\n"), _DH(), header.m_u16ID, header.m_u16QDCount, header.m_u16ANCount, header.m_u16NSCount, header.m_u16ARCount);); + bResult = _parseResponse(header); + } + else // Received a query (Questions) + { + //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: Reading query: ID:%u, Q:%u, A:%u, NS:%u, AR:%u\n"), _DH(), header.m_u16ID, header.m_u16QDCount, header.m_u16ANCount, header.m_u16NSCount, header.m_u16ARCount);); + bResult = _parseQuery(header); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: Received UNEXPECTED opcode:%u. Ignoring message!\n"), _DH(), header.m_4bOpcode);); + m_rUDPContext.flush(); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: FAILED to read header\n"), _DH());); + m_rUDPContext.flush(); + } + DEBUG_EX_INFO( + unsigned uFreeHeap = ESP.getFreeHeap(); + DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: Done (%s after %lu ms, ate %i bytes, remaining %u)\n\n"), _DH(), (bResult ? "Succeeded" : "FAILED"), (millis() - ulStartTime), (uStartMemory - uFreeHeap), uFreeHeap); + ); + return bResult; +} + +/* + MDNSResponder::clsHost::_parseQuery + + Queries are of interest in two cases: + 1. allow for tiebreaking while probing in the case of a race condition between two instances probing for + the same name at the same time + 2. provide answers to questions for our host domain or any presented service + + When reading the questions, a set of (planned) responses is created, eg. a reverse PTR question for the host domain + gets an A (IP address) response, a PTR question for the _services._dns-sd domain gets a PTR (type) response for any + registered service, ... + + As any mDNS responder should be able to handle 'legacy' queries (from DNS clients), this case is handled here also. + Legacy queries have got only one (unicast) question and are directed to the local DNS port (not the multicast port). + + 1. +*/ +bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHeader& p_MsgHeader) +{ + bool bResult = true; + + stcSendParameter sendParameter; + uint32_t u32HostOrServiceReplies = 0; + for (uint16_t qd = 0; ((bResult) && (qd < p_MsgHeader.m_u16QDCount)); ++qd) + { + stcRRQuestion questionRR; + if ((bResult = _readRRQuestion(questionRR))) + { + // Define host replies, BUT only answer queries after probing is done + u32HostOrServiceReplies = + sendParameter.m_u32HostReplyMask |= ((probeStatus()) + ? _replyMaskForHost(questionRR.m_Header, 0) + : 0); + DEBUG_EX_INFO(if (u32HostOrServiceReplies) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Host reply needed %s\n"), _DH(), _replyFlags2String(u32HostOrServiceReplies));); + + // Check tiebreak need for host domain + if (enuProbingStatus::InProgress == m_HostProbeInformation.m_ProbingStatus) + { + bool bFullNameMatch = false; + if ((_replyMaskForHost(questionRR.m_Header, &bFullNameMatch)) && + (bFullNameMatch)) + { + // We're in 'probing' state and someone is asking for our host domain: this might be + // a race-condition: Two host with the same domain names try simutanously to probe their domains + // See: RFC 6762, 8.2 (Tiebraking) + // However, we're using a max. reduced approach for tiebreaking here: The higher IP-address wins! + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Possible race-condition for host domain detected while probing.\n"), _DH());); + Serial.printf_P(PSTR("%s _parseQuery: Possible race-condition for host domain detected while probing.\n"), _DH()); + + m_HostProbeInformation.m_bTiebreakNeeded = true; + } + } + + // Define service replies + for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) + { + // Define service replies, BUT only answer queries after probing is done + uint32_t u32ReplyMaskForQuestion = ((pService->probeStatus()) + ? _replyMaskForService(questionRR.m_Header, *pService, 0) + : 0); + u32HostOrServiceReplies |= (pService->m_u32ReplyMask |= u32ReplyMaskForQuestion); + DEBUG_EX_INFO(if (u32ReplyMaskForQuestion) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service reply needed: %s\n"), _DH(pService), _replyFlags2String(u32ReplyMaskForQuestion));); + + // Check tiebreak need for service domain + if (enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) + { + bool bFullNameMatch = false; + if ((_replyMaskForService(questionRR.m_Header, *pService, &bFullNameMatch)) && + (bFullNameMatch)) + { + // We're in 'probing' state and someone is asking for this service domain: this might be + // a race-condition: Two services with the same domain names try simutanously to probe their domains + // See: RFC 6762, 8.2 (Tiebraking) + // However, we're using a max. reduced approach for tiebreaking here: The 'higher' SRV host wins! + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Possible race-condition for service domain detected while probing.\n"), _DH(pService));); + Serial.printf_P(PSTR("%s _parseQuery: Possible race-condition for service domain detected while probing.\n"), _DH(pService)); + + pService->m_ProbeInformation.m_bTiebreakNeeded = true; + } + } + } + + // Handle unicast and legacy specialities + // If only one question asks for unicast reply, the whole reply packet is send unicast + if (((DNS_MQUERY_PORT != m_rUDPContext.getRemotePort()) || // Unicast (maybe legacy) query OR + (questionRR.m_bUnicast)) && // Expressivly unicast query + (!sendParameter.m_bUnicast)) + { + + sendParameter.m_bUnicast = true; + //sendParameter.m_bCacheFlush = false; + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Unicast response asked for %s!\n"), _DH(), m_rUDPContext.getRemoteAddress().toString().c_str());); + //Serial.printf_P(PSTR("%s _parseQuery: Ignored Unicast response asked for by %s!\n"), _DH(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str()); + + if ((DNS_MQUERY_PORT != m_rUDPContext.getRemotePort()) && // Unicast (maybe legacy) query AND + (1 == p_MsgHeader.m_u16QDCount) && // Only one question AND + ((sendParameter.m_u32HostReplyMask) || // Host replies OR + (u32HostOrServiceReplies))) // Host or service replies available + { + // Local host check + // We're a match for this legacy query, BUT + // make sure, that the query comes from a local host +#ifdef MDNS_IPV4_SUPPORT + ip_info IPInfo_Local; +#endif + if ( +#ifdef MDNS_IPV4_SUPPORT + (m_rUDPContext.getRemoteAddress().isV4()) && + ((wifi_get_ip_info(netif_get_index(&m_rNetIf), &IPInfo_Local))) && + (ip4_addr_netcmp(ip_2_ip4((const ip_addr_t*)m_rUDPContext.getRemoteAddress()), &IPInfo_Local.ip, &IPInfo_Local.netmask)) +#else + (true) +#endif + && +#ifdef MDNS_IPV6_SUPPORT + (m_rUDPContext.getRemoteAddress().isV6()) && + (ip6_addr_islinklocal(ip_2_ip6((const ip_addr_t*)m_rUDPContext.getRemoteAddress()))) +#else + (true) +#endif + ) + { + /* ip_info IPInfo_Local; + ip_info IPInfo_Remote; + if (((IPInfo_Remote.ip.addr = m_pUDPContext->getRemoteAddress())) && + (((wifi_get_ip_info(SOFTAP_IF, &IPInfo_Local)) && + (ip4_addr_netcmp(&IPInfo_Remote.ip, &IPInfo_Local.ip, &IPInfo_Local.netmask))) || // Remote IP in SOFTAP's subnet OR + ((wifi_get_ip_info(STATION_IF, &IPInfo_Local)) && + (ip4_addr_netcmp(&IPInfo_Remote.ip, &IPInfo_Local.ip, &IPInfo_Local.netmask))))) // Remote IP in STATION's subnet + {*/ + Serial.println("\n\n\nUNICAST QUERY\n\n"); + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Legacy query from local host %s!\n"), _DH(), m_rUDPContext.getRemoteAddress().toString().c_str());); + + sendParameter.m_u16ID = p_MsgHeader.m_u16ID; + sendParameter.m_bLegacyQuery = true; + sendParameter.m_bCacheFlush = false; + sendParameter.m_pQuestions = new stcRRQuestion; + if ((bResult = (0 != sendParameter.m_pQuestions))) + { + sendParameter.m_pQuestions->m_Header.m_Domain = questionRR.m_Header.m_Domain; + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = questionRR.m_Header.m_Attributes.m_u16Type; + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = questionRR.m_Header.m_Attributes.m_u16Class; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: FAILED to add legacy question!\n"), _DH());); + } + } + else + { + Serial.println("\n\n\nINVALID UNICAST QUERY\n\n"); + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Legacy query from NON-LOCAL host!\n"), _DH());); + bResult = false; + } + } + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: FAILED to read question!\n"), _DH());); + } + } // for questions + + //DEBUG_EX_INFO(if (u8HostOrServiceReplies) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Reply needed: %u (%s: %s->%s)\n"), _DH(), u8HostOrServiceReplies, clsTimeSyncer::timestr(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str(), IPAddress(m_pUDPContext->getDestAddress()).toString().c_str());); + + // Handle known answers + uint32_t u32Answers = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); + if ((u32HostOrServiceReplies) && + (u32Answers)) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Reading known answers(%u):\n"), _DH(), u32Answers);); + + for (uint32_t an = 0; ((bResult) && (an < u32Answers)); ++an) + { + stcRRAnswer* pKnownRRAnswer = 0; + if (((bResult = _readRRAnswer(pKnownRRAnswer))) && + (pKnownRRAnswer)) + { + + if ((DNS_RRTYPE_ANY != pKnownRRAnswer->m_Header.m_Attributes.m_u16Type) && // No ANY type answer + (DNS_RRCLASS_ANY != (pKnownRRAnswer->m_Header.m_Attributes.m_u16Class & (~0x8000)))) // No ANY class answer + { + + // Find match between planned answer (sendParameter.m_u8HostReplyMask) and this 'known answer' + uint32_t u32HostMatchMask = (sendParameter.m_u32HostReplyMask & _replyMaskForHost(pKnownRRAnswer->m_Header)); + if ((u32HostMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND + ((MDNS_HOST_TTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new host TTL (120s) + { + + // Compare contents + if (enuAnswerType::PTR == pKnownRRAnswer->answerType()) + { + stcRRDomain hostDomain; + if ((_buildDomainForHost(m_pcHostName, hostDomain)) && + (((stcRRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain == hostDomain)) + { + // Host domain match +#ifdef MDNS_IPV4_SUPPORT + if (u32HostMatchMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)) + { + // IPv4 PTR was asked for, but is already known -> skipping + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: IPv4 PTR already known... skipping!\n"), _DH());); + sendParameter.m_u32HostReplyMask &= ~static_cast<uint32_t>(enuContentFlag::PTR_IPv4); + } +#endif +#ifdef MDNS_IPV6_SUPPORT + if (u32HostMatchMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv6)) + { + // IPv6 PTR was asked for, but is already known -> skipping + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: IPv6 PTR already known... skipping!\n"), _DH());); + sendParameter.m_u32HostReplyMask &= ~static_cast<uint32_t>(enuContentFlag::PTR_IPv6); + } +#endif + } + } + else if (u32HostMatchMask & static_cast<uint32_t>(enuContentFlag::A)) + { + // IPv4 address was asked for +#ifdef MDNS_IPV4_SUPPORT + if ((enuAnswerType::A == pKnownRRAnswer->answerType()) && + (((stcRRAnswerA*)pKnownRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V4))) + { + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: IPv4 address already known... skipping!\n"), _DH());); + sendParameter.m_u32HostReplyMask &= ~static_cast<uint32_t>(enuContentFlag::A); + } // else: RData NOT IPv4 length !! +#endif + } + else if (u32HostMatchMask & static_cast<uint32_t>(enuContentFlag::AAAA)) + { + // IPv6 address was asked for +#ifdef MDNS_IPV6_SUPPORT + if ((enuAnswerType::AAAA == pKnownRRAnswer->answerType()) && + (((stcRRAnswerAAAA*)pKnownRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V6))) + { + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: IPv6 address already known... skipping!\n"), _DH());); + sendParameter.m_u32HostReplyMask &= ~static_cast<uint32_t>(enuContentFlag::AAAA); + } // else: RData NOT IPv6 length !! +#endif + } + } // Host match /*and TTL*/ + + // + // Check host tiebreak possibility + if (m_HostProbeInformation.m_bTiebreakNeeded) + { + stcRRDomain hostDomain; + if ((_buildDomainForHost(m_pcHostName, hostDomain)) && + (pKnownRRAnswer->m_Header.m_Domain == hostDomain)) + { + // Host domain match +#ifdef MDNS_IPV4_SUPPORT + if (enuAnswerType::A == pKnownRRAnswer->answerType()) + { + // CHECK + IPAddress localIPAddress(_getResponderIPAddress(enuIPProtocolType::V4)); + if (((stcRRAnswerA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) + { + // SAME IP address -> We've received an old message from ourselfs (same IP) + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv4) WON (was an old message)!\n"), _DH());); + m_HostProbeInformation.m_bTiebreakNeeded = false; + } + else + { + if ((uint32_t)(((stcRRAnswerA*)pKnownRRAnswer)->m_IPAddress) > (uint32_t)localIPAddress) // The OTHER IP is 'higher' -> LOST + { + // LOST tiebreak + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv4) LOST (lower)!\n"), _DH());); + _cancelProbingForHost(); + m_HostProbeInformation.m_bTiebreakNeeded = false; + } + else // WON tiebreak + { + //TiebreakState = TiebreakState_Won; // We received an 'old' message from ourselfs -> Just ignore + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv4) WON (higher IP)!\n"), _DH());); + m_HostProbeInformation.m_bTiebreakNeeded = false; + } + } + } +#endif +#ifdef MDNS_IPV6_SUPPORT + if (enuAnswerType::AAAA == pKnownRRAnswer->answerType()) + { + // TODO / CHECK + IPAddress localIPAddress(_getResponderIPAddress(enuIPProtocolType::V6)); + if (((stcRRAnswerAAAA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) + { + // SAME IP address -> We've received an old message from ourselfs (same IP) + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv6) WON (was an old message)!\n"), _DH());); + m_HostProbeInformation.m_bTiebreakNeeded = false; + } + else + { + if ((uint32_t)(((stcRRAnswerAAAA*)pKnownRRAnswer)->m_IPAddress) > (uint32_t)localIPAddress) // The OTHER IP is 'higher' -> LOST + { + // LOST tiebreak + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv6) LOST (lower)!\n"), _DH());); + _cancelProbingForHost(); + m_HostProbeInformation.m_bTiebreakNeeded = false; + } + else // WON tiebreak + { + //TiebreakState = TiebreakState_Won; // We received an 'old' message from ourselfs -> Just ignore + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv6) WON (higher IP)!\n"), _DH());); + m_HostProbeInformation.m_bTiebreakNeeded = false; + } + } + } +#endif + } + } // Host tiebreak possibility + + // Check service answers + for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) + { + + uint32_t u32ServiceMatchMask = (pService->m_u32ReplyMask & _replyMaskForService(pKnownRRAnswer->m_Header, *pService)); + + if ((u32ServiceMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND + ((MDNS_SERVICE_TTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new service TTL (4500s) + { + + if (enuAnswerType::PTR == pKnownRRAnswer->answerType()) + { + stcRRDomain serviceDomain; + if ((u32ServiceMatchMask & static_cast<uint32_t>(enuContentFlag::PTR_TYPE)) && + (_buildDomainForService(*pService, false, serviceDomain)) && + (serviceDomain == ((stcRRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service type PTR already known... skipping!\n"), _DH());); + pService->m_u32ReplyMask &= ~static_cast<uint32_t>(enuContentFlag::PTR_TYPE); + } + if ((u32ServiceMatchMask & static_cast<uint32_t>(enuContentFlag::PTR_NAME)) && + (_buildDomainForService(*pService, true, serviceDomain)) && + (serviceDomain == ((stcRRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service name PTR already known... skipping!\n"), _DH());); + pService->m_u32ReplyMask &= ~static_cast<uint32_t>(enuContentFlag::PTR_NAME); + } + } + else if (u32ServiceMatchMask & static_cast<uint32_t>(enuContentFlag::SRV)) + { + DEBUG_EX_ERR(if (enuAnswerType::SRV != pKnownRRAnswer->answerType()) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: ERROR! INVALID answer type (SRV)!\n"), _DH());); + stcRRDomain hostDomain; + if ((_buildDomainForHost(m_pcHostName, hostDomain)) && + (hostDomain == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain)) // Host domain match + { + + if ((MDNS_SRV_PRIORITY == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_u16Priority) && + (MDNS_SRV_WEIGHT == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_u16Weight) && + (pService->m_u16Port == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_u16Port)) + { + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service SRV answer already known... skipping!\n"), _DH());); + pService->m_u32ReplyMask &= ~static_cast<uint32_t>(enuContentFlag::SRV); + } // else: Small differences -> send update message + } + } + else if (u32ServiceMatchMask & static_cast<uint32_t>(enuContentFlag::TXT)) + { + DEBUG_EX_ERR(if (enuAnswerType::TXT != pKnownRRAnswer->answerType()) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: ERROR! INVALID answer type (TXT)!\n"), _DH());); + _collectServiceTxts(*pService); + if (pService->m_Txts == ((stcRRAnswerTXT*)pKnownRRAnswer)->m_Txts) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service TXT answer already known... skipping!\n"), _DH());); + pService->m_u32ReplyMask &= ~static_cast<uint32_t>(enuContentFlag::TXT); + } + _releaseTempServiceTxts(*pService); + } + } // Service match and enough TTL + + // + // Check service tiebreak possibility + if (pService->m_ProbeInformation.m_bTiebreakNeeded) + { + stcRRDomain serviceDomain; + if ((_buildDomainForService(*pService, true, serviceDomain)) && + (pKnownRRAnswer->m_Header.m_Domain == serviceDomain)) + { + // Service domain match + if (enuAnswerType::SRV == pKnownRRAnswer->answerType()) + { + stcRRDomain hostDomain; + if ((_buildDomainForHost(m_pcHostName, hostDomain)) && + (hostDomain == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain)) // Host domain match + { + + // We've received an old message from ourselfs (same SRV) + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (SRV) won (was an old message)!\n"), _DH());); + pService->m_ProbeInformation.m_bTiebreakNeeded = false; + } + else + { + if (((stcRRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain > hostDomain) // The OTHER domain is 'higher' -> LOST + { + // LOST tiebreak + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (SRV) LOST (lower)!\n"), _DH());); + _cancelProbingForService(*pService); + pService->m_ProbeInformation.m_bTiebreakNeeded = false; + } + else // WON tiebreak + { + //TiebreakState = TiebreakState_Won; // We received an 'old' message from ourselfs -> Just ignore + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (SRV) won (higher)!\n"), _DH());); + pService->m_ProbeInformation.m_bTiebreakNeeded = false; + } + } + } + } + } // service tiebreak possibility + } // for services + } // ANY answers + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: FAILED to read known answer!\n"), _DH());); + } + + if (pKnownRRAnswer) + { + delete pKnownRRAnswer; + pKnownRRAnswer = 0; + } + } // for answers + } + else + { + DEBUG_EX_INFO(if (u32Answers) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Skipped %u known answers!\n"), _DH(), u32Answers);); + m_rUDPContext.flush(); + } + + if (bResult) + { + // Check, if a reply is needed + uint32_t u32ReplyNeeded = sendParameter.m_u32HostReplyMask; + for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) + { + u32ReplyNeeded |= pService->m_u32ReplyMask; + } + + if (u32ReplyNeeded) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Sending answer(%s)...\n"), _DH(), _replyFlags2String(u32ReplyNeeded));); + + sendParameter.m_Response = stcSendParameter::enuResponseType::Response; + sendParameter.m_bAuthorative = true; + + bResult = _sendMDNSMessage(sendParameter); + } + DEBUG_EX_INFO( + else + { + DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: No reply needed\n"), _DH()); + } + ); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Something FAILED!\n"), _DH());); + m_rUDPContext.flush(); + } + + // + // Check and reset tiebreak-states + if (m_HostProbeInformation.m_bTiebreakNeeded) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: UNSOLVED tiebreak-need for host domain!\n"), _DH());); + m_HostProbeInformation.m_bTiebreakNeeded = false; + } + for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) + { + if (pService->m_ProbeInformation.m_bTiebreakNeeded) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: UNSOLVED tiebreak-need for service domain '%s')\n"), _DH(), _service2String(pService));); + pService->m_ProbeInformation.m_bTiebreakNeeded = false; + } + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::clsHost::_parseResponse + + Responses are of interest in two cases: + 1. find domain name conflicts while probing + 2. get answers to service queries + + In both cases any included questions are ignored + + 1. If any answer has a domain name similar to one of the domain names we're planning to use (and are probing for), + then we've got a 'probing conflict'. The conflict has to be solved on our side of the conflict (eg. by + setting a new hostname and restart probing). The callback 'm_fnProbeResultCallback' is called with + 'p_bProbeResult=false' in this case. + + 2. Service queries like '_http._tcp.local' will (if available) produce PTR, SRV, TXT and A/AAAA answers. + All stored answers are pivoted by the service instance name (from the PTR record). Other answer parts, + like host domain or IP address are than attached to this element. + Any answer part carries a TTL, this is also stored (incl. the reception time); if the TTL is '0' the + answer (part) is withdrawn by the sender and should be removed from any cache. RFC 6762, 10.1 proposes to + set the caches TTL-value to 1 second in such a case and to delete the item only, if no update has + has taken place in this second. + Answer parts may arrive in 'unsorted' order, so they are grouped into three levels: + Level 1: PRT - names the service instance (and is used as pivot), voids all other parts if is withdrawn or outdates + Level 2: SRV - links the instance name to a host domain and port, voids A/AAAA parts if is withdrawn or outdates + TXT - links the instance name to services TXTs + Level 3: A/AAAA - links the host domain to an IP address +*/ +bool MDNSResponder::clsHost::_parseResponse(const MDNSResponder::clsHost::stcMsgHeader& p_MsgHeader) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse\n"));); + //DEBUG_EX_INFO(_udpDump();); + + bool bResult = false; + + // A response should be the result of a query or a probe + if ((_hasQueriesWaitingForAnswers()) || // Waiting for query answers OR + (_hasProbesWaitingForAnswers())) // Probe responses + { + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: Received a response\n"), _DH()); + //_udpDump(); + ); + + bResult = true; + // + // Ignore questions here + stcRRQuestion dummyRRQ; + for (uint16_t qd = 0; ((bResult) && (qd < p_MsgHeader.m_u16QDCount)); ++qd) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: Received a response containing a question... ignoring!\n"), _DH());); + bResult = _readRRQuestion(dummyRRQ); + } // for queries + + // + // Read and collect answers + stcRRAnswer* pCollectedRRAnswers = 0; + uint32_t u32NumberOfAnswerRRs = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); + for (uint32_t an = 0; ((bResult) && (an < u32NumberOfAnswerRRs)); ++an) + { + stcRRAnswer* pRRAnswer = 0; + if (((bResult = _readRRAnswer(pRRAnswer))) && + (pRRAnswer)) + { + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: ADDING answer!\n"));); + pRRAnswer->m_pNext = pCollectedRRAnswers; + pCollectedRRAnswers = pRRAnswer; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: FAILED to read answer!\n"), _DH());); + if (pRRAnswer) + { + delete pRRAnswer; + pRRAnswer = 0; + } + bResult = false; + } + } // for answers + + // + // Process answers + if (bResult) + { + bResult = ((!pCollectedRRAnswers) || + (_processAnswers(pCollectedRRAnswers))); + } + else // Some failure while reading answers + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: FAILED to read answers!\n"), _DH());); + m_rUDPContext.flush(); + } + + // Delete collected answers + while (pCollectedRRAnswers) + { + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: DELETING answer!\n"), _DH());); + stcRRAnswer* pNextAnswer = pCollectedRRAnswers->m_pNext; + delete pCollectedRRAnswers; + pCollectedRRAnswers = pNextAnswer; + } + } + else // Received an unexpected response -> ignore + { + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: Received an unexpected response... ignoring!\n"), _DH()); + /* + DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: Received an unexpected response... ignoring!\nDUMP:\n"), _DH()); + bool bDumpResult = true; + for (uint16_t qd=0; ((bDumpResult) && (qd<p_MsgHeader.m_u16QDCount)); ++qd) { + stcRRQuestion questionRR; + bDumpResult = _readRRQuestion(questionRR); + } // for questions + // Handle known answers + uint32_t u32Answers = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); + for (uint32_t an=0; ((bDumpResult) && (an<u32Answers)); ++an) { + stcRRAnswer* pRRAnswer = 0; + bDumpResult = _readRRAnswer(pRRAnswer); + if (pRRAnswer) { + delete pRRAnswer; + pRRAnswer = 0; + } + } + */ + ); + m_rUDPContext.flush(); + bResult = true; + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::clsHost::_processAnswers + Host: + A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 + AAAA (01Cx): eg. esp8266.local AAAA OP TTL 1234:5678::90 + PTR (0x0C, IPv4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local + PTR (0x0C, IPv6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local + Service: + PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local + PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local + SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local + TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 + +*/ +bool MDNSResponder::clsHost::_processAnswers(const MDNSResponder::clsHost::stcRRAnswer* p_pAnswers) +{ + bool bResult = false; + + if (p_pAnswers) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processAnswers: Processing answers...\n"), _DH());); + bResult = true; + + // Answers may arrive in an unexpected order. So we loop our answers as long, as we + // can connect new information to service queries + bool bFoundNewKeyAnswer; + do + { + bFoundNewKeyAnswer = false; + + const stcRRAnswer* pRRAnswer = p_pAnswers; + while ((pRRAnswer) && + (bResult)) + { + // 1. level answer (PTR) + if (enuAnswerType::PTR == pRRAnswer->answerType()) + { + // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local + bResult = _processPTRAnswer((stcRRAnswerPTR*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new SRV or TXT answers to be linked to queries + } + // 2. level answers + // SRV -> host domain and port + else if (enuAnswerType::SRV == pRRAnswer->answerType()) + { + // eg. MyESP._http._tcp.local SRV xxxx xx yy zz 5000 esp8266.local + bResult = _processSRVAnswer((stcRRAnswerSRV*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new A/AAAA answers to be linked to queries + } + // TXT -> Txts + else if (enuAnswerType::TXT == pRRAnswer->answerType()) + { + // eg. MyESP_http._tcp.local TXT xxxx xx c#=1 + bResult = _processTXTAnswer((stcRRAnswerTXT*)pRRAnswer); + } + // 3. level answers +#ifdef MDNS_IPV4_SUPPORT + // A -> IPv4Address + else if (enuAnswerType::A == pRRAnswer->answerType()) + { + // eg. esp8266.local A xxxx xx 192.168.2.120 + bResult = _processAAnswer((stcRRAnswerA*)pRRAnswer); + } +#endif +#ifdef MDNS_IPV6_SUPPORT + // AAAA -> IPv6Address + else if (enuAnswerType::AAAA == pRRAnswer->answerType()) + { + // eg. esp8266.local AAAA xxxx xx 09cf::0c + bResult = _processAAAAAnswer((stcRRAnswerAAAA*)pRRAnswer); + } +#endif + + // Finally check for probing conflicts + // Host domain + if ((enuProbingStatus::InProgress == m_HostProbeInformation.m_ProbingStatus) && + ((enuAnswerType::A == pRRAnswer->answerType()) || + (enuAnswerType::AAAA == pRRAnswer->answerType()))) + { + + stcRRDomain hostDomain; + if ((_buildDomainForHost(m_pcHostName, hostDomain)) && + (pRRAnswer->m_Header.m_Domain == hostDomain)) + { + + bool bPossibleEcho = false; +#ifdef MDNS_IPV4_SUPPORT + if ((enuAnswerType::A == pRRAnswer->answerType()) && + (((stcRRAnswerA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V4))) + { + + bPossibleEcho = true; + } +#endif +#ifdef MDNS_IPV6_SUPPORT + if ((enuAnswerType::AAAA == pRRAnswer->answerType()) && + (((stcRRAnswerAAAA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V6))) + { + + bPossibleEcho = true; + } +#endif + if (!bPossibleEcho) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processAnswers: Probing CONFLICT found with '%s.local'\n"), _DH(), m_pcHostName);); + _cancelProbingForHost(); + } + else + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processAnswers: Ignoring CONFLICT found with '%s.local' as echo!\n"), _DH(), m_pcHostName);); + } + } + } + // Service domains + for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) + { + if ((enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) && + ((enuAnswerType::TXT == pRRAnswer->answerType()) || + (enuAnswerType::SRV == pRRAnswer->answerType()))) + { + + stcRRDomain serviceDomain; + if ((_buildDomainForService(*pService, true, serviceDomain)) && + (pRRAnswer->m_Header.m_Domain == serviceDomain)) + { + + // TODO: Echo management needed? + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processAnswers: Probing CONFLICT found with '%s'\n"), _DH(), _service2String(pService));); + _cancelProbingForService(*pService); + } + } + } + + pRRAnswer = pRRAnswer->m_pNext; // Next collected answer + } // while (answers) + } while ((bFoundNewKeyAnswer) && + (bResult)); + } // else: No answers provided + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _processAnswers: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::clsHost::_processPTRAnswer (level 1) +*/ +bool MDNSResponder::clsHost::_processPTRAnswer(const MDNSResponder::clsHost::stcRRAnswerPTR* p_pPTRAnswer, + bool& p_rbFoundNewKeyAnswer) +{ + bool bResult = false; + + if ((bResult = (0 != p_pPTRAnswer))) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processPTRAnswer: Processing PTR answers...\n"), _DH());); + // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local + // Check pending service queries for eg. '_http._tcp' + + stcQuery* pQuery = _findNextQueryByDomain(p_pPTRAnswer->m_Header.m_Domain, stcQuery::enuQueryType::Service, 0); + while (pQuery) + { + if (pQuery->m_bAwaitingAnswers) + { + // Find answer for service domain (eg. MyESP._http._tcp.local) + stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForServiceDomain(p_pPTRAnswer->m_PTRDomain); + if (pSQAnswer) // existing answer + { + if (p_pPTRAnswer->m_u32TTL) // Received update message + { + pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); // Update TTL tag + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processPTRAnswer: Updated TTL(%lu) for "), _DH(), p_pPTRAnswer->m_u32TTL); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + ); + } + else // received goodbye-message + { + pSQAnswer->m_TTLServiceDomain.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processPTRAnswer: 'Goodbye' received for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + ); + } + } + else if ((p_pPTRAnswer->m_u32TTL) && // Not just a goodbye-message + ((pSQAnswer = new stcQuery::stcAnswer))) // Not yet included -> add answer + { + pSQAnswer->m_ServiceDomain = p_pPTRAnswer->m_PTRDomain; + pSQAnswer->m_QueryAnswerFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::ServiceDomain); + pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); + //pSQAnswer->releaseServiceDomain(); + + bResult = pQuery->addAnswer(pSQAnswer); + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processPTRAnswer: Added service domain to answer: "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.println(); + ); + + p_rbFoundNewKeyAnswer = true; + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::ServiceDomain), true); + } + } + pQuery = _findNextQueryByDomain(p_pPTRAnswer->m_Header.m_Domain, stcQuery::enuQueryType::Service, pQuery); + } + } // else: No p_pPTRAnswer + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _processPTRAnswer: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::clsHost::_processSRVAnswer (level 2) +*/ +bool MDNSResponder::clsHost::_processSRVAnswer(const MDNSResponder::clsHost::stcRRAnswerSRV* p_pSRVAnswer, + bool& p_rbFoundNewKeyAnswer) +{ + bool bResult = false; + + if ((bResult = (0 != p_pSRVAnswer))) + { + // eg. MyESP._http._tcp.local SRV xxxx xx yy zz 5000 esp8266.local + + stcQuery* pQuery = m_pQueries; + while (pQuery) + { + if (pQuery->m_bAwaitingAnswers) + { + stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForServiceDomain(p_pSRVAnswer->m_Header.m_Domain); + if (pSQAnswer) // Answer for this service domain (eg. MyESP._http._tcp.local) available + { + if (p_pSRVAnswer->m_u32TTL) // First or update message (TTL != 0) + { + pSQAnswer->m_TTLHostDomainAndPort.set(p_pSRVAnswer->m_u32TTL); // Update TTL tag + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processSRVAnswer: Updated TTL(%lu) for "), _DH(), p_pSRVAnswer->m_u32TTL); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); + ); + // Host domain & Port + if ((pSQAnswer->m_HostDomain != p_pSRVAnswer->m_SRVDomain) || + (pSQAnswer->m_u16Port != p_pSRVAnswer->m_u16Port)) + { + + pSQAnswer->m_HostDomain = p_pSRVAnswer->m_SRVDomain; + //pSQAnswer->releaseHostDomain(); + pSQAnswer->m_u16Port = p_pSRVAnswer->m_u16Port; + pSQAnswer->m_QueryAnswerFlags |= (static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain) | static_cast<typeQueryAnswerType>(enuQueryAnswerType::Port)); + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processSVRAnswer: Added host domain and port to "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(": ")); + _printRRDomain(pSQAnswer->m_HostDomain); + DEBUG_OUTPUT.printf_P(PSTR(": %u\n"), pSQAnswer->m_u16Port); + ); + + p_rbFoundNewKeyAnswer = true; + _executeQueryCallback(*pQuery, *pSQAnswer, (static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain) | static_cast<typeQueryAnswerType>(enuQueryAnswerType::Port)), true); + } + } + else // Goodby message + { + pSQAnswer->m_TTLHostDomainAndPort.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processSRVAnswer: 'Goodbye' received for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); + ); + } + } + } // m_bAwaitingAnswers + pQuery = pQuery->m_pNext; + } // while(service query) + } // else: No p_pSRVAnswer + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _processSRVAnswer: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::clsHost::_processTXTAnswer (level 2) +*/ +bool MDNSResponder::clsHost::_processTXTAnswer(const MDNSResponder::clsHost::stcRRAnswerTXT* p_pTXTAnswer) +{ + bool bResult = false; + + if ((bResult = (0 != p_pTXTAnswer))) + { + // eg. MyESP._http._tcp.local TXT xxxx xx c#=1 + + stcQuery* pQuery = m_pQueries; + while (pQuery) + { + if (pQuery->m_bAwaitingAnswers) + { + stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForServiceDomain(p_pTXTAnswer->m_Header.m_Domain); + if (pSQAnswer) // Answer for this service domain (eg. MyESP._http._tcp.local) available + { + if (p_pTXTAnswer->m_u32TTL) // First or update message + { + pSQAnswer->m_TTLTxts.set(p_pTXTAnswer->m_u32TTL); // Update TTL tag + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processTXTAnswer: Updated TTL(%lu) for "), _DH(), p_pTXTAnswer->m_u32TTL); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); + ); + if (!pSQAnswer->m_Txts.compare(p_pTXTAnswer->m_Txts)) + { + pSQAnswer->m_Txts = p_pTXTAnswer->m_Txts; + pSQAnswer->m_QueryAnswerFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts); + //pSQAnswer->releaseTxts(); + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processTXTAnswer: Added TXT to "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.println(); + ); + + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts), true); + } + } + else // Goodby message + { + pSQAnswer->m_TTLTxts.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processTXTAnswer: 'Goodbye' received for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); + ); + } + } + } // m_bAwaitingAnswers + pQuery = pQuery->m_pNext; + } // while(service query) + } // else: No p_pTXTAnswer + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _processTXTAnswer: FAILED!\n"), _DH());); + return bResult; +} + +#ifdef MDNS_IPV4_SUPPORT +/* + MDNSResponder::clsHost::_processAAnswer (level 3) +*/ +bool MDNSResponder::clsHost::_processAAnswer(const MDNSResponder::clsHost::stcRRAnswerA* p_pAAnswer) +{ + bool bResult = false; + + if ((bResult = (0 != p_pAAnswer))) + { + // eg. esp8266.local A xxxx xx 192.168.2.120 + + stcQuery* pQuery = m_pQueries; + while (pQuery) + { + if (pQuery->m_bAwaitingAnswers) + { + // Look for answers to host queries + if ((p_pAAnswer->m_u32TTL) && // NOT just a goodbye message + (stcQuery::enuQueryType::Host == pQuery->m_QueryType) && // AND a host query + (pQuery->m_Domain == p_pAAnswer->m_Header.m_Domain)) // AND a matching host domain + { + + stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAnswer->m_Header.m_Domain); + if ((!pSQAnswer) && + ((pSQAnswer = new stcQuery::stcAnswer))) + { + // Add not yet included answer + pSQAnswer->m_HostDomain = p_pAAnswer->m_Header.m_Domain; + //pSQAnswer->releaseHostDomain(); + + bResult = pQuery->addAnswer(pSQAnswer); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: Added host query answer for "), _DH()); + _printRRDomain(pQuery->m_Domain); + DEBUG_OUTPUT.println(); + ); + + pSQAnswer->m_QueryAnswerFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain); + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain), true); + } + } + + // Look for answers to service queries + stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAnswer->m_Header.m_Domain); + if (pSQAnswer) // Answer for this host domain (eg. esp8266.local) available + { + stcQuery::stcAnswer::stcIPAddress* pIPAddress = pSQAnswer->findIPv4Address(p_pAAnswer->m_IPAddress); + if (pIPAddress) + { + // Already known IPv4 address + if (p_pAAnswer->m_u32TTL) // Valid TTL -> Update answers TTL + { + pIPAddress->m_TTL.set(p_pAAnswer->m_u32TTL); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: Updated TTL(%lu) for "), _DH(), p_pAAnswer->m_u32TTL); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IPv4 address (%s)\n"), pIPAddress->m_IPAddress.toString().c_str()); + ); + } + else // 'Goodbye' message for known IPv4 address + { + pIPAddress->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: 'Goodbye' received for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IPv4 address (%s)\n"), pIPAddress->m_IPAddress.toString().c_str()); + ); + } + } + else + { + // Until now unknown IPv4 address -> Add (if the message isn't just a 'Goodbye' note) + if (p_pAAnswer->m_u32TTL) // NOT just a 'Goodbye' message + { + pIPAddress = new stcQuery::stcAnswer::stcIPAddress(p_pAAnswer->m_IPAddress, p_pAAnswer->m_u32TTL); + if ((pIPAddress) && + (pSQAnswer->addIPv4Address(pIPAddress))) + { + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: Added IPv4 address to "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(": %s\n"), pIPAddress->m_IPAddress.toString().c_str()); + ); + + pSQAnswer->m_QueryAnswerFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address); + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address), true); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: FAILED to add IPv4 address (%s)!\n"), _DH(), p_pAAnswer->m_IPAddress.toString().c_str());); + } + } + } + } + } // m_bAwaitingAnswers + pQuery = pQuery->m_pNext; + } // while(service query) + } // else: No p_pAAnswer + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: FAILED!\n"), _DH());); + return bResult; +} +#endif + +#ifdef MDNS_IPV6_SUPPORT +/* + MDNSResponder::clsHost::_processAAAAAnswer (level 3) +*/ +bool MDNSResponder::clsHost::_processAAAAAnswer(const MDNSResponder::clsHost::stcRRAnswerAAAA* p_pAAAAAnswer) +{ + bool bResult = false; + + if ((bResult = (0 != p_pAAAAAnswer))) + { + // eg. esp8266.local AAAA xxxx xx 0bf3::0c + + stcQuery* pQuery = m_pQueries; + while (pQuery) + { + if (pQuery->m_bAwaitingAnswers) + { + // Look for answers to host queries + if ((p_pAAAAAnswer->m_u32TTL) && // NOT just a goodbye message + (stcQuery::enuQueryType::Host == pQuery->m_QueryType) && // AND a host query + (pQuery->m_Domain == p_pAAAAAnswer->m_Header.m_Domain)) // AND a matching host domain + { + + stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAAAAnswer->m_Header.m_Domain); + if ((!pSQAnswer) && + ((pSQAnswer = new stcQuery::stcAnswer))) + { + // Add not yet included answer + pSQAnswer->m_HostDomain = p_pAAAAAnswer->m_Header.m_Domain; + //pSQAnswer->releaseHostDomain(); + + bResult = pQuery->addAnswer(pSQAnswer); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processAAAAAnswer: Added host query answer for "), _DH()); + _printRRDomain(pQuery->m_Domain); + DEBUG_OUTPUT.println(); + ); + + pSQAnswer->m_QueryAnswerFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain); + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain), true); + } + } + + // Look for answers to service queries + stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAAAAnswer->m_Header.m_Domain); + if (pSQAnswer) // Answer for this host domain (eg. esp8266.local) available + { + stcQuery::stcAnswer::stcIPAddress* pIPAddress = pSQAnswer->findIPv6Address(p_pAAAAAnswer->m_IPAddress); + if (pIPAddress) + { + // Already known IPv6 address + if (p_pAAAAAnswer->m_u32TTL) // Valid TTL -> Update answers TTL + { + pIPAddress->m_TTL.set(p_pAAAAAnswer->m_u32TTL); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processAAAAAnswer: Updated TTL(%lu) for "), _DH(), p_pAAAAAnswer->m_u32TTL); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IPv6 address (%s)\n"), pIPAddress->m_IPAddress.toString().c_str()); + ); + } + else // 'Goodbye' message for known IPv6 address + { + pIPAddress->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processAAAAAnswer: 'Goodbye' received for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IPv6 address (%s)\n"), pIPAddress->m_IPAddress.toString().c_str()); + ); + } + } + else + { + // Until now unknown IPv6 address -> Add (if the message isn't just a 'Goodbye' note) + if (p_pAAAAAnswer->m_u32TTL) // NOT just a 'Goodbye' message + { + pIPAddress = new stcQuery::stcAnswer::stcIPAddress(p_pAAAAAnswer->m_IPAddress, p_pAAAAAnswer->m_u32TTL); + if ((pIPAddress) && + (pSQAnswer->addIPv6Address(pIPAddress))) + { + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _processAAAAAnswer: Added IPv6 address to "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(": %s\n"), pIPAddress->m_IPAddress.toString().c_str()); + ); + + pSQAnswer->m_QueryAnswerFlags |= static_cast<uint32_t>(enuQueryAnswerType::IPv6Address); + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address), true); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _processAAAAAnswer: FAILED to add IPv6 address (%s)!\n"), _DH(), p_pAAAAAnswer->m_IPAddress.toString().c_str());); + } + } + } + } + } // m_bAwaitingAnswers + pQuery = pQuery->m_pNext; + } // while(service query) + } // else: No p_pAAAAAnswer + + return bResult; +} +#endif + + +/* + PROBING +*/ + +/* + MDNSResponder::clsHost::_updateProbeStatus + + Manages the (outgoing) probing process. + - If probing has not been started yet (ProbingStatus_NotStarted), the initial delay (see RFC 6762) is determined and + the process is started + - After timeout (of initial or subsequential delay) a probe message is send out for three times. If the message has + already been sent out three times, the probing has been successful and is finished. + + Conflict management is handled in '_parseResponse ff.' + Tiebraking is handled in 'parseQuery ff.' +*/ +bool MDNSResponder::clsHost::_updateProbeStatus(void) +{ + bool bResult = true; + + // + // Probe host domain + if ((enuProbingStatus::ReadyToStart == m_HostProbeInformation.m_ProbingStatus) && // Ready to get started AND + (( +#ifdef MDNS_IPV4_SUPPORT + _getResponderIPAddress(enuIPProtocolType::V4).isSet() // AND has IPv4 address +#else + true +#endif + ) || ( +#ifdef MDNS_IPV6_SUPPORT + _getResponderIPAddress(enuIPProtocolType::V6).isSet() // OR has IPv6 address +#else + true +#endif + ))) // Has IP address + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Starting host probing...\n"), _DH());); + + // First probe delay SHOULD be random 0-250 ms + m_HostProbeInformation.m_Timeout.reset(rand() % MDNS_PROBE_DELAY); + m_HostProbeInformation.m_ProbingStatus = enuProbingStatus::InProgress; + } + else if ((enuProbingStatus::InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing AND + (m_HostProbeInformation.m_Timeout.expired())) // Time for next probe + { + + if (MDNS_PROBE_COUNT > m_HostProbeInformation.m_u8SentCount) // Send next probe + { + if ((bResult = _sendHostProbe())) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Did sent host probe for '%s.local'\n\n"), _DH(), (m_pcHostName ? : ""));); + m_HostProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); + ++m_HostProbeInformation.m_u8SentCount; + } + } + else // Probing finished + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("\n%s _updateProbeStatus: Done host probing for '%s.local'.\n\n\n"), _DH(), (m_pcHostName ? : ""));); + m_HostProbeInformation.m_ProbingStatus = enuProbingStatus::Done; + m_HostProbeInformation.m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + + _callHostProbeResultCallback(true); + + // Prepare to announce host + m_HostProbeInformation.m_u8SentCount = 0; + m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Prepared host announcing.\n\n"), _DH());); + } + } // else: Probing already finished OR waiting for next time slot + else if ((enuProbingStatus::Done == m_HostProbeInformation.m_ProbingStatus) && + (m_HostProbeInformation.m_Timeout.expired())) + { + + if ((bResult = _announce(true, false))) // Don't announce services here + { + ++m_HostProbeInformation.m_u8SentCount; // 1.. + + if (MDNS_ANNOUNCE_COUNT > m_HostProbeInformation.m_u8SentCount) + { + m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY * pow(2, (m_HostProbeInformation.m_u8SentCount - 1))); // 2^(0..) -> 1, 2, 4, ... + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Announcing host '%s.local' (%lu).\n\n"), _DH(), (m_pcHostName ? : ""), m_HostProbeInformation.m_u8SentCount);); + } + else + { + m_HostProbeInformation.m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Done host announcing for '%s.local'.\n\n"), _DH(), (m_pcHostName ? : ""));); + } + } + } + + // + // Probe services + for (stcService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + { + if (enuProbingStatus::ReadyToStart == pService->m_ProbeInformation.m_ProbingStatus) // Ready to get started + { + + pService->m_ProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); // More or equal than first probe for host domain + pService->m_ProbeInformation.m_ProbingStatus = enuProbingStatus::InProgress; + } + else if ((enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing AND + (pService->m_ProbeInformation.m_Timeout.expired())) // Time for next probe + { + + if (MDNS_PROBE_COUNT > pService->m_ProbeInformation.m_u8SentCount) // Send next probe + { + if ((bResult = _sendServiceProbe(*pService))) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Did sent service probe for '%s' (%u)\n\n"), _DH(), _service2String(pService), (pService->m_ProbeInformation.m_u8SentCount + 1));); + pService->m_ProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); + ++pService->m_ProbeInformation.m_u8SentCount; + } + } + else // Probing finished + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("\n%s _updateProbeStatus: Done service probing '%s'\n\n\n"), _DH(), _service2String(pService));); + pService->m_ProbeInformation.m_ProbingStatus = enuProbingStatus::Done; + pService->m_ProbeInformation.m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + + _callServiceProbeResultCallback(*pService, true); + + // Prepare to announce service + pService->m_ProbeInformation.m_u8SentCount = 0; + pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Prepared service announcing.\n\n"), _DH());); + } + } // else: Probing already finished OR waiting for next time slot + else if ((enuProbingStatus::Done == pService->m_ProbeInformation.m_ProbingStatus) && + (pService->m_ProbeInformation.m_Timeout.expired())) + { + + if ((bResult = _announceService(*pService))) // Announce service + { + ++pService->m_ProbeInformation.m_u8SentCount; // 1.. + + if (MDNS_ANNOUNCE_COUNT > pService->m_ProbeInformation.m_u8SentCount) + { + pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY * pow(2, (pService->m_ProbeInformation.m_u8SentCount - 1))); // 2^(0..) -> 1, 2, 4, ... + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Announcing service '%s' (%lu)\n\n"), _DH(), _service2String(pService), pService->m_ProbeInformation.m_u8SentCount);); + } + else + { + pService->m_ProbeInformation.m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Done service announcing for '%s'\n\n"), _DH(), _service2String(pService));); + } + } + } + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: FAILED!\n\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::clsHost::_resetProbeStatus + + Resets the probe status. + If 'p_bRestart' is set, the status is set to ProbingStatus_NotStarted. Consequently, + when running 'updateProbeStatus' (which is done in every '_update' loop), the probing + process is restarted. +*/ +bool MDNSResponder::clsHost::_resetProbeStatus(bool p_bRestart /*= true*/) +{ + m_HostProbeInformation.clear(false); + m_HostProbeInformation.m_ProbingStatus = (p_bRestart ? enuProbingStatus::ReadyToStart : enuProbingStatus::Done); + + for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) + { + pService->m_ProbeInformation.clear(false); + pService->m_ProbeInformation.m_ProbingStatus = (p_bRestart ? enuProbingStatus::ReadyToStart : enuProbingStatus::Done); + } + return true; +} + +/* + MDNSResponder::clsHost::_hasProbesWaitingForAnswers +*/ +bool MDNSResponder::clsHost::_hasProbesWaitingForAnswers(void) const +{ + bool bResult = ((enuProbingStatus::InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing + (0 < m_HostProbeInformation.m_u8SentCount)); // And really probing + + for (stcService* pService = m_pServices; ((!bResult) && (pService)); pService = pService->m_pNext) + { + bResult = ((enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing + (0 < pService->m_ProbeInformation.m_u8SentCount)); // And really probing + } + return bResult; +} + +/* + MDNSResponder::clsHost::_sendHostProbe + + Asks (probes) in the local network for the planned host domain + - (eg. esp8266.local) + + To allow 'tiebreaking' (see '_parseQuery'), the answers for these questions are delivered in + the 'knwon answers' section of the query. + Host domain: + - A/AAAA (eg. esp8266.esp -> 192.168.2.120) +*/ +bool MDNSResponder::clsHost::_sendHostProbe(void) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendHostProbe (%s.local, %lu)\n"), _DH(), m_pcHostName, millis());); + + bool bResult = true; + + // Requests for host domain + stcSendParameter sendParameter; + sendParameter.m_bCacheFlush = false; // RFC 6762 10.2 + + sendParameter.m_pQuestions = new stcRRQuestion; + if (((bResult = (0 != sendParameter.m_pQuestions))) && + ((bResult = _buildDomainForHost(m_pcHostName, sendParameter.m_pQuestions->m_Header.m_Domain)))) + { + + //sendParameter.m_pQuestions->m_bUnicast = true; + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet + + // Add known answers +#ifdef MDNS_IPV4_SUPPORT + sendParameter.m_u32HostReplyMask |= static_cast<uint32_t>(enuContentFlag::A); // Add A answer +#endif +#ifdef MDNS_IPV6_SUPPORT + sendParameter.m_u32HostReplyMask |= static_cast<uint32_t>(enuContentFlag::AAAA); // Add AAAA answer +#endif + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _sendHostProbe: FAILED to create host question!\n"), _DH());); + if (sendParameter.m_pQuestions) + { + delete sendParameter.m_pQuestions; + sendParameter.m_pQuestions = 0; + } + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendHostProbe: FAILED!\n"), _DH());); + return ((bResult) && + (_sendMDNSMessage(sendParameter))); +} + +/* + MDNSResponder::clsHost::_sendServiceProbe + + Asks (probes) in the local network for the planned service instance domain + - (eg. MyESP._http._tcp.local). + + To allow 'tiebreaking' (see '_parseQuery'), the answers for these questions are delivered in + the 'knwon answers' section of the query. + Service domain: + - SRV (eg. MyESP._http._tcp.local -> 5000 esp8266.local) + - PTR NAME (eg. _http._tcp.local -> MyESP._http._tcp.local) (TODO: Check if needed, maybe TXT is better) +*/ +bool MDNSResponder::clsHost::_sendServiceProbe(stcService& p_rService) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendServiceProbe (%s, %lu)\n"), _DH(), _service2String(&p_rService), millis());); + + bool bResult = true; + + // Requests for service instance domain + stcSendParameter sendParameter; + sendParameter.m_bCacheFlush = false; // RFC 6762 10.2 + + sendParameter.m_pQuestions = new stcRRQuestion; + if (((bResult = (0 != sendParameter.m_pQuestions))) && + ((bResult = _buildDomainForService(p_rService, true, sendParameter.m_pQuestions->m_Header.m_Domain)))) + { + + sendParameter.m_pQuestions->m_bUnicast = true; + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet + + // Add known answers + p_rService.m_u32ReplyMask = (static_cast<uint32_t>(enuContentFlag::SRV) | static_cast<uint32_t>(enuContentFlag::PTR_NAME)); // Add SRV and PTR NAME answers + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _sendServiceProbe: FAILED to create service question!\n"), _DH());); + if (sendParameter.m_pQuestions) + { + delete sendParameter.m_pQuestions; + sendParameter.m_pQuestions = 0; + } + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendServiceProbe: FAILED!\n"), _DH());); + return ((bResult) && + (_sendMDNSMessage(sendParameter))); +} + +/* + MDNSResponder::clsHost::_cancelProbingForHost +*/ +bool MDNSResponder::clsHost::_cancelProbingForHost(void) +{ + bool bResult = false; + + m_HostProbeInformation.clear(false); + + // Send host notification + bResult = _callHostProbeResultCallback(false); + + for (stcService* pService = m_pServices; ((!bResult) && (pService)); pService = pService->m_pNext) + { + bResult = _cancelProbingForService(*pService); + } + return bResult; +} + +/* + MDNSResponder::clsHost::_cancelProbingForService +*/ +bool MDNSResponder::clsHost::_cancelProbingForService(stcService& p_rService) +{ + p_rService.m_ProbeInformation.clear(false); + + // Send notification + return _callServiceProbeResultCallback(p_rService, false); +} + +/* + MDNSResponder::clsHost::_callHostProbeResultCallback + +*/ +bool MDNSResponder::clsHost::_callHostProbeResultCallback(bool p_bResult) +{ + if (m_HostProbeInformation.m_fnProbeResultCallback) + { + m_HostProbeInformation.m_fnProbeResultCallback(*this, m_pcHostName, p_bResult); + } + else if (!p_bResult) + { + // Auto-Handle failure by changing the host name, use '-' as divider between base name and index + char* pcHostDomainTemp = strdup(m_pcHostName); + if (pcHostDomainTemp) + { + if (MDNSResponder::indexDomain(pcHostDomainTemp, "-", 0)) + { + setHostName(pcHostDomainTemp); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _callHostProbeResultCallback: FAILED to update host domain '%s'!\n"), _DH(), (m_pcHostName ? : ""));); + } + free(pcHostDomainTemp); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _callHostProbeResultCallback: FAILED to copy host domain '%s'!\n"), _DH(), (m_pcHostName ? : ""));); + } + } + return true; +} + +/* + MDNSResponder::clsHost::_callServiceProbeResultCallback + +*/ +bool MDNSResponder::clsHost::_callServiceProbeResultCallback(MDNSResponder::clsHost::stcService& p_rService, + bool p_bResult) +{ + if (p_rService.m_ProbeInformation.m_fnProbeResultCallback) + { + p_rService.m_ProbeInformation.m_fnProbeResultCallback(*this, p_rService, p_rService.m_pcName, p_bResult); + } + else if (!p_bResult) + { + // Auto-Handle failure by changing the service name, use ' #' as divider between base name and index + char* pcServiceNameTemp = strdup(p_rService.m_pcName); + if (pcServiceNameTemp) + { + if (MDNSResponder::indexDomain(pcServiceNameTemp, " #", 0)) + { + setServiceName(&p_rService, pcServiceNameTemp); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _callServiceProbeResultCallback: FAILED to update service name for '%s'!\n"), _DH(), _service2String(&p_rService));); + } + free(pcServiceNameTemp); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _callServiceProbeResultCallback: FAILED to copy service name for '%s'!\n"), _DH(), _service2String(&p_rService));); + } + } + return true; +} + + +/** + ANNOUNCING +*/ + +/* + MDNSResponder::clsHost::_announce + + Announces the host domain: + - A/AAAA (eg. esp8266.local -> 192.168.2.120) + - PTR (eg. 192.168.2.120.in-addr.arpa -> esp8266.local) + + and all presented services: + - PTR_TYPE (_services._dns-sd._udp.local -> _http._tcp.local) + - PTR_NAME (eg. _http._tcp.local -> MyESP8266._http._tcp.local) + - SRV (eg. MyESP8266._http._tcp.local -> 5000 esp8266.local) + - TXT (eg. MyESP8266._http._tcp.local -> c#=1) + + Goodbye (Un-Announcing) for the host domain and all services is also handled here. + Goodbye messages are created by setting the TTL for the answer to 0, this happens + inside the '_writeXXXAnswer' procs via 'sendParameter.m_bUnannounce = true' +*/ +bool MDNSResponder::clsHost::_announce(bool p_bAnnounce, + bool p_bIncludeServices) +{ + bool bResult = false; + + stcSendParameter sendParameter; + if (enuProbingStatus::Done == m_HostProbeInformation.m_ProbingStatus) + { + bResult = true; + + sendParameter.m_Response = stcSendParameter::enuResponseType::Unsolicited; // Announces are 'Unsolicited authorative responses' + sendParameter.m_bAuthorative = true; + sendParameter.m_bCacheFlush = true; // RFC 6762 8.3 + sendParameter.m_bUnannounce = !p_bAnnounce; // When unannouncing, the TTL is set to '0' while creating the answers + + // Announce host + sendParameter.m_u32HostReplyMask = 0; +#ifdef MDNS_IPV4_SUPPORT + sendParameter.m_u32HostReplyMask |= static_cast<uint32_t>(enuContentFlag::A); // A answer + sendParameter.m_u32HostReplyMask |= static_cast<uint32_t>(enuContentFlag::PTR_IPv4); // PTR_IPv4 answer +#endif +#ifdef MDNS_IPV6_SUPPORT + sendParameter.m_u32HostReplyMask |= static_cast<uint32_t>(enuContentFlag::AAAA); // AAAA answer + sendParameter.m_u32HostReplyMask |= static_cast<uint32_t>(enuContentFlag::PTR_IPv6); // PTR_IPv6 answer +#endif + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _announce: Announcing host %s (content: %s)\n"), _DH(), m_pcHostName, _replyFlags2String(sendParameter.m_u32HostReplyMask));); + + if (p_bIncludeServices) + { + // Announce services (service type, name, SRV (location) and TXTs) + for (stcService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + { + if (enuProbingStatus::Done == pService->m_ProbeInformation.m_ProbingStatus) + { + pService->m_u32ReplyMask = (static_cast<uint32_t>(enuContentFlag::PTR_TYPE) | static_cast<uint32_t>(enuContentFlag::PTR_NAME) | static_cast<uint32_t>(enuContentFlag::SRV) | static_cast<uint32_t>(enuContentFlag::TXT)); + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _announce: Announcing service '%s' (content %s)\n"), _DH(), _service2String(pService), _replyFlags2String(pService->m_u32ReplyMask));); + } + } + } + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _announce: FAILED!\n"), _DH());); + return ((bResult) && + (_sendMDNSMessage(sendParameter))); +} + +/* + MDNSResponder::clsHost::_announceService +*/ +bool MDNSResponder::clsHost::_announceService(MDNSResponder::clsHost::stcService& p_rService, + bool p_bAnnounce /*= true*/) +{ + bool bResult = false; + + stcSendParameter sendParameter; + if (enuProbingStatus::Done == p_rService.m_ProbeInformation.m_ProbingStatus) + { + + sendParameter.m_Response = stcSendParameter::enuResponseType::Unsolicited; // Announces are 'Unsolicited authorative responses' + sendParameter.m_bAuthorative = true; + sendParameter.m_bUnannounce = !p_bAnnounce; // When unannouncing, the TTL is set to '0' while creating the answers + + // DON'T announce host + sendParameter.m_u32HostReplyMask = 0; + + // Announce services (service type, name, SRV (location) and TXTs) + p_rService.m_u32ReplyMask = (static_cast<uint32_t>(enuContentFlag::PTR_TYPE) | static_cast<uint32_t>(enuContentFlag::PTR_NAME) | static_cast<uint32_t>(enuContentFlag::SRV) | static_cast<uint32_t>(enuContentFlag::TXT)); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _announceService: Announcing service '%s' (content: %s)\n"), _DH(), _service2String(&p_rService), _replyFlags2String(p_rService.m_u32ReplyMask));); + + bResult = true; + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _announceService: FAILED!\n"), _DH());); + return ((bResult) && + (_sendMDNSMessage(sendParameter))); +} + + +/** + QUERY CACHE +*/ + +/* + MDNSResponder::clsHost::_checkQueryCache + + For any 'living' query (m_bAwaitingAnswers == true) all available answers (their components) + are checked for topicality based on the stored reception time and the answers TTL. + When the components TTL is outlasted by more than 80%, a new question is generated, to get updated information. + When no update arrived (in time), the component is removed from the answer (cache). + +*/ +bool MDNSResponder::clsHost::_checkQueryCache(void) +{ + bool bResult = true; + + DEBUG_EX_INFO( + bool printedInfo = false; + ); + for (stcQuery* pQuery = m_pQueries; ((bResult) && (pQuery)); pQuery = pQuery->m_pNext) + { + // + // Resend dynamic queries, if not already done often enough + if ((!pQuery->m_bLegacyQuery) && + (pQuery->m_ResendTimeout.expired())) + { + + if ((bResult = _sendMDNSQuery(*pQuery))) + { + // The re-query rate is increased to more than one hour (RFC 6762 5.2) + ++pQuery->m_u8SentCount; + uint32_t u32NewDelay = (MDNS_DYNAMIC_QUERY_RESEND_DELAY * pow(2, std::min((pQuery->m_u8SentCount - 1), 12))); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Next query in %u seconds!\n"), _DH(), (u32NewDelay));); + pQuery->m_ResendTimeout.reset(u32NewDelay); + } + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: %s to resend query!\n"), _DH(), (bResult ? "Succeeded" : "FAILED")); + printedInfo = true; + ); + } + + // + // Schedule updates for cached answers + if (pQuery->m_bAwaitingAnswers) + { + stcQuery::stcAnswer* pSQAnswer = pQuery->m_pAnswers; + while ((bResult) && + (pSQAnswer)) + { + stcQuery::stcAnswer* pNextSQAnswer = pSQAnswer->m_pNext; + + // 1. level answer + if ((bResult) && + (pSQAnswer->m_TTLServiceDomain.flagged())) + { + + if (!pSQAnswer->m_TTLServiceDomain.finalTimeoutLevel()) + { + + bResult = ((_sendMDNSQuery(*pQuery)) && + (pSQAnswer->m_TTLServiceDomain.restart())); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: PTR update scheduled for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" %s\n"), (bResult ? "OK" : "FAILURE")); + printedInfo = true; + ); + } + else + { + // Timed out! -> Delete + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::ServiceDomain), false); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Will remove PTR answer for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + printedInfo = true; + ); + + bResult = pQuery->removeAnswer(pSQAnswer); + pSQAnswer = 0; + continue; // Don't use this answer anymore + } + } // ServiceDomain flagged + + // 2. level answers + // HostDomain & Port (from SRV) + if ((bResult) && + (pSQAnswer->m_TTLHostDomainAndPort.flagged())) + { + + if (!pSQAnswer->m_TTLHostDomainAndPort.finalTimeoutLevel()) + { + + bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_SRV)) && + (pSQAnswer->m_TTLHostDomainAndPort.restart())); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: SRV update scheduled for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" host domain and port %s\n"), (bResult ? "OK" : "FAILURE")); + printedInfo = true; + ); + } + else + { + // Timed out! -> Delete + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Will remove SRV answer for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); + printedInfo = true; + ); + // Delete + pSQAnswer->m_HostDomain.clear(); + //pSQAnswer->releaseHostDomain(); + pSQAnswer->m_u16Port = 0; + pSQAnswer->m_TTLHostDomainAndPort.set(0); + typeQueryAnswerType queryAnswerContentFlags = (static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain) | static_cast<typeQueryAnswerType>(enuQueryAnswerType::Port)); + // As the host domain is the base for the IPv4- and IPv6Address, remove these too +#ifdef MDNS_IPV4_SUPPORT + pSQAnswer->releaseIPv4Addresses(); + queryAnswerContentFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address); +#endif +#ifdef MDNS_IPV6_SUPPORT + pSQAnswer->releaseIPv6Addresses(); + queryAnswerContentFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address); +#endif + + // Remove content flags for deleted answer parts + pSQAnswer->m_QueryAnswerFlags &= ~queryAnswerContentFlags; + _executeQueryCallback(*pQuery, *pSQAnswer, queryAnswerContentFlags, false); + } + } // HostDomainAndPort flagged + + // Txts (from TXT) + if ((bResult) && + (pSQAnswer->m_TTLTxts.flagged())) + { + + if (!pSQAnswer->m_TTLTxts.finalTimeoutLevel()) + { + + bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_TXT)) && + (pSQAnswer->m_TTLTxts.restart())); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: TXT update scheduled for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" TXTs %s\n"), (bResult ? "OK" : "FAILURE")); + printedInfo = true; + ); + } + else + { + // Timed out! -> Delete + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Will remove TXT answer for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); + printedInfo = true; + ); + // Delete + pSQAnswer->m_Txts.clear(); + pSQAnswer->m_TTLTxts.set(0); + + // Remove content flags for deleted answer parts + pSQAnswer->m_QueryAnswerFlags &= ~static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts); + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts), false); + } + } // TXTs flagged + + // 3. level answers +#ifdef MDNS_IPV4_SUPPORT + // IPv4Address (from A) + stcQuery::stcAnswer::stcIPAddress* pIPv4Address = pSQAnswer->m_pIPv4Addresses; + bool bAUpdateQuerySent = false; + while ((pIPv4Address) && + (bResult)) + { + + stcQuery::stcAnswer::stcIPAddress* pNextIPv4Address = pIPv4Address->m_pNext; // Get 'next' early, as 'current' may be deleted at the end... + + if (pIPv4Address->m_TTL.flagged()) + { + + if (!pIPv4Address->m_TTL.finalTimeoutLevel()) // Needs update + { + + if ((bAUpdateQuerySent) || + ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_A)))) + { + + pIPv4Address->m_TTL.restart(); + bAUpdateQuerySent = true; + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: IPv4 update scheduled for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IPv4 address (%s)\n"), (pIPv4Address->m_IPAddress.toString().c_str())); + printedInfo = true; + ); + } + } + else + { + // Timed out! -> Delete + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Will remove IPv4 answer for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IPv4 address\n")); + printedInfo = true; + ); + pSQAnswer->removeIPv4Address(pIPv4Address); + if (!pSQAnswer->m_pIPv4Addresses) // NO IPv4 address left -> remove content flag + { + pSQAnswer->m_QueryAnswerFlags &= ~static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address); + } + // Notify client + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address), false); + } + } // IPv4 flagged + + pIPv4Address = pNextIPv4Address; // Next + } // while +#endif +#ifdef MDNS_IPV6_SUPPORT + // IPv6Address (from AAAA) + stcQuery::stcAnswer::stcIPAddress* pIPv6Address = pSQAnswer->m_pIPv6Addresses; + bool bAAAAUpdateQuerySent = false; + while ((pIPv6Address) && + (bResult)) + { + + stcQuery::stcAnswer::stcIPAddress* pNextIPv6Address = pIPv6Address->m_pNext; // Get 'next' early, as 'current' may be deleted at the end... + + if (pIPv6Address->m_TTL.flagged()) + { + + if (!pIPv6Address->m_TTL.finalTimeoutLevel()) // Needs update + { + + if ((bAAAAUpdateQuerySent) || + ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) + { + + pIPv6Address->m_TTL.restart(); + bAAAAUpdateQuerySent = true; + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: IPv6 update scheduled for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IPv6 address (%s)\n"), (pIPv6Address->m_IPAddress.toString().c_str())); + printedInfo = true; + ); + } + } + else + { + // Timed out! -> Delete + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Will remove answer for "), _DH()); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IPv6 address\n")); + printedInfo = true; + ); + pSQAnswer->removeIPv6Address(pIPv6Address); + if (!pSQAnswer->m_pIPv6Addresses) // NO IPv6 address left -> remove content flag + { + pSQAnswer->m_QueryAnswerFlags &= ~static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address); + } + // Notify client + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address), false); + } + } // IPv6 flagged + + pIPv6Address = pNextIPv6Address; // Next + } // while +#endif + pSQAnswer = pNextSQAnswer; + } + } + } + DEBUG_EX_INFO(if (printedInfo) DEBUG_OUTPUT.printf_P(PSTR("\n"));); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: FAILED!\n"), _DH());); + return bResult; +} + + +/* + MDNSResponder::clsHost::_replyMaskForHost + + Determines the relavant host answers for the given question. + - A question for the hostname (eg. esp8266.local) will result in an A/AAAA (eg. 192.168.2.129) reply. + - A question for the reverse IP address (eg. 192-168.2.120.inarpa.arpa) will result in an PTR_IPv4 (eg. esp8266.local) reply. + + In addition, a full name match (question domain == host domain) is marked. +*/ +uint32_t MDNSResponder::clsHost::_replyMaskForHost(const MDNSResponder::clsHost::stcRRHeader& p_RRHeader, + bool* p_pbFullNameMatch /*= 0*/) const +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _replyMaskForHost\n"));); + + uint32_t u32ReplyMask = 0; + (p_pbFullNameMatch ? *p_pbFullNameMatch = false : 0); + + if ((DNS_RRCLASS_IN == (p_RRHeader.m_Attributes.m_u16Class & (~0x8000))) || + (DNS_RRCLASS_ANY == (p_RRHeader.m_Attributes.m_u16Class & (~0x8000)))) + { + + if ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + { + // PTR request +#ifdef MDNS_IPV4_SUPPORT + stcRRDomain reverseIPv4Domain; + if ((_getResponderIPAddress(enuIPProtocolType::V4).isSet()) && + (_buildDomainForReverseIPv4(_getResponderIPAddress(enuIPProtocolType::V4), reverseIPv4Domain)) && + (p_RRHeader.m_Domain == reverseIPv4Domain)) + { + // Reverse domain match + u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::PTR_IPv4); + } +#endif +#ifdef MDNS_IPV6_SUPPORT + stcRRDomain reverseIPv6Domain; + if ((_getResponderIPAddress(enuIPProtocolType::V6).isSet()) && + (_buildDomainForReverseIPv6(_getResponderIPAddress(enuIPProtocolType::V6), reverseIPv6Domain)) && + (p_RRHeader.m_Domain == reverseIPv6Domain)) + { + // Reverse domain match + u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::PTR_IPv6); + } +#endif + } // Address qeuest + + stcRRDomain hostDomain; + if ((_buildDomainForHost(m_pcHostName, hostDomain)) && + (p_RRHeader.m_Domain == hostDomain)) // Host domain match + { + + (p_pbFullNameMatch ? (*p_pbFullNameMatch = true) : (0)); + +#ifdef MDNS_IPV4_SUPPORT + if ((DNS_RRTYPE_A == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + { + // IPv4 address request + u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::A); + } +#endif +#ifdef MDNS_IPV6_SUPPORT + if ((DNS_RRTYPE_AAAA == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + { + // IPv6 address request + u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::AAAA); + } +#endif + } + } + else + { + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _replyMaskForHost: INVALID RR-class (0x%04X)!\n"), p_RRHeader.m_Attributes.m_u16Class);); + } + DEBUG_EX_INFO(if (u32ReplyMask) DEBUG_OUTPUT.printf_P(PSTR("%s _replyMaskForHost: %s\n"), _DH(), _replyFlags2String(u32ReplyMask));); + return u32ReplyMask; +} + +/* + MDNSResponder::clsHost::_replyMaskForService + + Determines the relevant service answers for the given question + - A PTR dns-sd service enum question (_services.dns-sd._udp.local) will result into an PTR_TYPE (eg. _http._tcp.local) answer + - A PTR service type question (eg. _http._tcp.local) will result into an PTR_NAME (eg. MyESP._http._tcp.local) answer + - A PTR service name question (eg. MyESP._http._tcp.local) will result into an PTR_NAME (eg. MyESP._http._tcp.local) answer + - A SRV service name question (eg. MyESP._http._tcp.local) will result into an SRV (eg. 5000 MyESP.local) answer + - A TXT service name question (eg. MyESP._http._tcp.local) will result into an TXT (eg. c#=1) answer + + In addition, a full name match (question domain == service instance domain) is marked. +*/ +uint32_t MDNSResponder::clsHost::_replyMaskForService(const MDNSResponder::clsHost::stcRRHeader& p_RRHeader, + const MDNSResponder::clsHost::stcService& p_Service, + bool* p_pbFullNameMatch /*= 0*/) const +{ + uint32_t u32ReplyMask = 0; + (p_pbFullNameMatch ? *p_pbFullNameMatch = false : 0); + + if ((DNS_RRCLASS_IN == (p_RRHeader.m_Attributes.m_u16Class & (~0x8000))) || + (DNS_RRCLASS_ANY == (p_RRHeader.m_Attributes.m_u16Class & (~0x8000)))) + { + + stcRRDomain DNSSDDomain; + if ((_buildDomainForDNSSD(DNSSDDomain)) && // _services._dns-sd._udp.local + (p_RRHeader.m_Domain == DNSSDDomain) && + ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type))) + { + // Common service info requested + u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::PTR_TYPE); + } + + stcRRDomain serviceDomain; + if ((_buildDomainForService(p_Service, false, serviceDomain)) && // eg. _http._tcp.local + (p_RRHeader.m_Domain == serviceDomain) && + ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type))) + { + // Special service info requested + u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::PTR_NAME); + } + + if ((_buildDomainForService(p_Service, true, serviceDomain)) && // eg. MyESP._http._tcp.local + (p_RRHeader.m_Domain == serviceDomain)) + { + + (p_pbFullNameMatch ? (*p_pbFullNameMatch = true) : (0)); + + if ((DNS_RRTYPE_SRV == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + { + // Instance info SRV requested + u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::SRV); + } + if ((DNS_RRTYPE_TXT == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + { + // Instance info TXT requested + u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::TXT); + } + } + } + else + { + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _replyMaskForService: INVALID RR-class (0x%04X)!\n"), p_RRHeader.m_Attributes.m_u16Class);); + } + DEBUG_EX_INFO(if (u32ReplyMask) DEBUG_OUTPUT.printf_P(PSTR("%s _replyMaskForService(%s.%s.%s): %s\n"), _DH(), p_Service.m_pcName, p_Service.m_pcServiceType, p_Service.m_pcProtocol, _replyFlags2String(u32ReplyMask));); + return u32ReplyMask; +} + +} // namespace MDNSImplementation + +} // namespace esp8266 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Debug.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Debug.cpp new file mode 100755 index 0000000000..3f43a54089 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Debug.cpp @@ -0,0 +1,327 @@ +/* + LEAmDNS2_Host_Debug.h + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +//#include <arch/cc.h> +//#include <sys/time.h> +//#include <HardwareSerial.h> +//#include <IPAddress.h> +//#include <lwip/ip_addr.h> +//#include <lwip/netif.h> +//#include <WString.h> +//#include <cstdint> + +/* + ESP8266mDNS Control.cpp +*/ + +extern "C" { + //#include "user_interface.h" +} + +#include "LEAmDNS2_lwIPdefs.h" +#include "LEAmDNS2_Priv.h" + +#ifdef MDNS_IPV4_SUPPORT +//#include <lwip/igmp.h> +#endif +#ifdef MDNS_IPV6_SUPPORT +//#include <lwip/mld6.h> +#endif + + +namespace esp8266 +{ + +/* + LEAmDNS +*/ +namespace experimental +{ + +#ifdef DEBUG_ESP_MDNS_RESPONDER + +/* + MDNSResponder::clsHost::_DH +*/ +const char* MDNSResponder::clsHost::_DH(const MDNSResponder::clsHost::stcService* p_pMDNSService /*= 0*/) const +{ + static char acBuffer[16 + 64]; + + *acBuffer = 0; + if (p_pMDNSService) + { + sprintf_P(acBuffer, PSTR("[MDNSResponder (%c%c%u)->%s]"), m_rNetIf.name[0], m_rNetIf.name[1], m_rNetIf.num, _service2String(p_pMDNSService)); + } + else + { + sprintf_P(acBuffer, PSTR("[MDNSResponder (%c%c%u)]"), m_rNetIf.name[0], m_rNetIf.name[1], m_rNetIf.num); + } + return acBuffer; +} + +/* + MDNSResponder::clsHost::_service2String +*/ +const char* MDNSResponder::clsHost::_service2String(const MDNSResponder::clsHost::stcService* p_pMDNSService) const +{ + static char acBuffer[64]; + + *acBuffer = 0; + if (p_pMDNSService) + { + sprintf_P(acBuffer, PSTR("%s.%s%s.%s%s.local"), + (p_pMDNSService->m_pcName ? : "-"), + (p_pMDNSService->m_pcServiceType ? ('_' == *(p_pMDNSService->m_pcServiceType) ? "" : "_") : "-"), + (p_pMDNSService->m_pcServiceType ? : "-"), + (p_pMDNSService->m_pcProtocol ? ('_' == *(p_pMDNSService->m_pcProtocol) ? "" : "_") : "-"), + (p_pMDNSService->m_pcProtocol ? : "-")); + } + return acBuffer; +} + +/* + MDNSResponder::clsHost::_printRRDomain +*/ +bool MDNSResponder::clsHost::_printRRDomain(const MDNSResponder::clsHost::stcRRDomain& p_RRDomain) const +{ + //DEBUG_OUTPUT.printf_P(PSTR("Domain: ")); + + const char* pCursor = p_RRDomain.m_acName; + uint8_t u8Length = *pCursor++; + if (u8Length) + { + while (u8Length) + { + for (uint8_t u = 0; u < u8Length; ++u) + { + DEBUG_OUTPUT.printf_P(PSTR("%c"), *(pCursor++)); + } + u8Length = *pCursor++; + if (u8Length) + { + DEBUG_OUTPUT.printf_P(PSTR(".")); + } + } + } + else // empty domain + { + DEBUG_OUTPUT.printf_P(PSTR("-empty-")); + } + //DEBUG_OUTPUT.printf_P(PSTR("\n")); + + return true; +} + +/* + MDNSResponder::clsHost::_printRRAnswer +*/ +bool MDNSResponder::clsHost::_printRRAnswer(const MDNSResponder::clsHost::stcRRAnswer& p_RRAnswer) const +{ + DEBUG_OUTPUT.printf_P(PSTR("%s RRAnswer: "), _DH()); + _printRRDomain(p_RRAnswer.m_Header.m_Domain); + DEBUG_OUTPUT.printf_P(PSTR(" Type:0x%04X Class:0x%04X TTL:%u, "), p_RRAnswer.m_Header.m_Attributes.m_u16Type, p_RRAnswer.m_Header.m_Attributes.m_u16Class, p_RRAnswer.m_u32TTL); + switch (p_RRAnswer.m_Header.m_Attributes.m_u16Type & (~0x8000)) // Topmost bit might carry 'cache flush' flag + { +#ifdef MDNS_IPV4_SUPPORT + case DNS_RRTYPE_A: + DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((const stcRRAnswerA*)&p_RRAnswer)->m_IPAddress.toString().c_str()); + break; +#endif + case DNS_RRTYPE_PTR: + DEBUG_OUTPUT.printf_P(PSTR("PTR ")); + _printRRDomain(((const stcRRAnswerPTR*)&p_RRAnswer)->m_PTRDomain); + break; + case DNS_RRTYPE_TXT: + { + size_t stTxtLength = ((const stcRRAnswerTXT*)&p_RRAnswer)->m_Txts.c_strLength(); + char* pTxts = new char[stTxtLength]; + if (pTxts) + { + ((/*const c_str()!!*/stcRRAnswerTXT*)&p_RRAnswer)->m_Txts.c_str(pTxts); + DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts); + delete[] pTxts; + } + break; + } +#ifdef MDNS_IPV6_SUPPORT + case DNS_RRTYPE_AAAA: + DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((stcRRAnswerAAAA*&)p_RRAnswer)->m_IPAddress.toString().c_str()); + break; +#endif + case DNS_RRTYPE_SRV: + DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((const stcRRAnswerSRV*)&p_RRAnswer)->m_u16Port); + _printRRDomain(((const stcRRAnswerSRV*)&p_RRAnswer)->m_SRVDomain); + break; + default: + DEBUG_OUTPUT.printf_P(PSTR("generic ")); + break; + } + DEBUG_OUTPUT.printf_P(PSTR("\n")); + + return true; +} + +/* + MDNSResponder::clsHost::_RRType2Name +*/ +const char* MDNSResponder::clsHost::_RRType2Name(uint16_t p_u16RRType) const +{ + static char acRRName[16]; + *acRRName = 0; + + switch (p_u16RRType & (~0x8000)) // Topmost bit might carry 'cache flush' flag + { + case DNS_RRTYPE_A: strcpy(acRRName, "A"); break; + case DNS_RRTYPE_PTR: strcpy(acRRName, "PTR"); break; + case DNS_RRTYPE_TXT: strcpy(acRRName, "TXT"); break; + case DNS_RRTYPE_AAAA: strcpy(acRRName, "AAAA"); break; + case DNS_RRTYPE_SRV: strcpy(acRRName, "SRV"); break; + case DNS_RRTYPE_NSEC: strcpy(acRRName, "NSEC"); break; + case DNS_RRTYPE_ANY: strcpy(acRRName, "ANY"); break; + default: + sprintf(acRRName, "Unknown(0x%04X)", p_u16RRType); // MAX 15! + } + return acRRName; +} + +/* + MDNSResponder::clsHost::_RRClass2String +*/ +const char* MDNSResponder::clsHost::_RRClass2String(uint16_t p_u16RRClass, + bool p_bIsQuery) const +{ + static char acClassString[16]; + *acClassString = 0; + + if (p_u16RRClass & 0x0001) + { + strcat(acClassString, "IN "); // 3 + } + if (p_u16RRClass & 0x8000) + { + strcat(acClassString, (p_bIsQuery ? "UNICAST " : "FLUSH ")); // 8/6 + } + + return acClassString; // 11 +} + +/* + MDNSResponder::clsHost::_replyFlags2String +*/ +const char* MDNSResponder::clsHost::_replyFlags2String(uint32_t p_u32ReplyFlags) const +{ + static char acFlagsString[64]; + + *acFlagsString = 0; + if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::A)) + { + strcat(acFlagsString, "A "); // 2 + } + if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)) + { + strcat(acFlagsString, "PTR_IPv4 "); // 7 + } + if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::PTR_IPv6)) + { + strcat(acFlagsString, "PTR_IPv6 "); // 7 + } + if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::AAAA)) + { + strcat(acFlagsString, "AAAA "); // 5 + } + if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::PTR_TYPE)) + { + strcat(acFlagsString, "PTR_TYPE "); // 9 + } + if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::PTR_NAME)) + { + strcat(acFlagsString, "PTR_NAME "); // 9 + } + if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::TXT)) + { + strcat(acFlagsString, "TXT "); // 4 + } + if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::SRV)) + { + strcat(acFlagsString, "SRV "); // 4 + } + if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::NSEC)) + { + strcat(acFlagsString, "NSEC "); // 5 + } + + if (0 == p_u32ReplyFlags) + { + strcpy(acFlagsString, "none"); + } + + return acFlagsString; // 63 +} + +/* + MDNSResponder::clsHost::_NSECBitmap2String +*/ +const char* MDNSResponder::clsHost::_NSECBitmap2String(const stcNSECBitmap* p_pNSECBitmap) const +{ + static char acFlagsString[32]; + + *acFlagsString = 0; + if (p_pNSECBitmap->getBit(DNS_RRTYPE_A)) + { + strcat(acFlagsString, "A "); // 2 + } + if (p_pNSECBitmap->getBit(DNS_RRTYPE_PTR)) + { + strcat(acFlagsString, "PTR "); // 4 + } + if (p_pNSECBitmap->getBit(DNS_RRTYPE_AAAA)) + { + strcat(acFlagsString, "AAAA "); // 5 + } + if (p_pNSECBitmap->getBit(DNS_RRTYPE_TXT)) + { + strcat(acFlagsString, "TXT "); // 4 + } + if (p_pNSECBitmap->getBit(DNS_RRTYPE_SRV)) + { + strcat(acFlagsString, "SRV "); // 4 + } + if (p_pNSECBitmap->getBit(DNS_RRTYPE_NSEC)) + { + strcat(acFlagsString, "NSEC "); // 5 + } + + if (!*acFlagsString) + { + strcpy(acFlagsString, "none"); + } + + return acFlagsString; // 31 +} + +#endif // DEBUG_ESP_MDNS_RESPONDER + +} // namespace MDNSImplementation + +} // namespace esp8266 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Structs.cpp new file mode 100755 index 0000000000..7121abcfca --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Structs.cpp @@ -0,0 +1,2435 @@ +/* + LEAmDNS2_Host_Structs.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#include "LEAmDNS2_Priv.h" +#include "LEAmDNS2_lwIPdefs.h" + +namespace esp8266 +{ + +/* + LEAmDNS +*/ +namespace experimental +{ + +/** + Internal CLASSES & STRUCTS +*/ + +/** + MDNSResponder::clsHost::stcServiceTxt + + One MDNS TXT item. + m_pcValue may be '\0'. + Objects can be chained together (list, m_pNext). + A 'm_bTemp' flag differentiates between static and dynamic items. + Output as byte array 'c#=1' is supported. +*/ + +/* + MDNSResponder::clsHost::stcServiceTxt::stcServiceTxt constructor +*/ +MDNSResponder::clsHost::stcServiceTxt::stcServiceTxt(const char* p_pcKey /*= 0*/, + const char* p_pcValue /*= 0*/, + bool p_bTemp /*= false*/) + : m_pNext(0), + m_pcKey(0), + m_pcValue(0), + m_bTemp(p_bTemp) +{ + setKey(p_pcKey); + setValue(p_pcValue); +} + +/* + MDNSResponder::clsHost::stcServiceTxt::stcServiceTxt copy-constructor +*/ +MDNSResponder::clsHost::stcServiceTxt::stcServiceTxt(const MDNSResponder::clsHost::stcServiceTxt& p_Other) + : m_pNext(0), + m_pcKey(0), + m_pcValue(0), + m_bTemp(false) +{ + operator=(p_Other); +} + +/* + MDNSResponder::clsHost::stcServiceTxt::~stcServiceTxt destructor +*/ +MDNSResponder::clsHost::stcServiceTxt::~stcServiceTxt(void) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcServiceTxt::operator= +*/ +MDNSResponder::clsHost::stcServiceTxt& MDNSResponder::clsHost::stcServiceTxt::operator=(const MDNSResponder::clsHost::stcServiceTxt& p_Other) +{ + if (&p_Other != this) + { + clear(); + set(p_Other.m_pcKey, p_Other.m_pcValue, p_Other.m_bTemp); + } + return *this; +} + +/* + MDNSResponder::clsHost::stcServiceTxt::clear +*/ +bool MDNSResponder::clsHost::stcServiceTxt::clear(void) +{ + releaseKey(); + releaseValue(); + return true; +} + +/* + MDNSResponder::clsHost::stcServiceTxt::allocKey +*/ +char* MDNSResponder::clsHost::stcServiceTxt::allocKey(size_t p_stLength) +{ + releaseKey(); + if (p_stLength) + { + m_pcKey = new char[p_stLength + 1]; + } + return m_pcKey; +} + +/* + MDNSResponder::clsHost::stcServiceTxt::setKey +*/ +bool MDNSResponder::clsHost::stcServiceTxt::setKey(const char* p_pcKey, + size_t p_stLength) +{ + bool bResult = false; + + releaseKey(); + if (p_stLength) + { + if (allocKey(p_stLength)) + { + strncpy(m_pcKey, p_pcKey, p_stLength); + m_pcKey[p_stLength] = 0; + bResult = true; + } + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcServiceTxt::setKey +*/ +bool MDNSResponder::clsHost::stcServiceTxt::setKey(const char* p_pcKey) +{ + return setKey(p_pcKey, (p_pcKey ? strlen(p_pcKey) : 0)); +} + +/* + MDNSResponder::clsHost::stcServiceTxt::releaseKey +*/ +bool MDNSResponder::clsHost::stcServiceTxt::releaseKey(void) +{ + if (m_pcKey) + { + delete[] m_pcKey; + m_pcKey = 0; + } + return true; +} + +/* + MDNSResponder::clsHost::stcServiceTxt::allocValue +*/ +char* MDNSResponder::clsHost::stcServiceTxt::allocValue(size_t p_stLength) +{ + releaseValue(); + if (p_stLength) + { + m_pcValue = new char[p_stLength + 1]; + } + return m_pcValue; +} + +/* + MDNSResponder::clsHost::stcServiceTxt::setValue +*/ +bool MDNSResponder::clsHost::stcServiceTxt::setValue(const char* p_pcValue, + size_t p_stLength) +{ + bool bResult = false; + + releaseValue(); + if (p_stLength) + { + if (allocValue(p_stLength)) + { + strncpy(m_pcValue, p_pcValue, p_stLength); + m_pcValue[p_stLength] = 0; + bResult = true; + } + } + else // No value -> also OK + { + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcServiceTxt::setValue +*/ +bool MDNSResponder::clsHost::stcServiceTxt::setValue(const char* p_pcValue) +{ + return setValue(p_pcValue, (p_pcValue ? strlen(p_pcValue) : 0)); +} + +/* + MDNSResponder::clsHost::stcServiceTxt::releaseValue +*/ +bool MDNSResponder::clsHost::stcServiceTxt::releaseValue(void) +{ + if (m_pcValue) + { + delete[] m_pcValue; + m_pcValue = 0; + } + return true; +} + +/* + MDNSResponder::clsHost::stcServiceTxt::set +*/ +bool MDNSResponder::clsHost::stcServiceTxt::set(const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp /*= false*/) +{ + m_bTemp = p_bTemp; + return ((setKey(p_pcKey)) && + (setValue(p_pcValue))); +} + +/* + MDNSResponder::clsHost::stcServiceTxt::update +*/ +bool MDNSResponder::clsHost::stcServiceTxt::update(const char* p_pcValue) +{ + return setValue(p_pcValue); +} + +/* + MDNSResponder::clsHost::stcServiceTxt::length + + length of eg. 'c#=1' without any closing '\0' +*/ +size_t MDNSResponder::clsHost::stcServiceTxt::length(void) const +{ + size_t stLength = 0; + if (m_pcKey) + { + stLength += strlen(m_pcKey); // Key + stLength += 1; // '=' + stLength += (m_pcValue ? strlen(m_pcValue) : 0); // Value + } + return stLength; +} + + +/** + MDNSResponder::clsHost::stcServiceTxts + + A list of zero or more MDNS TXT items. + Dynamic TXT items can be removed by 'removeTempTxts'. + A TXT item can be looke up by its 'key' member. + Export as ';'-separated byte array is supported. + Export as 'length byte coded' byte array is supported. + Comparision ((all A TXT items in B and equal) AND (all B TXT items in A and equal)) is supported. + +*/ + +/* + MDNSResponder::clsHost::stcServiceTxts::stcServiceTxts contructor +*/ +MDNSResponder::clsHost::stcServiceTxts::stcServiceTxts(void) + : m_pTxts(0), + m_pcCache(0) +{ +} + +/* + MDNSResponder::clsHost::stcServiceTxts::stcServiceTxts copy-constructor +*/ +MDNSResponder::clsHost::stcServiceTxts::stcServiceTxts(const stcServiceTxts& p_Other) + : m_pTxts(0), + m_pcCache(0) +{ + operator=(p_Other); +} + +/* + MDNSResponder::clsHost::stcServiceTxts::~stcServiceTxts destructor +*/ +MDNSResponder::clsHost::stcServiceTxts::~stcServiceTxts(void) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcServiceTxts::operator= +*/ +MDNSResponder::clsHost::stcServiceTxts& MDNSResponder::clsHost::stcServiceTxts::operator=(const stcServiceTxts& p_Other) +{ + if (this != &p_Other) + { + clear(); + + for (stcServiceTxt* pOtherTxt = p_Other.m_pTxts; pOtherTxt; pOtherTxt = pOtherTxt->m_pNext) + { + add(new stcServiceTxt(*pOtherTxt)); + } + } + return *this; +} + +/* + MDNSResponder::clsHost::stcServiceTxts::clear +*/ +bool MDNSResponder::clsHost::stcServiceTxts::clear(void) +{ + while (m_pTxts) + { + stcServiceTxt* pNext = m_pTxts->m_pNext; + delete m_pTxts; + m_pTxts = pNext; + } + return clearCache(); +} + +/* + MDNSResponder::clsHost::stcServiceTxts::clearCache +*/ +bool MDNSResponder::clsHost::stcServiceTxts::clearCache(void) +{ + if (m_pcCache) + { + delete[] m_pcCache; + m_pcCache = 0; + } + return true; +} + +/* + MDNSResponder::clsHost::stcServiceTxts::add +*/ +bool MDNSResponder::clsHost::stcServiceTxts::add(MDNSResponder::clsHost::stcServiceTxt* p_pTxt) +{ + bool bResult = false; + + if (p_pTxt) + { + p_pTxt->m_pNext = m_pTxts; + m_pTxts = p_pTxt; + bResult = true; + } + return ((clearCache()) && + (bResult)); +} + +/* + MDNSResponder::clsHost::stcServiceTxts::remove +*/ +bool MDNSResponder::clsHost::stcServiceTxts::remove(stcServiceTxt* p_pTxt) +{ + bool bResult = false; + + if (p_pTxt) + { + stcServiceTxt* pPred = m_pTxts; + while ((pPred) && + (pPred->m_pNext != p_pTxt)) + { + pPred = pPred->m_pNext; + } + if (pPred) + { + pPred->m_pNext = p_pTxt->m_pNext; + delete p_pTxt; + bResult = true; + } + else if (m_pTxts == p_pTxt) // No predecesor, but first item + { + m_pTxts = p_pTxt->m_pNext; + delete p_pTxt; + bResult = true; + } + } + return ((clearCache()) && + (bResult)); +} + +/* + MDNSResponder::clsHost::stcServiceTxts::removeTempTxts +*/ +bool MDNSResponder::clsHost::stcServiceTxts::removeTempTxts(void) +{ + bool bResult = true; + + stcServiceTxt* pTxt = m_pTxts; + while ((bResult) && + (pTxt)) + { + stcServiceTxt* pNext = pTxt->m_pNext; + if (pTxt->m_bTemp) + { + bResult = remove(pTxt); + } + pTxt = pNext; + } + return ((clearCache()) && + (bResult)); +} + +/* + MDNSResponder::clsHost::stcServiceTxts::find +*/ +MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::stcServiceTxts::find(const char* p_pcKey) +{ + stcServiceTxt* pResult = 0; + + for (stcServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) + { + if ((p_pcKey) && + (0 == strcmp(pTxt->m_pcKey, p_pcKey))) + { + pResult = pTxt; + break; + } + } + return pResult; +} + +/* + MDNSResponder::clsHost::stcServiceTxts::find +*/ +const MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::stcServiceTxts::find(const char* p_pcKey) const +{ + const stcServiceTxt* pResult = 0; + + for (const stcServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) + { + if ((p_pcKey) && + (0 == strcmp(pTxt->m_pcKey, p_pcKey))) + { + + pResult = pTxt; + break; + } + } + return pResult; +} + +/* + MDNSResponder::clsHost::stcServiceTxts::find +*/ +MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::stcServiceTxts::find(const stcServiceTxt* p_pTxt) +{ + stcServiceTxt* pResult = 0; + + for (stcServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) + { + if (p_pTxt == pTxt) + { + pResult = pTxt; + break; + } + } + return pResult; +} + +/* + MDNSResponder::clsHost::stcServiceTxts::length +*/ +uint16_t MDNSResponder::clsHost::stcServiceTxts::length(void) const +{ + uint16_t u16Length = 0; + + stcServiceTxt* pTxt = m_pTxts; + while (pTxt) + { + u16Length += 1; // Length byte + u16Length += pTxt->length(); // Text + pTxt = pTxt->m_pNext; + } + return u16Length; +} + +/* + MDNSResponder::clsHost::stcServiceTxts::c_strLength + + (incl. closing '\0'). Length bytes place is used for delimiting ';' and closing '\0' +*/ +size_t MDNSResponder::clsHost::stcServiceTxts::c_strLength(void) const +{ + return length(); +} + +/* + MDNSResponder::clsHost::stcServiceTxts::c_str +*/ +bool MDNSResponder::clsHost::stcServiceTxts::c_str(char* p_pcBuffer) +{ + bool bResult = false; + + if (p_pcBuffer) + { + bResult = true; + + *p_pcBuffer = 0; + for (stcServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) + { + size_t stLength; + if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) + { + if (pTxt != m_pTxts) + { + *p_pcBuffer++ = ';'; + } + strncpy(p_pcBuffer, pTxt->m_pcKey, stLength); p_pcBuffer[stLength] = 0; + p_pcBuffer += stLength; + *p_pcBuffer++ = '='; + if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) + { + strncpy(p_pcBuffer, pTxt->m_pcValue, stLength); p_pcBuffer[stLength] = 0; + p_pcBuffer += stLength; + } + } + } + *p_pcBuffer++ = 0; + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcServiceTxts::c_str +*/ +const char* MDNSResponder::clsHost::stcServiceTxts::c_str(void) const +{ + + if ((!m_pcCache) && + (m_pTxts) && + ((((stcServiceTxts*)this)->m_pcCache = new char[c_strLength()]))) // TRANSPARENT caching + { + ((stcServiceTxts*)this)->c_str(m_pcCache); + } + return m_pcCache; +} + +/* + MDNSResponder::clsHost::stcServiceTxts::bufferLength + + (incl. closing '\0'). +*/ +size_t MDNSResponder::clsHost::stcServiceTxts::bufferLength(void) const +{ + return (length() + 1); +} + +/* + MDNSResponder::clsHost::stcServiceTxts::toBuffer +*/ +bool MDNSResponder::clsHost::stcServiceTxts::buffer(char* p_pcBuffer) +{ + bool bResult = false; + + if (p_pcBuffer) + { + bResult = true; + + *p_pcBuffer = 0; + for (stcServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) + { + *(unsigned char*)p_pcBuffer++ = pTxt->length(); + size_t stLength; + if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) + { + memcpy(p_pcBuffer, pTxt->m_pcKey, stLength); + p_pcBuffer += stLength; + *p_pcBuffer++ = '='; + if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) + { + memcpy(p_pcBuffer, pTxt->m_pcValue, stLength); + p_pcBuffer += stLength; + } + } + } + *p_pcBuffer++ = 0; + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcServiceTxts::compare +*/ +bool MDNSResponder::clsHost::stcServiceTxts::compare(const MDNSResponder::clsHost::stcServiceTxts& p_Other) const +{ + bool bResult = false; + + if ((bResult = (length() == p_Other.length()))) + { + // Compare A->B + for (const stcServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) + { + const stcServiceTxt* pOtherTxt = p_Other.find(pTxt->m_pcKey); + bResult = ((pOtherTxt) && + (pTxt->m_pcValue) && + (pOtherTxt->m_pcValue) && + (strlen(pTxt->m_pcValue) == strlen(pOtherTxt->m_pcValue)) && + (0 == strcmp(pTxt->m_pcValue, pOtherTxt->m_pcValue))); + } + // Compare B->A + for (const stcServiceTxt* pOtherTxt = p_Other.m_pTxts; ((bResult) && (pOtherTxt)); pOtherTxt = pOtherTxt->m_pNext) + { + const stcServiceTxt* pTxt = find(pOtherTxt->m_pcKey); + bResult = ((pTxt) && + (pOtherTxt->m_pcValue) && + (pTxt->m_pcValue) && + (strlen(pOtherTxt->m_pcValue) == strlen(pTxt->m_pcValue)) && + (0 == strcmp(pOtherTxt->m_pcValue, pTxt->m_pcValue))); + } + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcServiceTxts::operator== +*/ +bool MDNSResponder::clsHost::stcServiceTxts::operator==(const stcServiceTxts& p_Other) const +{ + return compare(p_Other); +} + +/* + MDNSResponder::clsHost::stcServiceTxts::operator!= +*/ +bool MDNSResponder::clsHost::stcServiceTxts::operator!=(const stcServiceTxts& p_Other) const +{ + return !compare(p_Other); +} + + +/** + MDNSResponder::clsHost::stcProbeInformation_Base + + Probing status information for a host or service domain + +*/ + +/* + MDNSResponder::clsHost::stcProbeInformation_Base::stcProbeInformation_Base constructor +*/ +MDNSResponder::clsHost::stcProbeInformation_Base::stcProbeInformation_Base(void) + : m_ProbingStatus(enuProbingStatus::WaitingForData), + m_u8SentCount(0), + m_Timeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()), + m_bConflict(false), + m_bTiebreakNeeded(false) +{ +} + +/* + MDNSResponder::clsHost::stcProbeInformation_Base::clear +*/ +bool MDNSResponder::clsHost::stcProbeInformation_Base::clear(void) +{ + m_ProbingStatus = enuProbingStatus::WaitingForData; + m_u8SentCount = 0; + m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + m_bConflict = false; + m_bTiebreakNeeded = false; + + return true; +} + + +/** + MDNSResponder::clsHost::stcProbeInformation_Host + + Probing status information for a host or service domain + +*/ + +/* + MDNSResponder::clsHost::stcProbeInformation_Host::stcProbeInformation_Host constructor +*/ +MDNSResponder::clsHost::stcProbeInformation_Host::stcProbeInformation_Host(void) + : m_fnProbeResultCallback(0) +{ +} + +/* + MDNSResponder::clsHost::stcProbeInformation_Host::clear +*/ +bool MDNSResponder::clsHost::stcProbeInformation_Host::clear(bool p_bClearUserdata /*= false*/) +{ + if (p_bClearUserdata) + { + m_fnProbeResultCallback = 0; + } + return stcProbeInformation_Base::clear(); +} + + +/** + MDNSResponder::clsHost::stcProbeInformation_Service + + Probing status information for a host or service domain + +*/ + +/* + MDNSResponder::clsHost::stcProbeInformation_Service::stcProbeInformation_Service constructor +*/ +MDNSResponder::clsHost::stcProbeInformation_Service::stcProbeInformation_Service(void) + : m_fnProbeResultCallback(0) +{ +} + +/* + MDNSResponder::clsHost::stcProbeInformation_Service::clear +*/ +bool MDNSResponder::clsHost::stcProbeInformation_Service::clear(bool p_bClearUserdata /*= false*/) +{ + if (p_bClearUserdata) + { + m_fnProbeResultCallback = 0; + } + return stcProbeInformation_Base::clear(); +} + + +/** + MDNSResponder::clsHost::stcService + + A MDNS service object (to be announced by the MDNS responder) + The service instance may be '\0'; in this case the hostname is used + and the flag m_bAutoName is set. If the hostname changes, all 'auto- + named' services are renamed also. + m_u8Replymask is used while preparing a response to a MDNS query. It is + resetted in '_sendMDNSMessage' afterwards. +*/ + +/* + MDNSResponder::clsHost::stcService::stcService constructor +*/ +MDNSResponder::clsHost::stcService::stcService(const char* p_pcName /*= 0*/, + const char* p_pcServiceType /*= 0*/, + const char* p_pcProtocol /*= 0*/) + : m_pNext(0), + m_pcName(0), + m_bAutoName(false), + m_pcServiceType(0), + m_pcProtocol(0), + m_u16Port(0), + m_u32ReplyMask(0), + m_fnTxtCallback(0) +{ + setName(p_pcName); + setServiceType(p_pcServiceType); + setProtocol(p_pcProtocol); +} + +/* + MDNSResponder::clsHost::stcService::~stcService destructor +*/ +MDNSResponder::clsHost::stcService::~stcService(void) +{ + releaseName(); + releaseServiceType(); + releaseProtocol(); +} + +/* + MDNSResponder::clsHost::stcService::setName +*/ +bool MDNSResponder::clsHost::stcService::setName(const char* p_pcName) +{ + bool bResult = false; + + releaseName(); + size_t stLength = (p_pcName ? strlen(p_pcName) : 0); + if (stLength) + { + if ((bResult = (0 != (m_pcName = new char[stLength + 1])))) + { + strncpy(m_pcName, p_pcName, stLength); + m_pcName[stLength] = 0; + } + } + else + { + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcService::releaseName +*/ +bool MDNSResponder::clsHost::stcService::releaseName(void) +{ + if (m_pcName) + { + delete[] m_pcName; + m_pcName = 0; + } + return true; +} + +/* + MDNSResponder::clsHost::stcService::setServiceType +*/ +bool MDNSResponder::clsHost::stcService::setServiceType(const char* p_pcServiceType) +{ + bool bResult = false; + + releaseServiceType(); + size_t stLength = (p_pcServiceType ? strlen(p_pcServiceType) : 0); + if (stLength) + { + if ((bResult = (0 != (m_pcServiceType = new char[stLength + 1])))) + { + strncpy(m_pcServiceType, p_pcServiceType, stLength); + m_pcServiceType[stLength] = 0; + } + } + else + { + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcService::releaseServiceType +*/ +bool MDNSResponder::clsHost::stcService::releaseServiceType(void) +{ + if (m_pcServiceType) + { + delete[] m_pcServiceType; + m_pcServiceType = 0; + } + return true; +} + +/* + MDNSResponder::clsHost::stcService::setProtocol +*/ +bool MDNSResponder::clsHost::stcService::setProtocol(const char* p_pcProtocol) +{ + bool bResult = false; + + releaseProtocol(); + size_t stLength = (p_pcProtocol ? strlen(p_pcProtocol) : 0); + if (stLength) + { + if ((bResult = (0 != (m_pcProtocol = new char[stLength + 1])))) + { + strncpy(m_pcProtocol, p_pcProtocol, stLength); + m_pcProtocol[stLength] = 0; + } + } + else + { + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcService::releaseProtocol +*/ +bool MDNSResponder::clsHost::stcService::releaseProtocol(void) +{ + if (m_pcProtocol) + { + delete[] m_pcProtocol; + m_pcProtocol = 0; + } + return true; +} + +/* + MDNSResponder::clsHost::stcService::probeStatus +*/ +bool MDNSResponder::clsHost::stcService::probeStatus(void) const +{ + return (enuProbingStatus::Done == m_ProbeInformation.m_ProbingStatus); +} + + +/** + MDNSResponder::clsHost::stcMsgHeader + + A MDNS message haeder. + +*/ + +/* + MDNSResponder::clsHost::stcMsgHeader::stcMsgHeader +*/ +MDNSResponder::clsHost::stcMsgHeader::stcMsgHeader(uint16_t p_u16ID /*= 0*/, + bool p_bQR /*= false*/, + uint8_t p_u8Opcode /*= 0*/, + bool p_bAA /*= false*/, + bool p_bTC /*= false*/, + bool p_bRD /*= false*/, + bool p_bRA /*= false*/, + uint8_t p_u8RCode /*= 0*/, + uint16_t p_u16QDCount /*= 0*/, + uint16_t p_u16ANCount /*= 0*/, + uint16_t p_u16NSCount /*= 0*/, + uint16_t p_u16ARCount /*= 0*/) + : m_u16ID(p_u16ID), + m_1bQR(p_bQR), m_4bOpcode(p_u8Opcode), m_1bAA(p_bAA), m_1bTC(p_bTC), m_1bRD(p_bRD), + m_1bRA(p_bRA), m_3bZ(0), m_4bRCode(p_u8RCode), + m_u16QDCount(p_u16QDCount), + m_u16ANCount(p_u16ANCount), + m_u16NSCount(p_u16NSCount), + m_u16ARCount(p_u16ARCount) +{ +} + + +/** + MDNSResponder::clsHost::stcRRDomain + + A MDNS domain object. + The labels of the domain are stored (DNS-like encoded) in 'm_acName': + [length byte]varlength label[length byte]varlength label[0] + 'm_u16NameLength' stores the used length of 'm_acName'. + Dynamic label addition is supported. + Comparison is supported. + Export as byte array 'esp8266.local' is supported. + +*/ + +/* + MDNSResponder::clsHost::stcRRDomain::stcRRDomain constructor +*/ +MDNSResponder::clsHost::stcRRDomain::stcRRDomain(void) + : m_u16NameLength(0), + m_pcDecodedName(0) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcRRDomain::stcRRDomain copy-constructor +*/ +MDNSResponder::clsHost::stcRRDomain::stcRRDomain(const stcRRDomain& p_Other) + : m_u16NameLength(0), + m_pcDecodedName(0) +{ + operator=(p_Other); +} + +/* + MDNSResponder::clsHost::stcRRDomain::stcRRDomain destructor +*/ +MDNSResponder::clsHost::stcRRDomain::~stcRRDomain(void) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcRRDomain::operator = +*/ +MDNSResponder::clsHost::stcRRDomain& MDNSResponder::clsHost::stcRRDomain::operator=(const stcRRDomain& p_Other) +{ + if (&p_Other != this) + { + clear(); + memcpy(m_acName, p_Other.m_acName, sizeof(m_acName)); + m_u16NameLength = p_Other.m_u16NameLength; + } + return *this; +} + +/* + MDNSResponder::clsHost::stcRRDomain::clear +*/ +bool MDNSResponder::clsHost::stcRRDomain::clear(void) +{ + memset(m_acName, 0, sizeof(m_acName)); + m_u16NameLength = 0; + return clearNameCache(); +} + +/* + MDNSResponder::clsHost::stcRRDomain::clearNameCache +*/ +bool MDNSResponder::clsHost::stcRRDomain::clearNameCache(void) +{ + if (m_pcDecodedName) + { + delete[] m_pcDecodedName; + m_pcDecodedName = 0; + } + return true; +} + +/* + MDNSResponder::clsHost::stcRRDomain::addLabel +*/ +bool MDNSResponder::clsHost::stcRRDomain::addLabel(const char* p_pcLabel, + bool p_bPrependUnderline /*= false*/) +{ + bool bResult = false; + + size_t stLength = (p_pcLabel + ? (strlen(p_pcLabel) + (p_bPrependUnderline ? 1 : 0)) + : 0); + if ((MDNS_DOMAIN_LABEL_MAXLENGTH >= stLength) && + (MDNS_DOMAIN_MAXLENGTH >= (m_u16NameLength + (1 + stLength)))) + { + // Length byte + m_acName[m_u16NameLength] = (unsigned char)stLength; // Might be 0! + ++m_u16NameLength; + // Label + if (stLength) + { + if (p_bPrependUnderline) + { + m_acName[m_u16NameLength++] = '_'; + --stLength; + } + strncpy(&(m_acName[m_u16NameLength]), p_pcLabel, stLength); m_acName[m_u16NameLength + stLength] = 0; + m_u16NameLength += stLength; + } + bResult = clearNameCache(); + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcRRDomain::compare +*/ +bool MDNSResponder::clsHost::stcRRDomain::compare(const stcRRDomain& p_Other) const +{ + bool bResult = false; + + if (m_u16NameLength == p_Other.m_u16NameLength) + { + const char* pT = m_acName; + const char* pO = p_Other.m_acName; + while ((pT) && + (pO) && + (*((unsigned char*)pT) == *((unsigned char*)pO)) && // Same length AND + (0 == strncasecmp((pT + 1), (pO + 1), *((unsigned char*)pT)))) // Same content + { + if (*((unsigned char*)pT)) // Not 0 + { + pT += (1 + * ((unsigned char*)pT)); // Shift by length byte and lenght + pO += (1 + * ((unsigned char*)pO)); + } + else // Is 0 -> Successfully reached the end + { + bResult = true; + break; + } + } + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcRRDomain::operator == +*/ +bool MDNSResponder::clsHost::stcRRDomain::operator==(const stcRRDomain& p_Other) const +{ + return compare(p_Other); +} + +/* + MDNSResponder::clsHost::stcRRDomain::operator != +*/ +bool MDNSResponder::clsHost::stcRRDomain::operator!=(const stcRRDomain& p_Other) const +{ + return !compare(p_Other); +} + +/* + MDNSResponder::clsHost::stcRRDomain::operator > +*/ +bool MDNSResponder::clsHost::stcRRDomain::operator>(const stcRRDomain& p_Other) const +{ + // TODO: Check, if this is a good idea... + return !compare(p_Other); +} + +/* + MDNSResponder::clsHost::stcRRDomain::c_strLength +*/ +size_t MDNSResponder::clsHost::stcRRDomain::c_strLength(void) const +{ + size_t stLength = 0; + + unsigned char* pucLabelLength = (unsigned char*)m_acName; + while (*pucLabelLength) + { + stLength += (*pucLabelLength + 1 /* +1 for '.' or '\0'*/); + pucLabelLength += (*pucLabelLength + 1); + } + return stLength; +} + +/* + MDNSResponder::clsHost::stcRRDomain::c_str (const) +*/ +bool MDNSResponder::clsHost::stcRRDomain::c_str(char* p_pcBuffer) const +{ + bool bResult = false; + + if (p_pcBuffer) + { + *p_pcBuffer = 0; + unsigned char* pucLabelLength = (unsigned char*)m_acName; + while (*pucLabelLength) + { + memcpy(p_pcBuffer, (const char*)(pucLabelLength + 1), *pucLabelLength); + p_pcBuffer += *pucLabelLength; + pucLabelLength += (*pucLabelLength + 1); + *p_pcBuffer++ = (*pucLabelLength ? '.' : '\0'); + } + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcRRDomain::c_str +*/ +const char* MDNSResponder::clsHost::stcRRDomain::c_str(void) const +{ + if ((!m_pcDecodedName) && + (m_u16NameLength) && + ((((stcRRDomain*)this)->m_pcDecodedName = new char[c_strLength()]))) // TRANSPARENT caching + { + ((stcRRDomain*)this)->c_str(m_pcDecodedName); + } + return m_pcDecodedName; +} + + +/** + MDNSResponder::clsHost::stcRRAttributes + + A MDNS attributes object. + +*/ + +/* + MDNSResponder::clsHost::stcRRAttributes::stcRRAttributes constructor +*/ +MDNSResponder::clsHost::stcRRAttributes::stcRRAttributes(uint16_t p_u16Type /*= 0*/, + uint16_t p_u16Class /*= 1 DNS_RRCLASS_IN Internet*/) + : m_u16Type(p_u16Type), + m_u16Class(p_u16Class) +{ +} + +/* + MDNSResponder::clsHost::stcRRAttributes::stcRRAttributes copy-constructor +*/ +MDNSResponder::clsHost::stcRRAttributes::stcRRAttributes(const MDNSResponder::clsHost::stcRRAttributes& p_Other) +{ + operator=(p_Other); +} + +/* + MDNSResponder::clsHost::stcRRAttributes::operator = +*/ +MDNSResponder::clsHost::stcRRAttributes& MDNSResponder::clsHost::stcRRAttributes::operator=(const MDNSResponder::clsHost::stcRRAttributes& p_Other) +{ + if (&p_Other != this) + { + m_u16Type = p_Other.m_u16Type; + m_u16Class = p_Other.m_u16Class; + } + return *this; +} + + +/** + MDNSResponder::clsHost::stcRRHeader + + A MDNS record header (domain and attributes) object. + +*/ + +/* + MDNSResponder::clsHost::stcRRHeader::stcRRHeader constructor +*/ +MDNSResponder::clsHost::stcRRHeader::stcRRHeader(void) +{ +} + +/* + MDNSResponder::clsHost::stcRRHeader::stcRRHeader copy-constructor +*/ +MDNSResponder::clsHost::stcRRHeader::stcRRHeader(const stcRRHeader& p_Other) +{ + operator=(p_Other); +} + +/* + MDNSResponder::clsHost::stcRRHeader::operator = +*/ +MDNSResponder::clsHost::stcRRHeader& MDNSResponder::clsHost::stcRRHeader::operator=(const MDNSResponder::clsHost::stcRRHeader& p_Other) +{ + if (&p_Other != this) + { + m_Domain = p_Other.m_Domain; + m_Attributes = p_Other.m_Attributes; + } + return *this; +} + +/* + MDNSResponder::clsHost::stcRRHeader::clear +*/ +bool MDNSResponder::clsHost::stcRRHeader::clear(void) +{ + m_Domain.clear(); + return true; +} + + +/** + MDNSResponder::clsHost::stcRRQuestion + + A MDNS question record object (header + question flags) + +*/ + +/* + MDNSResponder::clsHost::stcRRQuestion::stcRRQuestion constructor +*/ +MDNSResponder::clsHost::stcRRQuestion::stcRRQuestion(void) + : m_pNext(0), + m_bUnicast(false) +{ +} + + +/** + MDNSResponder::clsHost::stcNSECBitmap + + A MDNS question record object (header + question flags) + +*/ + +/* + MDNSResponder::clsHost::stcNSECBitmap::stcNSECBitmap constructor +*/ +MDNSResponder::clsHost::stcNSECBitmap::stcNSECBitmap(void) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcNSECBitmap::stcNSECBitmap destructor +*/ +bool MDNSResponder::clsHost::stcNSECBitmap::clear(void) +{ + memset(m_au8BitmapData, 0, sizeof(m_au8BitmapData)); + return true; +} + +/* + MDNSResponder::clsHost::stcNSECBitmap::length +*/ +uint16_t MDNSResponder::clsHost::stcNSECBitmap::length(void) const +{ + return sizeof(m_au8BitmapData); // 6 +} + +/* + MDNSResponder::clsHost::stcNSECBitmap::setBit +*/ +bool MDNSResponder::clsHost::stcNSECBitmap::setBit(uint16_t p_u16Bit) +{ + bool bResult = false; + + if ((p_u16Bit) && + (length() > (p_u16Bit / 8))) // bit between 0..47(2F) + { + + uint8_t& ru8Byte = m_au8BitmapData[p_u16Bit / 8]; + uint8_t u8Flag = 1 << (7 - (p_u16Bit % 8)); // (7 - (0..7)) = 7..0 + + ru8Byte |= u8Flag; + + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcNSECBitmap::getBit +*/ +bool MDNSResponder::clsHost::stcNSECBitmap::getBit(uint16_t p_u16Bit) const +{ + bool bResult = false; + + if ((p_u16Bit) && + (length() > (p_u16Bit / 8))) // bit between 0..47(2F) + { + + uint8_t u8Byte = m_au8BitmapData[p_u16Bit / 8]; + uint8_t u8Flag = 1 << (7 - (p_u16Bit % 8)); // (7 - (0..7)) = 7..0 + + bResult = (u8Byte & u8Flag); + } + return bResult; +} + + +/** + MDNSResponder::clsHost::stcRRAnswer + + A MDNS answer record object (header + answer content). + This is a 'virtual' base class for all other MDNS answer classes. + +*/ + +/* + MDNSResponder::clsHost::stcRRAnswer::stcRRAnswer constructor +*/ +MDNSResponder::clsHost::stcRRAnswer::stcRRAnswer(enuAnswerType p_AnswerType, + const MDNSResponder::clsHost::stcRRHeader& p_Header, + uint32_t p_u32TTL) + : m_pNext(0), + m_AnswerType(p_AnswerType), + m_Header(p_Header), + m_u32TTL(p_u32TTL) +{ + // Extract 'cache flush'-bit + m_bCacheFlush = (m_Header.m_Attributes.m_u16Class & 0x8000); + m_Header.m_Attributes.m_u16Class &= (~0x8000); +} + +/* + MDNSResponder::clsHost::stcRRAnswer::~stcRRAnswer destructor +*/ +MDNSResponder::clsHost::stcRRAnswer::~stcRRAnswer(void) +{ +} + +/* + MDNSResponder::clsHost::stcRRAnswer::answerType +*/ +MDNSResponder::clsHost::enuAnswerType MDNSResponder::clsHost::stcRRAnswer::answerType(void) const +{ + return m_AnswerType; +} + +/* + MDNSResponder::clsHost::stcRRAnswer::clear +*/ +bool MDNSResponder::clsHost::stcRRAnswer::clear(void) +{ + m_pNext = 0; + m_Header.clear(); + return true; +} + + +/** + MDNSResponder::clsHost::stcRRAnswerA + + A MDNS A answer object. + Extends the base class by an IPv4 address member. + +*/ + +#ifdef MDNS_IPV4_SUPPORT +/* + MDNSResponder::clsHost::stcRRAnswerA::stcRRAnswerA constructor +*/ +MDNSResponder::clsHost::stcRRAnswerA::stcRRAnswerA(const MDNSResponder::clsHost::stcRRHeader& p_Header, + uint32_t p_u32TTL) + : stcRRAnswer(enuAnswerType::A, p_Header, p_u32TTL), + m_IPAddress() +{ +} + +/* + MDNSResponder::clsHost::stcRRAnswerA::stcRRAnswerA destructor +*/ +MDNSResponder::clsHost::stcRRAnswerA::~stcRRAnswerA(void) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcRRAnswerA::clear +*/ +bool MDNSResponder::clsHost::stcRRAnswerA::clear(void) +{ + m_IPAddress = IPAddress(); + return true; +} +#endif + + +/** + MDNSResponder::clsHost::stcRRAnswerPTR + + A MDNS PTR answer object. + Extends the base class by a MDNS domain member. + +*/ + +/* + MDNSResponder::clsHost::stcRRAnswerPTR::stcRRAnswerPTR constructor +*/ +MDNSResponder::clsHost::stcRRAnswerPTR::stcRRAnswerPTR(const MDNSResponder::clsHost::stcRRHeader& p_Header, + uint32_t p_u32TTL) + : stcRRAnswer(enuAnswerType::PTR, p_Header, p_u32TTL) +{ +} + +/* + MDNSResponder::clsHost::stcRRAnswerPTR::~stcRRAnswerPTR destructor +*/ +MDNSResponder::clsHost::stcRRAnswerPTR::~stcRRAnswerPTR(void) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcRRAnswerPTR::clear +*/ +bool MDNSResponder::clsHost::stcRRAnswerPTR::clear(void) +{ + m_PTRDomain.clear(); + return true; +} + + +/** + MDNSResponder::clsHost::stcRRAnswerTXT + + A MDNS TXT answer object. + Extends the base class by a MDNS TXT items list member. + +*/ + +/* + MDNSResponder::clsHost::stcRRAnswerTXT::stcRRAnswerTXT constructor +*/ +MDNSResponder::clsHost::stcRRAnswerTXT::stcRRAnswerTXT(const MDNSResponder::clsHost::stcRRHeader& p_Header, + uint32_t p_u32TTL) + : stcRRAnswer(enuAnswerType::TXT, p_Header, p_u32TTL) +{ +} + +/* + MDNSResponder::clsHost::stcRRAnswerTXT::~stcRRAnswerTXT destructor +*/ +MDNSResponder::clsHost::stcRRAnswerTXT::~stcRRAnswerTXT(void) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcRRAnswerTXT::clear +*/ +bool MDNSResponder::clsHost::stcRRAnswerTXT::clear(void) +{ + m_Txts.clear(); + return true; +} + + +/** + MDNSResponder::clsHost::stcRRAnswerAAAA + + A MDNS AAAA answer object. + Extends the base class by an IPv6 address member. + +*/ + +#ifdef MDNS_IPV6_SUPPORT +/* + MDNSResponder::clsHost::stcRRAnswerAAAA::stcRRAnswerAAAA constructor +*/ +MDNSResponder::clsHost::stcRRAnswerAAAA::stcRRAnswerAAAA(const MDNSResponder::clsHost::stcRRHeader& p_Header, + uint32_t p_u32TTL) + : stcRRAnswer(enuAnswerType::AAAA, p_Header, p_u32TTL), + m_IPAddress() +{ +} + +/* + MDNSResponder::clsHost::stcRRAnswerAAAA::~stcRRAnswerAAAA destructor +*/ +MDNSResponder::clsHost::stcRRAnswerAAAA::~stcRRAnswerAAAA(void) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcRRAnswerAAAA::clear +*/ +bool MDNSResponder::clsHost::stcRRAnswerAAAA::clear(void) +{ + m_IPAddress = IPAddress(); + return true; +} +#endif + + +/** + MDNSResponder::clsHost::stcRRAnswerSRV + + A MDNS SRV answer object. + Extends the base class by a port member. + +*/ + +/* + MDNSResponder::clsHost::stcRRAnswerSRV::stcRRAnswerSRV constructor +*/ +MDNSResponder::clsHost::stcRRAnswerSRV::stcRRAnswerSRV(const MDNSResponder::clsHost::stcRRHeader& p_Header, + uint32_t p_u32TTL) + : stcRRAnswer(enuAnswerType::SRV, p_Header, p_u32TTL), + m_u16Priority(0), + m_u16Weight(0), + m_u16Port(0) +{ +} + +/* + MDNSResponder::clsHost::stcRRAnswerSRV::~stcRRAnswerSRV destructor +*/ +MDNSResponder::clsHost::stcRRAnswerSRV::~stcRRAnswerSRV(void) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcRRAnswerSRV::clear +*/ +bool MDNSResponder::clsHost::stcRRAnswerSRV::clear(void) +{ + m_u16Priority = 0; + m_u16Weight = 0; + m_u16Port = 0; + m_SRVDomain.clear(); + return true; +} + + +/** + MDNSResponder::clsHost::stcRRAnswerGeneric + + An unknown (generic) MDNS answer object. + Extends the base class by a RDATA buffer member. + +*/ + +/* + MDNSResponder::clsHost::stcRRAnswerGeneric::stcRRAnswerGeneric constructor +*/ +MDNSResponder::clsHost::stcRRAnswerGeneric::stcRRAnswerGeneric(const stcRRHeader& p_Header, + uint32_t p_u32TTL) + : stcRRAnswer(enuAnswerType::Generic, p_Header, p_u32TTL), + m_u16RDLength(0), + m_pu8RDData(0) +{ +} + +/* + MDNSResponder::clsHost::stcRRAnswerGeneric::~stcRRAnswerGeneric destructor +*/ +MDNSResponder::clsHost::stcRRAnswerGeneric::~stcRRAnswerGeneric(void) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcRRAnswerGeneric::clear +*/ +bool MDNSResponder::clsHost::stcRRAnswerGeneric::clear(void) +{ + if (m_pu8RDData) + { + delete[] m_pu8RDData; + m_pu8RDData = 0; + } + m_u16RDLength = 0; + + return true; +} + + +/** + MDNSResponder::clsHost::stcSendParameter + + A 'collection' of properties and flags for one MDNS query or response. + Mainly managed by the 'Control' functions. + The current offset in the UPD output buffer is tracked to be able to do + a simple host or service domain compression. + +*/ + +/** + MDNSResponder::clsHost::stcSendParameter::stcDomainCacheItem + + A cached host or service domain, incl. the offset in the UDP output buffer. + +*/ + +/* + MDNSResponder::clsHost::stcSendParameter::stcDomainCacheItem::stcDomainCacheItem constructor +*/ +MDNSResponder::clsHost::stcSendParameter::stcDomainCacheItem::stcDomainCacheItem(const void* p_pHostNameOrService, + bool p_bAdditionalData, + uint32_t p_u16Offset) + : m_pNext(0), + m_pHostNameOrService(p_pHostNameOrService), + m_bAdditionalData(p_bAdditionalData), + m_u16Offset(p_u16Offset) +{ +} + +/** + MDNSResponder::clsHost::stcSendParameter +*/ + +/* + MDNSResponder::clsHost::stcSendParameter::stcSendParameter constructor +*/ +MDNSResponder::clsHost::stcSendParameter::stcSendParameter(void) + : m_pQuestions(0), + m_Response(enuResponseType::None), + m_pDomainCacheItems(0) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcSendParameter::~stcSendParameter destructor +*/ +MDNSResponder::clsHost::stcSendParameter::~stcSendParameter(void) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcSendParameter::clear +*/ +bool MDNSResponder::clsHost::stcSendParameter::clear(void) +{ + m_u16ID = 0; + flushQuestions(); + m_u32HostReplyMask = 0; + + m_bLegacyQuery = false; + m_Response = enuResponseType::None; + m_bAuthorative = false; + m_bCacheFlush = true; + m_bUnicast = false; + m_bUnannounce = false; + + m_u16Offset = 0; + flushDomainCache(); + return true; +} + +/* + MDNSResponder::clsHost::stcSendParameter::flushQuestions +*/ +bool MDNSResponder::clsHost::stcSendParameter::flushQuestions(void) +{ + while (m_pQuestions) + { + stcRRQuestion* pNext = m_pQuestions->m_pNext; + delete m_pQuestions; + m_pQuestions = pNext; + } + return true; +} + +/* + MDNSResponder::clsHost::stcSendParameter::flushDomainCache +*/ +bool MDNSResponder::clsHost::stcSendParameter::flushDomainCache(void) +{ + while (m_pDomainCacheItems) + { + stcDomainCacheItem* pNext = m_pDomainCacheItems->m_pNext; + delete m_pDomainCacheItems; + m_pDomainCacheItems = pNext; + } + return true; +} + +/* + MDNSResponder::clsHost::stcSendParameter::flushTempContent +*/ +bool MDNSResponder::clsHost::stcSendParameter::flushTempContent(void) +{ + m_u16Offset = 0; + flushDomainCache(); + return true; +} + +/* + MDNSResponder::clsHost::stcSendParameter::shiftOffset +*/ +bool MDNSResponder::clsHost::stcSendParameter::shiftOffset(uint16_t p_u16Shift) +{ + m_u16Offset += p_u16Shift; + return true; +} + +/* + MDNSResponder::clsHost::stcSendParameter::addDomainCacheItem +*/ +bool MDNSResponder::clsHost::stcSendParameter::addDomainCacheItem(const void* p_pHostNameOrService, + bool p_bAdditionalData, + uint16_t p_u16Offset) +{ + bool bResult = false; + + stcDomainCacheItem* pNewItem = 0; + if ((p_pHostNameOrService) && + (p_u16Offset) && + ((pNewItem = new stcDomainCacheItem(p_pHostNameOrService, p_bAdditionalData, p_u16Offset)))) + { + + pNewItem->m_pNext = m_pDomainCacheItems; + bResult = ((m_pDomainCacheItems = pNewItem)); + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcSendParameter::findCachedDomainOffset +*/ +uint16_t MDNSResponder::clsHost::stcSendParameter::findCachedDomainOffset(const void* p_pHostNameOrService, + bool p_bAdditionalData) const +{ + const stcDomainCacheItem* pCacheItem = m_pDomainCacheItems; + + for (; pCacheItem; pCacheItem = pCacheItem->m_pNext) + { + if ((pCacheItem->m_pHostNameOrService == p_pHostNameOrService) && + (pCacheItem->m_bAdditionalData == p_bAdditionalData)) // Found cache item + { + break; + } + } + return (pCacheItem ? pCacheItem->m_u16Offset : 0); +} + + +/** + MDNSResponder::clsHost::stcQuery + + A MDNS service query object. + Service queries may be static or dynamic. + As the static service query is processed in the blocking function 'queryService', + only one static service service may exist. The processing of the answers is done + on the WiFi-stack side of the ESP stack structure (via 'UDPContext.onRx(_update)'). + +*/ + +/** + MDNSResponder::clsHost::stcQuery::stcAnswer + + One answer for a service query. + Every answer must contain + - a service instance entry (pivot), + and may contain + - a host domain, + - a port + - an IPv4 address + (- an IPv6 address) + - a MDNS TXTs + The existance of a component is flaged in 'm_u32ContentFlags'. + For every answer component a TTL value is maintained. + Answer objects can be connected to a linked list. + + For the host domain, service domain and TXTs components, a char array + representation can be retrieved (which is created on demand). + +*/ + +/** + MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL + + The TTL (Time-To-Live) for an specific answer content. + The 80% and outdated states are calculated based on the current time (millis) + and the 'set' time (also millis). + If the answer is scheduled for an update, the corresponding flag should be set. + +*/ + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::stcTTL constructor +*/ +MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::stcTTL(void) + : m_u32TTL(0), + m_TTLTimeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()), + m_TimeoutLevel(static_cast<typeTimeoutLevel>(enuTimeoutLevel::None)) +{ +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::set +*/ +bool MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::set(uint32_t p_u32TTL) +{ + m_u32TTL = p_u32TTL; + if (m_u32TTL) + { + m_TimeoutLevel = static_cast<typeTimeoutLevel>(enuTimeoutLevel::Base); // Set to 80% + m_TTLTimeout.reset(timeout()); + } + else + { + m_TimeoutLevel = static_cast<typeTimeoutLevel>(enuTimeoutLevel::None); // undef + m_TTLTimeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + } + return true; +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::flagged +*/ +bool MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::flagged(void) const +{ + return ((m_u32TTL) && + (static_cast<typeTimeoutLevel>(enuTimeoutLevel::None) != m_TimeoutLevel) && + (((esp8266::polledTimeout::timeoutTemplate<false>*)&m_TTLTimeout)->expired())); // Cast-away the const; in case of oneShot-timer OK (but ugly...) +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::restart +*/ +bool MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::restart(void) +{ + bool bResult = true; + + if ((static_cast<typeTimeoutLevel>(enuTimeoutLevel::Base) <= m_TimeoutLevel) && // >= 80% AND + (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final) > m_TimeoutLevel)) // < 100% + { + + m_TimeoutLevel += static_cast<typeTimeoutLevel>(enuTimeoutLevel::Interval); // increment by 5% + m_TTLTimeout.reset(timeout()); + } + else + { + bResult = false; + m_TTLTimeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + m_TimeoutLevel = static_cast<typeTimeoutLevel>(enuTimeoutLevel::None); + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::prepareDeletion +*/ +bool MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::prepareDeletion(void) +{ + m_TimeoutLevel = static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final); + m_TTLTimeout.reset(1 * 1000); // See RFC 6762, 10.1 + + return true; +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::finalTimeoutLevel +*/ +bool MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::finalTimeoutLevel(void) const +{ + return (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final) == m_TimeoutLevel); +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::timeout +*/ +unsigned long MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::timeout(void) const +{ + uint32_t u32Timeout = std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max(); + + if (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Base) == m_TimeoutLevel) // 80% + { + u32Timeout = (m_u32TTL * 800); // to milliseconds + } + else if ((static_cast<typeTimeoutLevel>(enuTimeoutLevel::Base) < m_TimeoutLevel) && // >80% AND + (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final) >= m_TimeoutLevel)) // <= 100% + { + + u32Timeout = (m_u32TTL * 50); + } // else: invalid + return u32Timeout; +} + + +/** + MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress + +*/ + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress::stcIPAddress constructor +*/ +MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress::stcIPAddress(IPAddress p_IPAddress, + uint32_t p_u32TTL /*= 0*/) + : m_pNext(0), + m_IPAddress(p_IPAddress) +{ + m_TTL.set(p_u32TTL); +} + + +/** + MDNSResponder::clsHost::stcQuery::stcAnswer +*/ + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::stcAnswer constructor +*/ +MDNSResponder::clsHost::stcQuery::stcAnswer::stcAnswer(void) + : m_pNext(0), + m_u16Port(0), +#ifdef MDNS_IPV4_SUPPORT + m_pIPv4Addresses(0), +#endif +#ifdef MDNS_IPV6_SUPPORT + m_pIPv6Addresses(0), +#endif + m_QueryAnswerFlags(0) +{ +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::~stcAnswer destructor +*/ +MDNSResponder::clsHost::stcQuery::stcAnswer::~stcAnswer(void) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::clear +*/ +bool MDNSResponder::clsHost::stcQuery::stcAnswer::clear(void) +{ + return ( +#ifdef MDNS_IPV4_SUPPORT + (releaseIPv4Addresses()) && +#endif +#ifdef MDNS_IPV6_SUPPORT + (releaseIPv6Addresses()) +#endif + ); +} + +#ifdef MDNS_IPV4_SUPPORT +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::releaseIPv4Addresses +*/ +bool MDNSResponder::clsHost::stcQuery::stcAnswer::releaseIPv4Addresses(void) +{ + while (m_pIPv4Addresses) + { + stcIPAddress* pNext = m_pIPv4Addresses->m_pNext; + delete m_pIPv4Addresses; + m_pIPv4Addresses = pNext; + } + return true; +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::addIPv4Address +*/ +bool MDNSResponder::clsHost::stcQuery::stcAnswer::addIPv4Address(MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* p_pIPv4Address) +{ + bool bResult = false; + + if (p_pIPv4Address) + { + p_pIPv4Address->m_pNext = m_pIPv4Addresses; + m_pIPv4Addresses = p_pIPv4Address; + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::removeIPv4Address +*/ +bool MDNSResponder::clsHost::stcQuery::stcAnswer::removeIPv4Address(MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* p_pIPv4Address) +{ + bool bResult = false; + + if (p_pIPv4Address) + { + stcIPAddress* pPred = m_pIPv4Addresses; + while ((pPred) && + (pPred->m_pNext != p_pIPv4Address)) + { + pPred = pPred->m_pNext; + } + if (pPred) + { + pPred->m_pNext = p_pIPv4Address->m_pNext; + delete p_pIPv4Address; + bResult = true; + } + else if (m_pIPv4Addresses == p_pIPv4Address) // No predecesor, but first item + { + m_pIPv4Addresses = p_pIPv4Address->m_pNext; + delete p_pIPv4Address; + bResult = true; + } + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv4Address (const) +*/ +const MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv4Address(const IPAddress& p_IPAddress) const +{ + return (stcIPAddress*)(((const stcAnswer*)this)->findIPv4Address(p_IPAddress)); +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv4Address +*/ +MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv4Address(const IPAddress& p_IPAddress) +{ + stcIPAddress* pIPv4Address = m_pIPv4Addresses; + while (pIPv4Address) + { + if (pIPv4Address->m_IPAddress == p_IPAddress) + { + break; + } + pIPv4Address = pIPv4Address->m_pNext; + } + return pIPv4Address; +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::IPv4AddressCount +*/ +uint32_t MDNSResponder::clsHost::stcQuery::stcAnswer::IPv4AddressCount(void) const +{ + uint32_t u32Count = 0; + + stcIPAddress* pIPv4Address = m_pIPv4Addresses; + while (pIPv4Address) + { + ++u32Count; + pIPv4Address = pIPv4Address->m_pNext; + } + return u32Count; +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::IPv4AddressAtIndex +*/ +MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::IPv4AddressAtIndex(uint32_t p_u32Index) +{ + return (stcIPAddress*)(((const stcAnswer*)this)->IPv4AddressAtIndex(p_u32Index)); +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::IPv4AddressAtIndex (const) +*/ +const MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::IPv4AddressAtIndex(uint32_t p_u32Index) const +{ + const stcIPAddress* pIPv4Address = 0; + + if (((uint32_t)(-1) != p_u32Index) && + (m_pIPv4Addresses)) + { + + uint32_t u32Index; + for (pIPv4Address = m_pIPv4Addresses, u32Index = 0; ((pIPv4Address) && (u32Index < p_u32Index)); pIPv4Address = pIPv4Address->m_pNext, ++u32Index); + } + return pIPv4Address; +} +#endif + +#ifdef MDNS_IPV6_SUPPORT +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::releaseIPv6Addresses +*/ +bool MDNSResponder::clsHost::stcQuery::stcAnswer::releaseIPv6Addresses(void) +{ + while (m_pIPv6Addresses) + { + stcIPAddress* pNext = m_pIPv6Addresses->m_pNext; + delete m_pIPv6Addresses; + m_pIPv6Addresses = pNext; + } + return true; +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::addIPv6Address +*/ +bool MDNSResponder::clsHost::stcQuery::stcAnswer::addIPv6Address(MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* p_pIPv6Address) +{ + bool bResult = false; + + if (p_pIPv6Address) + { + p_pIPv6Address->m_pNext = m_pIPv6Addresses; + m_pIPv6Addresses = p_pIPv6Address; + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::removeIPv6Address +*/ +bool MDNSResponder::clsHost::stcQuery::stcAnswer::removeIPv6Address(MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* p_pIPv6Address) +{ + bool bResult = false; + + if (p_pIPv6Address) + { + stcIPAddress* pPred = m_pIPv6Addresses; + while ((pPred) && + (pPred->m_pNext != p_pIPv6Address)) + { + pPred = pPred->m_pNext; + } + if (pPred) + { + pPred->m_pNext = p_pIPv6Address->m_pNext; + delete p_pIPv6Address; + bResult = true; + } + else if (m_pIPv6Addresses == p_pIPv6Address) // No predecesor, but first item + { + m_pIPv6Addresses = p_pIPv6Address->m_pNext; + delete p_pIPv6Address; + bResult = true; + } + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv6Address +*/ +MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv6Address(const IPAddress& p_IPAddress) +{ + return (stcIPAddress*)(((const stcAnswer*)this)->findIPv6Address(p_IPAddress)); +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv6Address (const) +*/ +const MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv6Address(const IPAddress& p_IPAddress) const +{ + const stcIPAddress* pIPv6Address = m_pIPv6Addresses; + while (pIPv6Address) + { + if (pIPv6Address->m_IPAddress == p_IPAddress) + { + break; + } + pIPv6Address = pIPv6Address->m_pNext; + } + return pIPv6Address; +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::IPv6AddressCount +*/ +uint32_t MDNSResponder::clsHost::stcQuery::stcAnswer::IPv6AddressCount(void) const +{ + uint32_t u32Count = 0; + + stcIPAddress* pIPv6Address = m_pIPv6Addresses; + while (pIPv6Address) + { + ++u32Count; + pIPv6Address = pIPv6Address->m_pNext; + } + return u32Count; +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::IPv6AddressAtIndex (const) +*/ +const MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::IPv6AddressAtIndex(uint32_t p_u32Index) const +{ + return (stcIPAddress*)(((const stcAnswer*)this)->IPv6AddressAtIndex(p_u32Index)); +} + +/* + MDNSResponder::clsHost::stcQuery::stcAnswer::IPv6AddressAtIndex +*/ +MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::IPv6AddressAtIndex(uint32_t p_u32Index) +{ + stcIPAddress* pIPv6Address = 0; + + if (((uint32_t)(-1) != p_u32Index) && + (m_pIPv6Addresses)) + { + + uint32_t u32Index; + for (pIPv6Address = m_pIPv6Addresses, u32Index = 0; ((pIPv6Address) && (u32Index < p_u32Index)); pIPv6Address = pIPv6Address->m_pNext, ++u32Index); + } + return pIPv6Address; +} +#endif + + +/** + MDNSResponder::clsHost::stcQuery + + A service query object. + A static query is flaged via 'm_bLegacyQuery'; while the function 'queryService' + is waiting for answers, the internal flag 'm_bAwaitingAnswers' is set. When the + timeout is reached, the flag is removed. These two flags are only used for static + service queries. + All answers to the service query are stored in 'm_pAnswers' list. + Individual answers may be addressed by index (in the list of answers). + Every time a answer component is added (or changes) in a dynamic service query, + the callback 'm_fnCallback' is called. + The answer list may be searched by service and host domain. + + Service query object may be connected to a linked list. +*/ + +/* + MDNSResponder::clsHost::stcQuery::stcQuery constructor +*/ +MDNSResponder::clsHost::stcQuery::stcQuery(const enuQueryType p_QueryType) + : m_pNext(0), + m_QueryType(p_QueryType), + m_fnCallback(0), + m_bLegacyQuery(false), + m_u8SentCount(0), + m_ResendTimeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()), + m_bAwaitingAnswers(true), + m_pAnswers(0) +{ + clear(); + m_QueryType = p_QueryType; +} + +/* + MDNSResponder::clsHost::stcQuery::~stcQuery destructor +*/ +MDNSResponder::clsHost::stcQuery::~stcQuery(void) +{ + clear(); +} + +/* + MDNSResponder::clsHost::stcQuery::clear +*/ +bool MDNSResponder::clsHost::stcQuery::clear(void) +{ + m_pNext = 0; + m_QueryType = enuQueryType::None; + m_fnCallback = 0; + m_bLegacyQuery = false; + m_u8SentCount = 0; + m_ResendTimeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + m_bAwaitingAnswers = true; + while (m_pAnswers) + { + stcAnswer* pNext = m_pAnswers->m_pNext; + delete m_pAnswers; + m_pAnswers = pNext; + } + return true; +} + +/* + MDNSResponder::clsHost::stcQuery::answerCount +*/ +uint32_t MDNSResponder::clsHost::stcQuery::answerCount(void) const +{ + uint32_t u32Count = 0; + + stcAnswer* pAnswer = m_pAnswers; + while (pAnswer) + { + ++u32Count; + pAnswer = pAnswer->m_pNext; + } + return u32Count; +} + +/* + MDNSResponder::clsHost::stcQuery::answerAtIndex +*/ +const MDNSResponder::clsHost::stcQuery::stcAnswer* MDNSResponder::clsHost::stcQuery::answerAtIndex(uint32_t p_u32Index) const +{ + const stcAnswer* pAnswer = 0; + + if (((uint32_t)(-1) != p_u32Index) && + (m_pAnswers)) + { + + uint32_t u32Index; + for (pAnswer = m_pAnswers, u32Index = 0; ((pAnswer) && (u32Index < p_u32Index)); pAnswer = pAnswer->m_pNext, ++u32Index); + } + return pAnswer; +} + +/* + MDNSResponder::clsHost::stcQuery::answerAtIndex +*/ +MDNSResponder::clsHost::stcQuery::stcAnswer* MDNSResponder::clsHost::stcQuery::answerAtIndex(uint32_t p_u32Index) +{ + return (stcAnswer*)(((const stcQuery*)this)->answerAtIndex(p_u32Index)); +} + +/* + MDNSResponder::clsHost::stcQuery::indexOfAnswer +*/ +uint32_t MDNSResponder::clsHost::stcQuery::indexOfAnswer(const MDNSResponder::clsHost::stcQuery::stcAnswer* p_pAnswer) const +{ + uint32_t u32Index = 0; + + for (const stcAnswer* pAnswer = m_pAnswers; pAnswer; pAnswer = pAnswer->m_pNext, ++u32Index) + { + if (pAnswer == p_pAnswer) + { + return u32Index; + } + } + return ((uint32_t)(-1)); +} + +/* + MDNSResponder::clsHost::stcQuery::addAnswer +*/ +bool MDNSResponder::clsHost::stcQuery::addAnswer(MDNSResponder::clsHost::stcQuery::stcAnswer* p_pAnswer) +{ + bool bResult = false; + + if (p_pAnswer) + { + p_pAnswer->m_pNext = m_pAnswers; + m_pAnswers = p_pAnswer; + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcQuery::removeAnswer +*/ +bool MDNSResponder::clsHost::stcQuery::removeAnswer(MDNSResponder::clsHost::stcQuery::stcAnswer* p_pAnswer) +{ + bool bResult = false; + + if (p_pAnswer) + { + stcAnswer* pPred = m_pAnswers; + while ((pPred) && + (pPred->m_pNext != p_pAnswer)) + { + pPred = pPred->m_pNext; + } + if (pPred) + { + pPred->m_pNext = p_pAnswer->m_pNext; + delete p_pAnswer; + bResult = true; + } + else if (m_pAnswers == p_pAnswer) // No predecesor, but first item + { + m_pAnswers = p_pAnswer->m_pNext; + delete p_pAnswer; + bResult = true; + } + } + return bResult; +} + +/* + MDNSResponder::clsHost::stcQuery::findAnswerForServiceDomain +*/ +MDNSResponder::clsHost::stcQuery::stcAnswer* MDNSResponder::clsHost::stcQuery::findAnswerForServiceDomain(const MDNSResponder::clsHost::stcRRDomain& p_ServiceDomain) +{ + stcAnswer* pAnswer = m_pAnswers; + while (pAnswer) + { + if (pAnswer->m_ServiceDomain == p_ServiceDomain) + { + break; + } + pAnswer = pAnswer->m_pNext; + } + return pAnswer; +} + +/* + MDNSResponder::clsHost::stcQuery::findAnswerForHostDomain +*/ +MDNSResponder::clsHost::stcQuery::stcAnswer* MDNSResponder::clsHost::stcQuery::findAnswerForHostDomain(const MDNSResponder::clsHost::stcRRDomain& p_HostDomain) +{ + stcAnswer* pAnswer = m_pAnswers; + while (pAnswer) + { + if (pAnswer->m_HostDomain == p_HostDomain) + { + break; + } + pAnswer = pAnswer->m_pNext; + } + return pAnswer; +} + + +} // namespace MDNSImplementation + +} // namespace esp8266 + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Transfer.cpp new file mode 100755 index 0000000000..5da81255ab --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Transfer.cpp @@ -0,0 +1,2390 @@ +/* + LEAmDNS2_Host_Transfer.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +extern "C" { +#include "user_interface.h" +} + +#include "lwip/netif.h" + +#include "LEAmDNS2_lwIPdefs.h" +#include "LEAmDNS2_Priv.h" + + +namespace esp8266 +{ + +/* + LEAmDNS +*/ +namespace experimental +{ + +/** + CONST STRINGS +*/ +static const char* scpcLocal = "local"; +static const char* scpcServices = "services"; +static const char* scpcDNSSD = "dns-sd"; +static const char* scpcUDP = "udp"; +//static const char* scpcTCP = "tcp"; + +#ifdef MDNS_IPV4_SUPPORT +static const char* scpcReverseIPv4Domain = "in-addr"; +#endif +#ifdef MDNS_IPV6_SUPPORT +static const char* scpcReverseIPv6Domain = "ip6"; +#endif +static const char* scpcReverseTopDomain = "arpa"; + +/** + TRANSFER +*/ + + +/** + SENDING +*/ + +/* + MDNSResponder::_sendMDNSMessage + + Unicast responses are prepared and sent directly to the querier. + Multicast responses or queries are transferred to _sendMDNSMessage_Multicast + + Any reply flags in installed services are removed at the end! + +*/ +bool MDNSResponder::clsHost::_sendMDNSMessage(MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + bool bResult = false; + + uint8_t u8AvailableProtocols = 0; +#ifdef MDNS_IPV4_SUPPORT + // Only send out IPv4 messages, if we've got an IPv4 address + if (_getResponderIPAddress(enuIPProtocolType::V4).isSet()) + { + u8AvailableProtocols |= static_cast<uint8_t>(enuIPProtocolType::V4); + } + DEBUG_EX_INFO(else + { + DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage: No IPv4 address available!\n"), _DH()); + }); +#endif +#ifdef MDNS_IPV6_SUPPORT + // Only send out IPv6 messages, if we've got an IPv6 address + if (_getResponderIPAddress(enuIPProtocolType::V6).isSet()) + { + u8AvailableProtocols |= static_cast<uint8_t>(enuIPProtocolType::V6); + } + DEBUG_EX_INFO(else + { + DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage: No IPv6 address available!\n"), _DH()); + }); +#endif + + if (stcSendParameter::enuResponseType::None != p_rSendParameter.m_Response) + { + IPAddress ipRemote = ((stcSendParameter::enuResponseType::Response == p_rSendParameter.m_Response) + ? m_rUDPContext.getRemoteAddress() + : IPAddress()); + + if (p_rSendParameter.m_bUnicast) // Unicast response -> Send to querier + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage: Will send unicast to '%s'.\n"), _DH(), ipRemote.toString().c_str());); + DEBUG_EX_ERR(if (!ipRemote.isSet()) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage: MISSING remote address for unicast response!\n"), _DH());); + + bResult = ((ipRemote.isSet()) && + (_prepareMDNSMessage(p_rSendParameter)) && + (m_rUDPContext.send(ipRemote, m_rUDPContext.getRemotePort()))); + } + else // Multicast response -> Send via the same network interface, that received the query + { +#ifdef MDNS_IPV4_SUPPORT + if (((!ipRemote.isSet()) || // NO remote IP + (ipRemote.isV4())) && // OR IPv4 + (u8AvailableProtocols & static_cast<uint8_t>(enuIPProtocolType::V4))) // AND IPv4 protocol available + { + + bResult = _sendMDNSMessage_Multicast(p_rSendParameter, static_cast<uint8_t>(enuIPProtocolType::V4)); + } +#endif +#ifdef MDNS_IPV6_SUPPORT + if (((!ipRemote.isSet()) || // NO remote IP + (ipRemote.isV6())) && // OR IPv6 + (u8AvailableProtocols & static_cast<uint8_t>(enuIPProtocolType::V6))) // AND IPv6 protocol available + { + + bResult = _sendMDNSMessage_Multicast(p_rSendParameter, static_cast<uint8_t>(enuIPProtocolType::V6)); + } +#endif + } + } + else // Multicast query -> Send by all available protocols + { + bResult = ((u8AvailableProtocols) && + (_sendMDNSMessage_Multicast(p_rSendParameter, u8AvailableProtocols))); + } + + // Finally clear service reply masks + for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) + { + pService->m_u32ReplyMask = 0; + } + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage: FAILED!\n"), _DH());); + return bResult; +} + +#include "cont.h" +/* + MDNSResponder::_sendMDNSMessage_Multicast + + Fills the UDP output buffer (via _prepareMDNSMessage) and sends the buffer + via the selected WiFi protocols +*/ +bool MDNSResponder::clsHost::_sendMDNSMessage_Multicast(MDNSResponder::clsHost::stcSendParameter& p_rSendParameter, + uint8_t p_IPProtocolTypes) +{ + bool bIPv4Result = true; + bool bIPv6Result = true; + +#ifdef MDNS_IPV4_SUPPORT + if (p_IPProtocolTypes & static_cast<uint8_t>(enuIPProtocolType::V4)) + { + IPAddress ip4MulticastAddress(DNS_MQUERY_IPV4_GROUP_INIT); + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast v4: Will send to '%s'.\n"), _DH(), ip4MulticastAddress.toString().c_str());); + DEBUG_EX_INFO(if (!_getResponderIPAddress(enuIPProtocolType::V4)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast v4: NO IPv4 address!.\n"), _DH());); + bIPv4Result = ((_prepareMDNSMessage(p_rSendParameter)) && + (m_rUDPContext.setMulticastInterface(&m_rNetIf), true) && + (m_rUDPContext.send(ip4MulticastAddress, DNS_MQUERY_PORT)) && + (m_rUDPContext.setMulticastInterface(0), true)); + DEBUG_EX_ERR(if (!bIPv4Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast (V4): FAILED!\n"), _DH());); + } +#endif + +#ifdef MDNS_IPV6_SUPPORT + if (p_IPProtocolTypes & static_cast<uint8_t>(enuIPProtocolType::V6)) + { + IPAddress ip6MulticastAddress(DNS_MQUERY_IPV6_GROUP_INIT); + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast v6: Will send to '%s'.\n"), _DH(), ip6MulticastAddress.toString().c_str());); + DEBUG_EX_INFO(if (!_getResponderIPAddress(enuIPProtocolType::V6)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast v6: NO IPv6 address!.\n"), _DH());); + DEBUG_EX_ERR( + bool bPrepareMessage = false; + bool bUDPContextSend = false; + ); + bIPv6Result = ((DEBUG_EX_ERR(bPrepareMessage =)_prepareMDNSMessage(p_rSendParameter)) && + (m_rUDPContext.setMulticastInterface(&m_rNetIf), true) && + (DEBUG_EX_ERR(bUDPContextSend =)m_rUDPContext.send(ip6MulticastAddress, DNS_MQUERY_PORT)) && + (m_rUDPContext.setMulticastInterface(0), true)); + DEBUG_EX_ERR(if (!bIPv6Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast (V6): FAILED! (%s, %s, %s)\n"), _DH(), (_getResponderIPAddress(enuIPProtocolType::V6).isSet() ? "1" : "0"), (bPrepareMessage ? "1" : "0"), (bUDPContextSend ? "1" : "0"));); + } +#endif + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast: %s!\n\n"), _DH(), ((bIPv4Result && bIPv6Result) ? "Succeeded" : "FAILED"));); + DEBUG_EX_ERR(if (!(bIPv4Result && bIPv6Result)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast: FAILED!\n"), _DH());); + return (bIPv4Result && bIPv6Result); +} + +/* + MDNSResponder::_prepareMDNSMessage + + The MDNS message is composed in a two-step process. + In the first loop 'only' the header informations (mainly number of answers) are collected, + while in the seconds loop, the header and all queries and answers are written to the UDP + output buffer. + +*/ +bool MDNSResponder::clsHost::_prepareMDNSMessage(MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage\n"));); + bool bResult = true; + + // Prepare output buffer for potential reuse + p_rSendParameter.flushTempContent(); + + // Prepare header; count answers + stcMsgHeader msgHeader(p_rSendParameter.m_u16ID, + (static_cast<stcSendParameter::enuResponseType>(stcSendParameter::enuResponseType::None) != p_rSendParameter.m_Response), + 0, + p_rSendParameter.m_bAuthorative); + // If this is a response, the answers are anwers, + // else this is a query or probe and the answers go into auth section + uint16_t& ru16Answers = ((stcSendParameter::enuResponseType::None != p_rSendParameter.m_Response) + ? msgHeader.m_u16ANCount // Usual answers + : msgHeader.m_u16NSCount); // Authorative answers + + /** + enuSequence + */ + using typeSequence = uint8_t; + enum class enuSequence : typeSequence + { + Count = 0, + Send = 1 + }; + + // Two step sequence: 'Count' and 'Send' + for (typeSequence sequence = static_cast<typeSequence>(enuSequence::Count); ((bResult) && (sequence <= static_cast<typeSequence>(enuSequence::Send))); ++sequence) + { + DEBUG_EX_INFO( + if (static_cast<typeSequence>(enuSequence::Send) == sequence) + DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), + _DH(), + (unsigned)msgHeader.m_u16ID, + (unsigned)msgHeader.m_1bQR, (unsigned)msgHeader.m_4bOpcode, (unsigned)msgHeader.m_1bAA, (unsigned)msgHeader.m_1bTC, (unsigned)msgHeader.m_1bRD, + (unsigned)msgHeader.m_1bRA, (unsigned)msgHeader.m_4bRCode, + (unsigned)msgHeader.m_u16QDCount, + (unsigned)msgHeader.m_u16ANCount, + (unsigned)msgHeader.m_u16NSCount, + (unsigned)msgHeader.m_u16ARCount); + ); + // Count/send + // Header + bResult = ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? true + : _writeMDNSMsgHeader(msgHeader, p_rSendParameter)); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSMsgHeader FAILED!\n"), _DH());); + // Questions + for (stcRRQuestion* pQuestion = p_rSendParameter.m_pQuestions; ((bResult) && (pQuestion)); pQuestion = pQuestion->m_pNext) + { + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++msgHeader.m_u16QDCount + : (bResult = _writeMDNSQuestion(*pQuestion, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSQuestion FAILED!\n"), _DH());); + } + + // Answers and authorative answers + // NSEC host (part 1) + uint32_t u32NSECContent = 0; +#ifdef MDNS_IPV4_SUPPORT + // A + if ((bResult) && + (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::A)) && + (_getResponderIPAddress(enuIPProtocolType::V4).isSet())) + { + + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::A); + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_A(_getResponderIPAddress(enuIPProtocolType::V4), p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_A(A) FAILED!\n"), _DH());); + } + // PTR_IPv4 + if ((bResult) && + (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)) && + (_getResponderIPAddress(enuIPProtocolType::V4).isSet())) + { + + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::PTR_IPv4); + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_PTR_IPv4(_getResponderIPAddress(enuIPProtocolType::V4), p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_PTR_IPv4 FAILED!\n"), _DH());); + } +#endif +#ifdef MDNS_IPV6_SUPPORT + // AAAA + if ((bResult) && + (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::AAAA)) && + (_getResponderIPAddress(enuIPProtocolType::V6).isSet())) + { + + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_AAAA(_getResponderIPAddress(enuIPProtocolType::V6), p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_AAAA(A) FAILED!\n"), _DH());); + } + // PTR_IPv6 + if ((bResult) && + (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv6)) && + (_getResponderIPAddress(enuIPProtocolType::V6).isSet())) + { + + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::PTR_IPv6); + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_PTR_IPv6(_getResponderIPAddress(enuIPProtocolType::V6), p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_PTR_IPv6 FAILED!\n"), _DH());); + } +#endif + + for (stcService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + { + // PTR_TYPE + if ((bResult) && + (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_TYPE))) + { + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_PTR_TYPE(*pService, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_PTR_TYPE FAILED!\n"), _DH());); + } + // PTR_NAME + if ((bResult) && + (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_NAME))) + { + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_PTR_NAME(*pService, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_PTR_NAME FAILED!\n"), _DH());); + } + // SRV + if ((bResult) && + (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::SRV))) + { + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_SRV(*pService, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_SRV(A) FAILED!\n"), _DH());); + } + // TXT + if ((bResult) && + (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::TXT))) + { + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_TXT(*pService, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_TXT(A) FAILED!\n"), _DH());); + } + } // for services + + // Additional answers + uint16_t& ru16AdditionalAnswers = msgHeader.m_u16ARCount; + +#ifdef MDNS_IPV4_SUPPORT + bool bNeedsAdditionalAnswerA = false; +#endif +#ifdef MDNS_IPV6_SUPPORT + bool bNeedsAdditionalAnswerAAAA = false; +#endif + for (stcService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + { + if ((bResult) && + (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_NAME)) && // If PTR_NAME is requested, AND + (!(pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::SRV)))) // NOT SRV -> add SRV as additional answer + { + + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++ru16AdditionalAnswers + : (bResult = _writeMDNSAnswer_SRV(*pService, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_SRV(B) FAILED!\n"), _DH());); + } + /* AppleTV doesn't add TXT + if ((bResult) && + (pService->m_u32ReplyMask & ContentFlag_PTR_NAME) && // If PTR_NAME is requested, AND + (!(pService->m_u32ReplyMask & ContentFlag_TXT))) { // NOT TXT -> add TXT as additional answer + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++ru16AdditionalAnswers + : (bResult = _writeMDNSAnswer_TXT(*pService, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_TXT(B) FAILED!\n"));); + } + */ + if ((pService->m_u32ReplyMask & (static_cast<uint32_t>(enuContentFlag::PTR_NAME) | static_cast<uint32_t>(enuContentFlag::SRV))) || // If service instance name or SRV OR + (p_rSendParameter.m_u32HostReplyMask & (static_cast<uint32_t>(enuContentFlag::A) | static_cast<uint32_t>(enuContentFlag::AAAA)))) // any host IP address is requested + { +#ifdef MDNS_IPV4_SUPPORT + if ((bResult) && + (!(p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::A)))) // Add IPv4 address + { + bNeedsAdditionalAnswerA = true; + } +#endif +#ifdef MDNS_IPV6_SUPPORT + if ((bResult) && + (!(p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::AAAA)))) // Add IPv6 address + { + bNeedsAdditionalAnswerAAAA = true; + } +#endif + } + // NSEC record for service + if ((bResult) && + (pService->m_u32ReplyMask) && + ((stcSendParameter::enuResponseType::None != p_rSendParameter.m_Response))) + { + + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++ru16AdditionalAnswers + : (bResult = _writeMDNSAnswer_NSEC(*pService, (static_cast<uint32_t>(enuContentFlag::TXT) | static_cast<uint32_t>(enuContentFlag::SRV)), p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_NSEC(Service) FAILED!\n"), _DH());); + } + } // for services + +#ifdef MDNS_IPV4_SUPPORT + // Answer A needed? + if ((bResult) && + (bNeedsAdditionalAnswerA) && + (_getResponderIPAddress(enuIPProtocolType::V4).isSet())) + { + // Additional A + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::A); + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++ru16AdditionalAnswers + : (bResult = _writeMDNSAnswer_A(_getResponderIPAddress(enuIPProtocolType::V4), p_rSendParameter))); + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_A(B) FAILED!\n"), _DH());); + } +#endif +#ifdef MDNS_IPV6_SUPPORT + // Answer AAAA needed? + if ((bResult) && + (bNeedsAdditionalAnswerAAAA) && + (_getResponderIPAddress(enuIPProtocolType::V6).isSet())) + { + // Additional AAAA + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? ++ru16AdditionalAnswers + : (bResult = _writeMDNSAnswer_AAAA(_getResponderIPAddress(enuIPProtocolType::V6), p_rSendParameter))); + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_AAAA(B) FAILED!\n"), _DH());); + } +#endif + + // NSEC host (part 2) + if ((bResult) && + ((stcSendParameter::enuResponseType::None != p_rSendParameter.m_Response)) && + (u32NSECContent)) + { + + // NSEC PTR IPv4/IPv6 are separate answers; make sure, that this is counted for +#ifdef MDNS_IPV4_SUPPORT + uint32_t u32NSECContent_PTR_IPv4 = (u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)); + u32NSECContent &= ~static_cast<uint32_t>(enuContentFlag::PTR_IPv4); +#endif +#ifdef MDNS_IPV6_SUPPORT + uint32_t u32NSECContent_PTR_IPv6 = (u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv6)); + u32NSECContent &= ~static_cast<uint32_t>(enuContentFlag::PTR_IPv6); +#endif + + ((static_cast<typeSequence>(enuSequence::Count) == sequence) + ? (ru16AdditionalAnswers += ((u32NSECContent ? 1 : 0) +#ifdef MDNS_IPV4_SUPPORT + + (u32NSECContent_PTR_IPv4 ? 1 : 0) +#endif +#ifdef MDNS_IPV6_SUPPORT + + (u32NSECContent_PTR_IPv6 ? 1 : 0) +#endif + )) + : (bResult = (((!u32NSECContent) || + // Write host domain NSEC answer + (_writeMDNSAnswer_NSEC(u32NSECContent, p_rSendParameter))) +#ifdef MDNS_IPV4_SUPPORT + // Write separate answer for host PTR IPv4 + && ((!u32NSECContent_PTR_IPv4) || + ((!_getResponderIPAddress(enuIPProtocolType::V4).isSet()) || + (_writeMDNSAnswer_NSEC_PTR_IPv4(_getResponderIPAddress(enuIPProtocolType::V4), p_rSendParameter)))) +#endif +#ifdef MDNS_IPV6_SUPPORT + // Write separate answer for host PTR IPv6 + && ((!u32NSECContent_PTR_IPv6) || + ((!_getResponderIPAddress(enuIPProtocolType::V6).isSet()) || + (_writeMDNSAnswer_NSEC_PTR_IPv6(_getResponderIPAddress(enuIPProtocolType::V6), p_rSendParameter)))) +#endif + ))); + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_NSEC(Host) FAILED!\n"), _DH());); + } + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: Loop %i FAILED!\n"), _DH(), sequence);); + } // for sequence + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_addMDNSQueryRecord + + Adds a query for the given domain and query type. + +*/ +bool MDNSResponder::clsHost::_addMDNSQueryRecord(MDNSResponder::clsHost::stcSendParameter& p_rSendParameter, + const MDNSResponder::clsHost::stcRRDomain& p_QueryDomain, + uint16_t p_u16RecordType) +{ + bool bResult = false; + + stcRRQuestion* pQuestion = new stcRRQuestion; + if ((bResult = (0 != pQuestion))) + { + // Link to list of questions + pQuestion->m_pNext = p_rSendParameter.m_pQuestions; + p_rSendParameter.m_pQuestions = pQuestion; + + pQuestion->m_Header.m_Domain = p_QueryDomain; + + pQuestion->m_Header.m_Attributes.m_u16Type = p_u16RecordType; + // It seems, that some mDNS implementations don't support 'unicast response' questions... + pQuestion->m_Header.m_Attributes.m_u16Class = (/*0x8000 |*/ DNS_RRCLASS_IN); // /*Unicast &*/ INternet + } + return bResult; +} + +/* + MDNSResponder::_sendMDNSQuery + + Creates and sends a query for the given domain and query type. + +*/ +bool MDNSResponder::clsHost::_sendMDNSQuery(const MDNSResponder::clsHost::stcQuery& p_Query, + MDNSResponder::clsHost::stcQuery::stcAnswer* p_pKnownAnswers /*= 0*/) +{ + bool bResult = false; + + stcSendParameter sendParameter; + switch (p_Query.m_QueryType) + { + case stcQuery::enuQueryType::Host: +#ifdef MDNS_IPV4_SUPPORT + bResult = _addMDNSQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_A); +#endif +#ifdef MDNS_IPV6_SUPPORT + bResult = _addMDNSQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_AAAA); +#endif + break; + + case stcQuery::enuQueryType::Service: + bResult = _addMDNSQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_PTR); + break; + + case stcQuery::enuQueryType::None: + default: + break; + } + + // TODO: Add known answers to query + (void)p_pKnownAnswers; + + bResult = ((bResult) && + (_sendMDNSMessage(sendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSQuery: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_sendMDNSQuery + + Creates and sends a query for the given domain and record type. + +*/ +bool MDNSResponder::clsHost::_sendMDNSQuery(const MDNSResponder::clsHost::stcRRDomain& p_QueryDomain, + uint16_t p_u16RecordType, + MDNSResponder::clsHost::stcQuery::stcAnswer* p_pKnownAnswers /*= 0*/) +{ + bool bResult = false; + + stcSendParameter sendParameter; + bResult = ((_addMDNSQueryRecord(sendParameter, p_QueryDomain, p_u16RecordType)) && + (_sendMDNSMessage(sendParameter))); + + // TODO: Add known answer records + (void) p_pKnownAnswers; + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSQuery: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_getResponderIPAddress +*/ +IPAddress MDNSResponder::clsHost::_getResponderIPAddress(enuIPProtocolType p_IPProtocolType) const +{ + IPAddress ipResponder; +#ifdef MDNS_IPV4_SUPPORT + if (enuIPProtocolType::V4 == p_IPProtocolType) + { + ipResponder = netif_ip_addr4(&m_rNetIf); + } +#endif +#ifdef MDNS_IPV6_SUPPORT + if (enuIPProtocolType::V6 == p_IPProtocolType) + { + bool bCheckLinkLocal = true; + for (int i = 0; ((!ipResponder.isSet()) && (i < 2)); ++i) // Two loops: First with link-local check, second without + { + for (int idx = 0; idx < LWIP_IPV6_NUM_ADDRESSES; ++idx) + { + //DEBUG_EX_INFO(if ip6_addr_isvalid(netif_ip6_addr_state(&m_rNetIf, idx)) DEBUG_OUTPUT.printf_P(PSTR("%s _getResponderIPAddress: Checking IPv6 address %s (LL: %s)\n"), _DH(), IPAddress(netif_ip_addr6(&m_rNetIf, idx)).toString().c_str(), (bCheckLinkLocal ? "YES" : "NO"));); + if ((ip6_addr_isvalid(netif_ip6_addr_state(&m_rNetIf, idx))) && + (((!bCheckLinkLocal) || + (ip6_addr_islinklocal(netif_ip6_addr(&m_rNetIf, idx)))))) + { + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _getResponderIPAddress: Selected IPv6 address %s (LL: %s)\n"), _DH(), IPAddress(netif_ip_addr6(&m_rNetIf, idx)).toString().c_str(), (bCheckLinkLocal ? "YES" : "NO"));); + ipResponder = netif_ip_addr6(&m_rNetIf, idx); + break; + } + } + bCheckLinkLocal = false; + } + } +#endif + return ipResponder; +} + + +/** + HELPERS +*/ + +/** + RESOURCE RECORDS +*/ + +/* + MDNSResponder::_readRRQuestion + + Reads a question (eg. MyESP._http._tcp.local ANY IN) from the UPD input buffer. + +*/ +bool MDNSResponder::clsHost::_readRRQuestion(MDNSResponder::clsHost::stcRRQuestion& p_rRRQuestion) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRQuestion\n"));); + + bool bResult = false; + + if ((bResult = _readRRHeader(p_rRRQuestion.m_Header))) + { + // Extract unicast flag from class field + p_rRRQuestion.m_bUnicast = (p_rRRQuestion.m_Header.m_Attributes.m_u16Class & 0x8000); + //p_rRRQuestion.m_Header.m_Attributes.m_u16Class &= (~0x8000); + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _readRRQuestion "), _DH()); + _printRRDomain(p_rRRQuestion.m_Header.m_Domain); + DEBUG_OUTPUT.printf_P(PSTR(" Type:%s Class:%s\n"), _RRType2Name(p_rRRQuestion.m_Header.m_Attributes.m_u16Type), _RRClass2String(p_rRRQuestion.m_Header.m_Attributes.m_u16Class, true)); + ); + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRQuestion: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_readRRAnswer + + Reads an answer (eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local) + from the UDP input buffer. + After reading the domain and type info, the further processing of the answer + is transferred the answer specific reading functions. + Unknown answer types are processed by the generic answer reader (to remove them + from the input buffer). + +*/ +bool MDNSResponder::clsHost::_readRRAnswer(MDNSResponder::clsHost::stcRRAnswer*& p_rpRRAnswer) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer\n"));); + + bool bResult = false; + + stcRRHeader header; + uint32_t u32TTL; + uint16_t u16RDLength; + if ((_readRRHeader(header)) && + (_udpRead32(u32TTL)) && + (_udpRead16(u16RDLength))) + { + + /* DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer: Reading 0x%04X answer (class:0x%04X, TTL:%u, RDLength:%u) for "), header.m_Attributes.m_u16Type, header.m_Attributes.m_u16Class, u32TTL, u16RDLength); + _printRRDomain(header.m_Domain); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + );*/ + + switch (header.m_Attributes.m_u16Type /*& (~0x8000)*/) // Topmost bit might carry 'cache flush' flag + { +#ifdef MDNS_IPV4_SUPPORT + case DNS_RRTYPE_A: + p_rpRRAnswer = new stcRRAnswerA(header, u32TTL); + bResult = _readRRAnswerA(*(stcRRAnswerA*&)p_rpRRAnswer, u16RDLength); + break; +#endif + case DNS_RRTYPE_PTR: + p_rpRRAnswer = new stcRRAnswerPTR(header, u32TTL); + bResult = _readRRAnswerPTR(*(stcRRAnswerPTR*&)p_rpRRAnswer, u16RDLength); + break; + case DNS_RRTYPE_TXT: + p_rpRRAnswer = new stcRRAnswerTXT(header, u32TTL); + bResult = _readRRAnswerTXT(*(stcRRAnswerTXT*&)p_rpRRAnswer, u16RDLength); + break; +#ifdef MDNS_IPV6_SUPPORT + case DNS_RRTYPE_AAAA: + p_rpRRAnswer = new stcRRAnswerAAAA(header, u32TTL); + bResult = _readRRAnswerAAAA(*(stcRRAnswerAAAA*&)p_rpRRAnswer, u16RDLength); + break; +#endif + case DNS_RRTYPE_SRV: + p_rpRRAnswer = new stcRRAnswerSRV(header, u32TTL); + bResult = _readRRAnswerSRV(*(stcRRAnswerSRV*&)p_rpRRAnswer, u16RDLength); + break; + default: + p_rpRRAnswer = new stcRRAnswerGeneric(header, u32TTL); + bResult = _readRRAnswerGeneric(*(stcRRAnswerGeneric*&)p_rpRRAnswer, u16RDLength); + break; + } + DEBUG_EX_INFO( + if ((bResult) && + (p_rpRRAnswer)) + { + DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer: "), _DH()); + _printRRDomain(p_rpRRAnswer->m_Header.m_Domain); + DEBUG_OUTPUT.printf_P(PSTR(" Type:%s Class:0x%04X TTL:%u, RDLength:%u "), + _RRType2Name(p_rpRRAnswer->m_Header.m_Attributes.m_u16Type), + (p_rpRRAnswer->m_Header.m_Attributes.m_u16Class | (p_rpRRAnswer->m_bCacheFlush ? 0x8000 : 0)), + p_rpRRAnswer->m_u32TTL, + u16RDLength); + switch (header.m_Attributes.m_u16Type /*& (~0x8000)*/) // Topmost bit might carry 'cache flush' flag + { +#ifdef MDNS_IPV4_SUPPORT + case DNS_RRTYPE_A: + DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((stcRRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); + break; +#endif + case DNS_RRTYPE_PTR: + DEBUG_OUTPUT.printf_P(PSTR("PTR ")); + _printRRDomain(((stcRRAnswerPTR*&)p_rpRRAnswer)->m_PTRDomain); + break; + case DNS_RRTYPE_TXT: + { + size_t stTxtLength = ((stcRRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_strLength(); + char* pTxts = new char[stTxtLength]; + if (pTxts) + { + ((stcRRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_str(pTxts); + DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts); + delete[] pTxts; + } + break; + } +#ifdef MDNS_IPV6_SUPPORT + case DNS_RRTYPE_AAAA: + DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((stcRRAnswerAAAA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); + break; +#endif + case DNS_RRTYPE_SRV: + DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((stcRRAnswerSRV*&)p_rpRRAnswer)->m_u16Port); + _printRRDomain(((stcRRAnswerSRV*&)p_rpRRAnswer)->m_SRVDomain); + break; + /* case DNS_RRTYPE_NSEC: + DEBUG_OUTPUT.printf_P(PSTR("NSEC ")); + _printRRDomain(((stcRRAnswerNSEC*&)p_rpRRAnswer)->m_NSECDomain); + for (uint32_t u=0; u<(((stcRRAnswerNSEC*&)p_rpRRAnswer)->m_pNSECBitmap->m_u16BitmapLength * 8); ++u) { + uint8_t byte = ((stcRRAnswerNSEC*&)p_rpRRAnswer)->m_pNSECBitmap->m_pu8BitmapData[u / 8]; + uint8_t flag = 1 << (7 - (u % 8)); // (7 - (0..7)) = 7..0 + if (byte & flag) { + DEBUG_OUTPUT.printf_P(PSTR(" %s"), _RRType2Name(u)); + } + } + break;*/ + default: + DEBUG_OUTPUT.printf_P(PSTR("generic ")); + break; + } + DEBUG_OUTPUT.printf_P(PSTR("\n")); + } + else + { + DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer: FAILED to read specific answer of type 0x%04X!\n"), _DH(), p_rpRRAnswer->m_Header.m_Attributes.m_u16Type); + } + ); // DEBUG_EX_INFO + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer: FAILED!\n"), _DH());); + return bResult; +} + +#ifdef MDNS_IPV4_SUPPORT +/* + MDNSResponder::_readRRAnswerA +*/ +bool MDNSResponder::clsHost::_readRRAnswerA(MDNSResponder::clsHost::stcRRAnswerA& p_rRRAnswerA, + uint16_t p_u16RDLength) +{ + + uint32_t u32IPv4Address; + bool bResult = ((MDNS_IPV4_SIZE == p_u16RDLength) && + (_udpReadBuffer((unsigned char*)&u32IPv4Address, MDNS_IPV4_SIZE)) && + ((p_rRRAnswerA.m_IPAddress = IPAddress(u32IPv4Address)))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerA: FAILED!\n"), _DH());); + return bResult; +} +#endif + +/* + MDNSResponder::_readRRAnswerPTR +*/ +bool MDNSResponder::clsHost::_readRRAnswerPTR(MDNSResponder::clsHost::stcRRAnswerPTR& p_rRRAnswerPTR, + uint16_t p_u16RDLength) +{ + bool bResult = ((p_u16RDLength) && + (_readRRDomain(p_rRRAnswerPTR.m_PTRDomain))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerPTR: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_readRRAnswerTXT + + Read TXT items from a buffer like 4c#=15ff=20 +*/ +bool MDNSResponder::clsHost::_readRRAnswerTXT(MDNSResponder::clsHost::stcRRAnswerTXT& p_rRRAnswerTXT, + uint16_t p_u16RDLength) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: RDLength:%u\n"), _DH(), p_u16RDLength);); + bool bResult = true; + + p_rRRAnswerTXT.clear(); + if (p_u16RDLength) + { + bResult = false; + + unsigned char* pucBuffer = new unsigned char[p_u16RDLength]; + if (pucBuffer) + { + if (_udpReadBuffer(pucBuffer, p_u16RDLength)) + { + bResult = true; + + const unsigned char* pucCursor = pucBuffer; + while ((pucCursor < (pucBuffer + p_u16RDLength)) && + (bResult)) + { + bResult = false; + + stcServiceTxt* pTxt = 0; + unsigned char ucLength = *pucCursor++; // Length of the next txt item + if (ucLength) + { + DEBUG_EX_INFO( + static char sacBuffer[64]; *sacBuffer = 0; + uint8_t u8MaxLength = ((ucLength > (sizeof(sacBuffer) - 1)) ? (sizeof(sacBuffer) - 1) : ucLength); + os_strncpy(sacBuffer, (const char*)pucCursor, u8MaxLength); sacBuffer[u8MaxLength] = 0; + DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: Item(%u): %s\n"), _DH(), ucLength, sacBuffer); + ); + + unsigned char* pucEqualSign = (unsigned char*)os_strchr((const char*)pucCursor, '='); // Position of the '=' sign + unsigned char ucKeyLength; + if ((pucEqualSign) && + ((ucKeyLength = (pucEqualSign - pucCursor)))) + { + unsigned char ucValueLength = (ucLength - (pucEqualSign - pucCursor + 1)); + bResult = (((pTxt = new stcServiceTxt)) && + (pTxt->setKey((const char*)pucCursor, ucKeyLength)) && + (pTxt->setValue((const char*)(pucEqualSign + 1), ucValueLength))); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: INVALID TXT format (No '=')!\n"), _DH());); + } + pucCursor += ucLength; + } + else // no/zero length TXT + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: TXT answer contains no items.\n"), _DH());); + bResult = true; + } + + if ((bResult) && + (pTxt)) // Everythings fine so far + { + // Link TXT item to answer TXTs + pTxt->m_pNext = p_rRRAnswerTXT.m_Txts.m_pTxts; + p_rRRAnswerTXT.m_Txts.m_pTxts = pTxt; + } + else // At least no TXT (migth be OK, if length was 0) OR an error + { + if (!bResult) + { + DEBUG_EX_ERR( + DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: FAILED to read TXT item!\n"), _DH()); + DEBUG_OUTPUT.printf_P(PSTR("RData dump:\n")); + _udpDump((m_rUDPContext.tell() - p_u16RDLength), p_u16RDLength); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + ); + } + if (pTxt) + { + delete pTxt; + pTxt = 0; + } + p_rRRAnswerTXT.clear(); + } + } // while + + DEBUG_EX_ERR( + if (!bResult) // Some failure + { + DEBUG_OUTPUT.printf_P(PSTR("RData dump:\n")); + _udpDump((m_rUDPContext.tell() - p_u16RDLength), p_u16RDLength); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + } + ); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: FAILED to read TXT content!\n"), _DH());); + } + // Clean up + delete[] pucBuffer; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: FAILED to alloc buffer for TXT content!\n"), _DH());); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: WARNING! No content!\n"), _DH());); + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: FAILED!\n"), _DH());); + return bResult; +} + +#ifdef MDNS_IPV6_SUPPORT +bool MDNSResponder::clsHost::_readRRAnswerAAAA(MDNSResponder::clsHost::stcRRAnswerAAAA& p_rRRAnswerAAAA, + uint16_t p_u16RDLength) +{ + bool bResult = false; + + uint32_t au32IPv6Address[4]; // 16 bytes + if ((bResult = ((MDNS_IPV6_SIZE == p_u16RDLength) && + (_udpReadBuffer((uint8_t*)&au32IPv6Address[0], MDNS_IPV6_SIZE))))) + { + + // ?? IPADDR6_INIT_HOST ?? + ip_addr_t addr = IPADDR6_INIT(au32IPv6Address[0], au32IPv6Address[1], au32IPv6Address[2], au32IPv6Address[3]); + p_rRRAnswerAAAA.m_IPAddress = IPAddress(addr); + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerAAAA: FAILED!\n"), _DH());); + return bResult; +} +#endif + +/* + MDNSResponder::_readRRAnswerSRV +*/ +bool MDNSResponder::clsHost::_readRRAnswerSRV(MDNSResponder::clsHost::stcRRAnswerSRV& p_rRRAnswerSRV, + uint16_t p_u16RDLength) +{ + bool bResult = (((3 * sizeof(uint16_t)) < p_u16RDLength) && + (_udpRead16(p_rRRAnswerSRV.m_u16Priority)) && + (_udpRead16(p_rRRAnswerSRV.m_u16Weight)) && + (_udpRead16(p_rRRAnswerSRV.m_u16Port)) && + (_readRRDomain(p_rRRAnswerSRV.m_SRVDomain))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerSRV: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_readRRAnswerGeneric +*/ +bool MDNSResponder::clsHost::_readRRAnswerGeneric(MDNSResponder::clsHost::stcRRAnswerGeneric& p_rRRAnswerGeneric, + uint16_t p_u16RDLength) +{ + bool bResult = (0 == p_u16RDLength); + + p_rRRAnswerGeneric.clear(); + if (((p_rRRAnswerGeneric.m_u16RDLength = p_u16RDLength)) && + ((p_rRRAnswerGeneric.m_pu8RDData = new unsigned char[p_rRRAnswerGeneric.m_u16RDLength]))) + { + + bResult = _udpReadBuffer(p_rRRAnswerGeneric.m_pu8RDData, p_rRRAnswerGeneric.m_u16RDLength); + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerGeneric: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_readRRHeader +*/ +bool MDNSResponder::clsHost::_readRRHeader(MDNSResponder::clsHost::stcRRHeader& p_rRRHeader) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRHeader\n"));); + + bool bResult = ((_readRRDomain(p_rRRHeader.m_Domain)) && + (_readRRAttributes(p_rRRHeader.m_Attributes))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRHeader: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_readRRDomain + + Reads a (maybe multilevel compressed) domain from the UDP input buffer. + +*/ +bool MDNSResponder::clsHost::_readRRDomain(MDNSResponder::clsHost::stcRRDomain& p_rRRDomain) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain\n"));); + + bool bResult = ((p_rRRDomain.clear()) && + (_readRRDomain_Loop(p_rRRDomain, 0))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_readRRDomain_Loop + + Reads a domain from the UDP input buffer. For every compression level, the functions + calls itself recursively. To avoid endless recursion because of malformed MDNS records, + the maximum recursion depth is set by MDNS_DOMAIN_MAX_REDIRCTION. + +*/ +bool MDNSResponder::clsHost::_readRRDomain_Loop(MDNSResponder::clsHost::stcRRDomain& p_rRRDomain, + uint8_t p_u8Depth) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u)\n"), _DH(), p_u8Depth);); + + bool bResult = false; + + if (MDNS_DOMAIN_MAX_REDIRCTION >= p_u8Depth) + { + bResult = true; + + uint8_t u8Len = 0; + do + { + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u): Offset:%u p0:%02x\n"), _DH(), p_u8Depth, m_rUDPContext.tell(), m_rUDPContext.peek());); + _udpRead8(u8Len); + + if (u8Len & MDNS_DOMAIN_COMPRESS_MARK) + { + // Compressed label(s) + uint16_t u16Offset = ((u8Len & ~MDNS_DOMAIN_COMPRESS_MARK) << 8); // Implicit BE to LE conversion! + _udpRead8(u8Len); + u16Offset |= u8Len; + + if (m_rUDPContext.isValidOffset(u16Offset)) + { + size_t stCurrentPosition = m_rUDPContext.tell(); // Prepare return from recursion + + //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u): Redirecting from %u to %u!\n"), _DH(), p_u8Depth, stCurrentPosition, u16Offset);); + m_rUDPContext.seek(u16Offset); + if (_readRRDomain_Loop(p_rRRDomain, p_u8Depth + 1)) // Do recursion + { + //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u): Succeeded to read redirected label! Returning to %u\n"), _DH(), p_u8Depth, stCurrentPosition);); + m_rUDPContext.seek(stCurrentPosition); // Restore after recursion + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u): FAILED to read redirected label!\n"), _DH(), p_u8Depth);); + bResult = false; + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u): INVALID offset in redirection!\n"), _DH(), p_u8Depth);); + bResult = false; + } + break; + } + else + { + // Normal (uncompressed) label (maybe '\0' only) + if (MDNS_DOMAIN_MAXLENGTH > (p_rRRDomain.m_u16NameLength + u8Len)) + { + // Add length byte + p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength] = u8Len; + ++(p_rRRDomain.m_u16NameLength); + if (u8Len) // Add name + { + if ((bResult = _udpReadBuffer((unsigned char*) & (p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength]), u8Len))) + { + /* DEBUG_EX_INFO( + p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength + u8Len] = 0; // Closing '\0' for printing + DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u): Domain label (%u): %s\n"), _DH(), p_u8Depth, (unsigned)(p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength - 1]), &(p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength])); + );*/ + + p_rRRDomain.m_u16NameLength += u8Len; + } + } + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(2) offset:%u p0:%x\n"), _DH(), m_rUDPContext.tell(), m_rUDPContext.peek());); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u): ERROR! Domain name too long (%u + %u)!\n"), _DH(), p_u8Depth, p_rRRDomain.m_u16NameLength, u8Len);); + bResult = false; + break; + } + } + } while ((bResult) && + (0 != u8Len)); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u): ERROR! Too many redirections!\n"), _DH(), p_u8Depth);); + } + return bResult; +} + +/* + MDNSResponder::_readRRAttributes +*/ +bool MDNSResponder::clsHost::_readRRAttributes(MDNSResponder::clsHost::stcRRAttributes& p_rRRAttributes) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAttributes\n"));); + + bool bResult = ((_udpRead16(p_rRRAttributes.m_u16Type)) && + (_udpRead16(p_rRRAttributes.m_u16Class))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAttributes: FAILED!\n"), _DH());); + return bResult; +} + + +/* + DOMAIN NAMES +*/ + +/* + MDNSResponder::_buildDomainForHost + + Builds a MDNS host domain (eg. esp8266.local) for the given hostname. + +*/ +bool MDNSResponder::clsHost::_buildDomainForHost(const char* p_pcHostName, + MDNSResponder::clsHost::stcRRDomain& p_rHostDomain) const +{ + + p_rHostDomain.clear(); + bool bResult = ((p_pcHostName) && + (*p_pcHostName) && + (p_rHostDomain.addLabel(p_pcHostName)) && + (p_rHostDomain.addLabel(scpcLocal)) && + (p_rHostDomain.addLabel(0))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _buildDomainForHost: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_buildDomainForDNSSD + + Builds the '_services._dns-sd._udp.local' domain. + Used while detecting generic service enum question (DNS-SD) and answering these questions. + +*/ +bool MDNSResponder::clsHost::_buildDomainForDNSSD(MDNSResponder::clsHost::stcRRDomain& p_rDNSSDDomain) const +{ + p_rDNSSDDomain.clear(); + bool bResult = ((p_rDNSSDDomain.addLabel(scpcServices, true)) && + (p_rDNSSDDomain.addLabel(scpcDNSSD, true)) && + (p_rDNSSDDomain.addLabel(scpcUDP, true)) && + (p_rDNSSDDomain.addLabel(scpcLocal)) && + (p_rDNSSDDomain.addLabel(0))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _buildDomainForDNSSD: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_buildDomainForService + + Builds the domain for the given service (eg. _http._tcp.local or + MyESP._http._tcp.local (if p_bIncludeName is set)). + +*/ +bool MDNSResponder::clsHost::_buildDomainForService(const MDNSResponder::clsHost::stcService& p_Service, + bool p_bIncludeName, + MDNSResponder::clsHost::stcRRDomain& p_rServiceDomain) const +{ + p_rServiceDomain.clear(); + bool bResult = (((!p_bIncludeName) || + (p_rServiceDomain.addLabel(p_Service.m_pcName))) && + (p_rServiceDomain.addLabel(p_Service.m_pcServiceType, ('_' != *p_Service.m_pcServiceType))) && + (p_rServiceDomain.addLabel(p_Service.m_pcProtocol, ('_' != *p_Service.m_pcProtocol))) && + (p_rServiceDomain.addLabel(scpcLocal)) && + (p_rServiceDomain.addLabel(0))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _buildDomainForService: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_buildDomainForService + + Builds the domain for the given service properties (eg. _http._tcp.local). + The usual prepended '_' are added, if missing in the input strings. + +*/ +bool MDNSResponder::clsHost::_buildDomainForService(const char* p_pcServiceType, + const char* p_pcProtocol, + MDNSResponder::clsHost::stcRRDomain& p_rServiceDomain) const +{ + p_rServiceDomain.clear(); + bool bResult = ((p_pcServiceType) && + (p_pcProtocol) && + (p_rServiceDomain.addLabel(p_pcServiceType, ('_' != *p_pcServiceType))) && + (p_rServiceDomain.addLabel(p_pcProtocol, ('_' != *p_pcProtocol))) && + (p_rServiceDomain.addLabel(scpcLocal)) && + (p_rServiceDomain.addLabel(0))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _buildDomainForService: FAILED for (%s.%s)!\n"), _DH(), (p_pcServiceType ? : "-"), (p_pcProtocol ? : "-"));); + return bResult; +} + +#ifdef MDNS_IPV4_SUPPORT +/* + MDNSResponder::_buildDomainForReverseIPv4 + + The IPv4 address is stringized by printing the four address bytes into a char buffer in reverse order + and adding 'in-addr.arpa' (eg. 012.789.456.123.in-addr.arpa). + Used while detecting reverse IPv4 questions and answering these +*/ +bool MDNSResponder::clsHost::_buildDomainForReverseIPv4(IPAddress p_IPv4Address, + MDNSResponder::clsHost::stcRRDomain& p_rReverseIPv4Domain) const +{ + bool bResult = ((p_IPv4Address.isSet()) && + (p_IPv4Address.isV4())); + + p_rReverseIPv4Domain.clear(); + + char acBuffer[32]; + for (int i = MDNS_IPV4_SIZE; ((bResult) && (i >= 1)); --i) + { + itoa(p_IPv4Address[i - 1], acBuffer, 10); + bResult = p_rReverseIPv4Domain.addLabel(acBuffer); + } + bResult = ((bResult) && + (p_rReverseIPv4Domain.addLabel(scpcReverseIPv4Domain)) && + (p_rReverseIPv4Domain.addLabel(scpcReverseTopDomain)) && + (p_rReverseIPv4Domain.addLabel(0))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _buildDomainForReverseIPv4: FAILED!\n"), _DH());); + return bResult; +} +#endif + +#ifdef MDNS_IPV6_SUPPORT +/* + MDNSResponder::_buildDomainForReverseIPv6 + + The IPv6 address is stringized by printing the 16 address bytes (32 nibbles) into a char buffer in reverse order + and adding 'ip6.arpa' (eg. 3.B.6.E.A.1.B.B.A.B.F.7.F.8.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.ip6.arpa). + Used while detecting reverse IPv6 questions and answering these +*/ +bool MDNSResponder::clsHost::_buildDomainForReverseIPv6(IPAddress p_IPv6Address, + MDNSResponder::clsHost::stcRRDomain& p_rReverseIPv6Domain) const +{ + bool bResult = ((p_IPv6Address.isSet()) && + (p_IPv6Address.isV6())); + + p_rReverseIPv6Domain.clear(); + + const uint16_t* pRaw = p_IPv6Address.raw6(); + for (int8_t i8 = (MDNS_IPV6_SIZE / 2); ((bResult) && (i8 > 0)); --i8) // 8..1 + { + uint16_t u16Part = ntohs(pRaw[i8 - 1] & 0xFFFF); + char acBuffer[2]; + for (uint8_t u8 = 0; ((bResult) && (u8 < 4)); ++u8) // 0..3 + { + itoa((u16Part & 0xF), acBuffer, 16); + bResult = p_rReverseIPv6Domain.addLabel(acBuffer); + u16Part >>= 4; + } + } + bResult = ((bResult) && + (p_rReverseIPv6Domain.addLabel(scpcReverseIPv6Domain)) && // .ip6.arpa + (p_rReverseIPv6Domain.addLabel(scpcReverseTopDomain)) && // .local + (p_rReverseIPv6Domain.addLabel(0))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _buildDomainForReverseIPv6: FAILED!\n"), _DH());); + return bResult; +} +#endif + + +/* + UDP +*/ + +/* + MDNSResponder::_udpReadBuffer +*/ +bool MDNSResponder::clsHost::_udpReadBuffer(unsigned char* p_pBuffer, + size_t p_stLength) +{ + bool bResult = ((true/*m_rUDPContext.getSize() > p_stLength*/) && + (p_pBuffer) && + (p_stLength) && + ((p_stLength == m_rUDPContext.read((char*)p_pBuffer, p_stLength)))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _udpReadBuffer: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_udpRead8 +*/ +bool MDNSResponder::clsHost::_udpRead8(uint8_t& p_ru8Value) +{ + return _udpReadBuffer((unsigned char*)&p_ru8Value, sizeof(p_ru8Value)); +} + +/* + MDNSResponder::_udpRead16 +*/ +bool MDNSResponder::clsHost::_udpRead16(uint16_t& p_ru16Value) +{ + bool bResult = false; + + if (_udpReadBuffer((unsigned char*)&p_ru16Value, sizeof(p_ru16Value))) + { + p_ru16Value = lwip_ntohs(p_ru16Value); + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::_udpRead32 +*/ +bool MDNSResponder::clsHost::_udpRead32(uint32_t& p_ru32Value) +{ + bool bResult = false; + + if (_udpReadBuffer((unsigned char*)&p_ru32Value, sizeof(p_ru32Value))) + { + p_ru32Value = lwip_ntohl(p_ru32Value); + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::_udpAppendBuffer +*/ +bool MDNSResponder::clsHost::_udpAppendBuffer(const unsigned char* p_pcBuffer, + size_t p_stLength) +{ + bool bResult = ((p_pcBuffer) && + (p_stLength) && + (p_stLength == m_rUDPContext.append((const char*)p_pcBuffer, p_stLength))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _udpAppendBuffer: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_udpAppend8 +*/ +bool MDNSResponder::clsHost::_udpAppend8(uint8_t p_u8Value) +{ + return (_udpAppendBuffer((unsigned char*)&p_u8Value, sizeof(p_u8Value))); +} + +/* + MDNSResponder::_udpAppend16 +*/ +bool MDNSResponder::clsHost::_udpAppend16(uint16_t p_u16Value) +{ + p_u16Value = lwip_htons(p_u16Value); + return (_udpAppendBuffer((unsigned char*)&p_u16Value, sizeof(p_u16Value))); +} + +/* + MDNSResponder::_udpAppend32 +*/ +bool MDNSResponder::clsHost::_udpAppend32(uint32_t p_u32Value) +{ + p_u32Value = lwip_htonl(p_u32Value); + return (_udpAppendBuffer((unsigned char*)&p_u32Value, sizeof(p_u32Value))); +} + +#ifdef DEBUG_ESP_MDNS_RESPONDER +/* + MDNSResponder::_udpDump +*/ +bool MDNSResponder::clsHost::_udpDump(bool p_bMovePointer /*= false*/) +{ + const uint8_t cu8BytesPerLine = 16; + + uint32_t u32StartPosition = m_rUDPContext.tell(); + DEBUG_OUTPUT.println("UDP Context Dump:"); + uint32_t u32Counter = 0; + uint8_t u8Byte = 0; + + while (_udpRead8(u8Byte)) + { + DEBUG_OUTPUT.printf_P(PSTR("%02x %s"), u8Byte, ((++u32Counter % cu8BytesPerLine) ? "" : "\n")); + } + DEBUG_OUTPUT.printf_P(PSTR("%sDone: %u bytes\n"), (((u32Counter) && (u32Counter % cu8BytesPerLine)) ? "\n" : ""), u32Counter); + + if (!p_bMovePointer) // Restore + { + m_rUDPContext.seek(u32StartPosition); + } + return true; +} + +/* + MDNSResponder::_udpDump +*/ +bool MDNSResponder::clsHost::_udpDump(unsigned p_uOffset, + unsigned p_uLength) +{ + if (m_rUDPContext.isValidOffset(p_uOffset)) + { + unsigned uCurrentPosition = m_rUDPContext.tell(); // Remember start position + + m_rUDPContext.seek(p_uOffset); + uint8_t u8Byte; + for (unsigned u = 0; ((u < p_uLength) && (_udpRead8(u8Byte))); ++u) + { + DEBUG_OUTPUT.printf_P(PSTR("%02x "), u8Byte); + } + // Return to start position + m_rUDPContext.seek(uCurrentPosition); + } + return true; +} +#endif + + +/** + READ/WRITE MDNS STRUCTS +*/ + +/* + MDNSResponder::_readMDNSMsgHeader + + Read a MDNS header from the UDP input buffer. + | 8 | 8 | 8 | 8 | + 00| Identifier | Flags & Codes | + 01| Question count | Answer count | + 02| NS answer count | Ad answer count | + + All 16-bit and 32-bit elements need to be translated form network coding to host coding (done in _udpRead16 and _udpRead32) + In addition, bitfield memory order is undefined in C standard (GCC doesn't order them in the coded direction...), so they + need some mapping here +*/ +bool MDNSResponder::clsHost::_readMDNSMsgHeader(MDNSResponder::clsHost::stcMsgHeader& p_rMsgHeader) +{ + bool bResult = false; + + uint8_t u8B1; + uint8_t u8B2; + if ((_udpRead16(p_rMsgHeader.m_u16ID)) && + (_udpRead8(u8B1)) && + (_udpRead8(u8B2)) && + (_udpRead16(p_rMsgHeader.m_u16QDCount)) && + (_udpRead16(p_rMsgHeader.m_u16ANCount)) && + (_udpRead16(p_rMsgHeader.m_u16NSCount)) && + (_udpRead16(p_rMsgHeader.m_u16ARCount))) + { + + p_rMsgHeader.m_1bQR = (u8B1 & 0x80); // Query/Responde flag + p_rMsgHeader.m_4bOpcode = (u8B1 & 0x78); // Operation code (0: Standard query, others ignored) + p_rMsgHeader.m_1bAA = (u8B1 & 0x04); // Authorative answer + p_rMsgHeader.m_1bTC = (u8B1 & 0x02); // Truncation flag + p_rMsgHeader.m_1bRD = (u8B1 & 0x01); // Recursion desired + + p_rMsgHeader.m_1bRA = (u8B2 & 0x80); // Recursion available + p_rMsgHeader.m_3bZ = (u8B2 & 0x70); // Zero + p_rMsgHeader.m_4bRCode = (u8B2 & 0x0F); // Response code + + /* DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readMDNSMsgHeader: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), + _DH(), + (unsigned)p_rMsgHeader.m_u16ID, + (unsigned)p_rMsgHeader.m_1bQR, (unsigned)p_rMsgHeader.m_4bOpcode, (unsigned)p_rMsgHeader.m_1bAA, (unsigned)p_rMsgHeader.m_1bTC, (unsigned)p_rMsgHeader.m_1bRD, + (unsigned)p_rMsgHeader.m_1bRA, (unsigned)p_rMsgHeader.m_4bRCode, + (unsigned)p_rMsgHeader.m_u16QDCount, + (unsigned)p_rMsgHeader.m_u16ANCount, + (unsigned)p_rMsgHeader.m_u16NSCount, + (unsigned)p_rMsgHeader.m_u16ARCount););*/ + bResult = true; + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readMDNSMsgHeader: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_write8 +*/ +bool MDNSResponder::clsHost::_write8(uint8_t p_u8Value, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + return ((_udpAppend8(p_u8Value)) && + (p_rSendParameter.shiftOffset(sizeof(p_u8Value)))); +} + +/* + MDNSResponder::_write16 +*/ +bool MDNSResponder::clsHost::_write16(uint16_t p_u16Value, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + return ((_udpAppend16(p_u16Value)) && + (p_rSendParameter.shiftOffset(sizeof(p_u16Value)))); +} + +/* + MDNSResponder::_write32 +*/ +bool MDNSResponder::clsHost::_write32(uint32_t p_u32Value, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + return ((_udpAppend32(p_u32Value)) && + (p_rSendParameter.shiftOffset(sizeof(p_u32Value)))); +} + +/* + MDNSResponder::_writeMDNSMsgHeader + + Write MDNS header to the UDP output buffer. + + All 16-bit and 32-bit elements need to be translated form host coding to network coding (done in _udpAppend16 and _udpAppend32) + In addition, bitfield memory order is undefined in C standard (GCC doesn't order them in the coded direction...), so they + need some mapping here +*/ +bool MDNSResponder::clsHost::_writeMDNSMsgHeader(const MDNSResponder::clsHost::stcMsgHeader& p_MsgHeader, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + /* DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSMsgHeader: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), + _DH(), + (unsigned)p_MsgHeader.m_u16ID, + (unsigned)p_MsgHeader.m_1bQR, (unsigned)p_MsgHeader.m_4bOpcode, (unsigned)p_MsgHeader.m_1bAA, (unsigned)p_MsgHeader.m_1bTC, (unsigned)p_MsgHeader.m_1bRD, + (unsigned)p_MsgHeader.m_1bRA, (unsigned)p_MsgHeader.m_4bRCode, + (unsigned)p_MsgHeader.m_u16QDCount, + (unsigned)p_MsgHeader.m_u16ANCount, + (unsigned)p_MsgHeader.m_u16NSCount, + (unsigned)p_MsgHeader.m_u16ARCount););*/ + + uint8_t u8B1((p_MsgHeader.m_1bQR << 7) | (p_MsgHeader.m_4bOpcode << 3) | (p_MsgHeader.m_1bAA << 2) | (p_MsgHeader.m_1bTC << 1) | (p_MsgHeader.m_1bRD)); + uint8_t u8B2((p_MsgHeader.m_1bRA << 7) | (p_MsgHeader.m_3bZ << 4) | (p_MsgHeader.m_4bRCode)); + bool bResult = ((_write16(p_MsgHeader.m_u16ID, p_rSendParameter)) && + (_write8(u8B1, p_rSendParameter)) && + (_write8(u8B2, p_rSendParameter)) && + (_write16(p_MsgHeader.m_u16QDCount, p_rSendParameter)) && + (_write16(p_MsgHeader.m_u16ANCount, p_rSendParameter)) && + (_write16(p_MsgHeader.m_u16NSCount, p_rSendParameter)) && + (_write16(p_MsgHeader.m_u16ARCount, p_rSendParameter))); + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSMsgHeader: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_writeRRAttributes +*/ +bool MDNSResponder::clsHost::_writeMDNSRRAttributes(const MDNSResponder::clsHost::stcRRAttributes& p_Attributes, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + bool bResult = ((_write16(p_Attributes.m_u16Type, p_rSendParameter)) && + (_write16(p_Attributes.m_u16Class, p_rSendParameter))); + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSRRAttributes: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_writeMDNSRRDomain +*/ +bool MDNSResponder::clsHost::_writeMDNSRRDomain(const MDNSResponder::clsHost::stcRRDomain& p_Domain, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + bool bResult = ((_udpAppendBuffer((const unsigned char*)p_Domain.m_acName, p_Domain.m_u16NameLength)) && + (p_rSendParameter.shiftOffset(p_Domain.m_u16NameLength))); + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSRRDomain: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_writeMDNSHostDomain + + Write a host domain to the UDP output buffer. + If the domain record is part of the answer, the records length is + prepended (p_bPrependRDLength is set). + + A very simple form of name compression is applied here: + If the domain is written to the UDP output buffer, the write offset is stored + together with a domain id (the pointer) in a p_rSendParameter substructure (cache). + If the same domain (pointer) should be written to the UDP output later again, + the old offset is retrieved from the cache, marked as a compressed domain offset + and written to the output buffer. + +*/ +bool MDNSResponder::clsHost::_writeMDNSHostDomain(const char* p_pcHostName, + bool p_bPrependRDLength, + uint16_t p_u16AdditionalLength, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + // The 'skip-compression' version is handled in '_writeMDNSAnswer_SRV' + uint16_t u16CachedDomainOffset = p_rSendParameter.findCachedDomainOffset((const void*)p_pcHostName, false); + + stcRRDomain hostDomain; + bool bResult = (u16CachedDomainOffset + // Found cached domain -> mark as compressed domain + ? ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset + ((!p_bPrependRDLength) || + (_write16((2 + p_u16AdditionalLength), p_rSendParameter))) && // Length of 'Cxxx' + (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) + (_write8((uint8_t)(u16CachedDomainOffset & 0xFF), p_rSendParameter))) + // No cached domain -> add this domain to cache and write full domain name + : ((_buildDomainForHost(p_pcHostName, hostDomain)) && // eg. esp8266.local + ((!p_bPrependRDLength) || + (_write16((hostDomain.m_u16NameLength + p_u16AdditionalLength), p_rSendParameter))) && // RDLength (if needed) + (p_rSendParameter.addDomainCacheItem((const void*)p_pcHostName, false, p_rSendParameter.m_u16Offset)) && + (_writeMDNSRRDomain(hostDomain, p_rSendParameter)))); + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSHostDomain: FAILED!\n"), _DH());); + return bResult; + +} + +/* + MDNSResponder::_writeMDNSServiceDomain + + Write a service domain to the UDP output buffer. + If the domain record is part of the answer, the records length is + prepended (p_bPrependRDLength is set). + + A very simple form of name compression is applied here: see '_writeMDNSHostDomain' + The cache differentiates of course between service domains which includes + the instance name (p_bIncludeName is set) and thoose who don't. + +*/ +bool MDNSResponder::clsHost::_writeMDNSServiceDomain(const MDNSResponder::clsHost::stcService& p_Service, + bool p_bIncludeName, + bool p_bPrependRDLength, + uint16_t p_u16AdditionalLength, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + // The 'skip-compression' version is handled in '_writeMDNSAnswer_SRV' + uint16_t u16CachedDomainOffset = p_rSendParameter.findCachedDomainOffset((const void*)&p_Service, p_bIncludeName); + + stcRRDomain serviceDomain; + bool bResult = (u16CachedDomainOffset + // Found cached domain -> mark as compressed domain + ? ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset + ((!p_bPrependRDLength) || + (_write16((2 + p_u16AdditionalLength), p_rSendParameter))) && // Lenght of 'Cxxx' + (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) + (_write8((uint8_t)(u16CachedDomainOffset & 0xFF), p_rSendParameter))) + // No cached domain -> add this domain to cache and write full domain name + : ((_buildDomainForService(p_Service, p_bIncludeName, serviceDomain)) && // eg. MyESP._http._tcp.local + ((!p_bPrependRDLength) || + (_write16((serviceDomain.m_u16NameLength + p_u16AdditionalLength), p_rSendParameter))) && // RDLength (if needed) + (p_rSendParameter.addDomainCacheItem((const void*)&p_Service, p_bIncludeName, p_rSendParameter.m_u16Offset)) && + (_writeMDNSRRDomain(serviceDomain, p_rSendParameter)))); + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSServiceDomain: FAILED!\n"), _DH());); + return bResult; + +} + +/* + MDNSResponder::_writeMDNSQuestion + + Write a MDNS question to the UDP output buffer + + QNAME (host/service domain, eg. esp8266.local) + QTYPE (16bit, eg. ANY) + QCLASS (16bit, eg. IN) + +*/ +bool MDNSResponder::clsHost::_writeMDNSQuestion(MDNSResponder::clsHost::stcRRQuestion& p_Question, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSQuestion\n"));); + + bool bResult = ((_writeMDNSRRDomain(p_Question.m_Header.m_Domain, p_rSendParameter)) && + (_writeMDNSRRAttributes(p_Question.m_Header.m_Attributes, p_rSendParameter))); + + DEBUG_EX_INFO(if (bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSQuestion "), _DH()); + _printRRDomain(p_Question.m_Header.m_Domain); + DEBUG_OUTPUT.printf_P(PSTR(" Type:%s Class:0x%04X\n"), + _RRType2Name(p_Question.m_Header.m_Attributes.m_u16Type), + p_Question.m_Header.m_Attributes.m_u16Class); + }); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSQuestion: FAILED!\n"), _DH());); + return bResult; + +} + + +#ifdef MDNS_IPV4_SUPPORT +/* + MDNSResponder::_writeMDNSAnswer_A + + Write a MDNS A answer to the UDP output buffer. + + NAME (var, host/service domain, eg. esp8266.local + TYPE (16bit, eg. A) + CLASS (16bit, eg. IN) + TTL (32bit, eg. 120) + RDLENGTH (16bit, eg 4) + RDATA (var, eg. 123.456.789.012) + + eg. esp8266.local A 0x8001 120 4 123.456.789.012 + Ref: http://www.zytrax.com/books/dns/ch8/a.html +*/ +bool MDNSResponder::clsHost::_writeMDNSAnswer_A(IPAddress p_IPAddress, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_A (%s)%s\n"), p_IPAddress.toString().c_str(), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); + + stcRRAttributes attributes(DNS_RRTYPE_A, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + const unsigned char aucIPAddress[MDNS_IPV4_SIZE] = { p_IPAddress[0], p_IPAddress[1], p_IPAddress[2], p_IPAddress[3] }; + bool bResult = ((p_IPAddress.isV4()) && + (_writeMDNSHostDomain(m_pcHostName, false, 0, p_rSendParameter)) && + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL + (_write16(MDNS_IPV4_SIZE, p_rSendParameter)) && // RDLength + (_udpAppendBuffer(aucIPAddress, MDNS_IPV4_SIZE)) && // RData + (p_rSendParameter.shiftOffset(MDNS_IPV4_SIZE))); + + DEBUG_EX_INFO(if (bResult) + DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_A %s.local Type:%s Class:0x%04X TTL:%u %s\n"), + _DH(), + m_pcHostName, + _RRType2Name(attributes.m_u16Type), + attributes.m_u16Class, + (p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), + p_IPAddress.toString().c_str()); + ); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_A: FAILED!\n"), _DH());); + return bResult; + +} + +/* + MDNSResponder::_writeMDNSAnswer_PTR_IPv4 + + Write a MDNS reverse IPv4 PTR answer to the UDP output buffer. + See: '_writeMDNSAnswer_A' + + eg. 012.789.456.123.in-addr.arpa PTR 0x8001 120 15 esp8266.local + Used while answering reverse IPv4 questions +*/ +bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_IPv4(IPAddress p_IPAddress, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_IPv4 (%s)%s\n"), p_IPAddress.toString().c_str(), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); + + stcRRDomain reverseIPv4Domain; + stcRRAttributes attributes(DNS_RRTYPE_PTR, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + stcRRDomain hostDomain; + bool bResult = ((p_IPAddress.isV4()) && + (_buildDomainForReverseIPv4(p_IPAddress, reverseIPv4Domain)) && // 012.789.456.123.in-addr.arpa + (_writeMDNSRRDomain(reverseIPv4Domain, p_rSendParameter)) && + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL + (_writeMDNSHostDomain(m_pcHostName, true, 0, p_rSendParameter))); // RDLength & RData (host domain, eg. esp8266.local) + + DEBUG_EX_INFO(if (bResult) + DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_IPv4 "), _DH()); + _printRRDomain(reverseIPv4Domain); + DEBUG_OUTPUT.printf_P(PSTR(" Type:%s Class:0x%04X TTL:%u %s.local\n"), + _RRType2Name(attributes.m_u16Type), + attributes.m_u16Class, + (p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), + m_pcHostName); + ); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_IPv4: FAILED!\n"), _DH());); + return bResult; +} +#endif + +/* + MDNSResponder::_writeMDNSAnswer_PTR_TYPE + + Write a MDNS PTR answer to the UDP output buffer. + See: '_writeMDNSAnswer_A' + + PTR all-services -> service type + eg. _services._dns-sd._udp.local PTR 0x8001 5400 xx _http._tcp.local + http://www.zytrax.com/books/dns/ch8/ptr.html +*/ +bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_TYPE(MDNSResponder::clsHost::stcService& p_rService, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_TYPE\n"));); + + stcRRDomain dnssdDomain; + stcRRDomain serviceDomain; + stcRRAttributes attributes(DNS_RRTYPE_PTR, DNS_RRCLASS_IN); // No cache flush for shared records! only INternet + bool bResult = ((_buildDomainForDNSSD(dnssdDomain)) && // _services._dns-sd._udp.local + (_writeMDNSRRDomain(dnssdDomain, p_rSendParameter)) && + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), p_rSendParameter)) && // TTL + (_writeMDNSServiceDomain(p_rService, false, true, 0, p_rSendParameter))); // RDLength & RData (service domain, eg. _http._tcp.local) + + DEBUG_EX_INFO(if (bResult) + DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_TYPE "), _DH()); + _printRRDomain(dnssdDomain); + DEBUG_OUTPUT.printf_P(PSTR(" Type:%s Class:0x%04X TTL:%u _%s._%s.local\n"), + _RRType2Name(attributes.m_u16Type), + attributes.m_u16Class, + (p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), + p_rService.m_pcServiceType, + p_rService.m_pcProtocol); + ); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_TYPE: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_writeMDNSAnswer_PTR_NAME + + Write a MDNS PTR answer to the UDP output buffer. + See: '_writeMDNSAnswer_A' + + PTR service type -> service name + eg. _http.tcp.local PTR 0x8001 120 xx myESP._http._tcp.local + http://www.zytrax.com/books/dns/ch8/ptr.html +*/ +bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_NAME(MDNSResponder::clsHost::stcService& p_rService, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_NAME\n"), _DH());); + + stcRRAttributes attributes(DNS_RRTYPE_PTR, DNS_RRCLASS_IN); // No cache flush for shared records! only INternet + bool bResult = ((_writeMDNSServiceDomain(p_rService, false, false, 0, p_rSendParameter)) && // _http._tcp.local + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), p_rSendParameter)) && // TTL + (_writeMDNSServiceDomain(p_rService, true, true, 0, p_rSendParameter))); // RDLength & RData (service domain, eg. MyESP._http._tcp.local) + + DEBUG_EX_INFO(if (bResult) + DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_NAME _%s._%s.local Type:%s Class:0x%04X TTL:%u %s._%s._%s.local\n"), + _DH(), + p_rService.m_pcServiceType, + p_rService.m_pcProtocol, + _RRType2Name(attributes.m_u16Type), + attributes.m_u16Class, + (p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), + p_rService.m_pcName, + p_rService.m_pcServiceType, + p_rService.m_pcProtocol); + ); + DEBUG_EX_ERR(if (!bResult)DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_NAME: FAILED!\n"), _DH());); + return bResult; +} + + +/* + MDNSResponder::_writeMDNSAnswer_TXT + + Write a MDNS TXT answer to the UDP output buffer. + See: '_writeMDNSAnswer_A' + + The TXT items in the RDATA block are 'length byte encoded': [len]vardata + + eg. myESP._http._tcp.local TXT 0x8001 120 4 c#=1 + http://www.zytrax.com/books/dns/ch8/txt.html +*/ +bool MDNSResponder::clsHost::_writeMDNSAnswer_TXT(MDNSResponder::clsHost::stcService& p_rService, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_TXT%s\n"), (p_rSendParameter.m_bCacheFlush ? "" : " nF"), _DH());); + + bool bResult = false; + + stcRRAttributes attributes(DNS_RRTYPE_TXT, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + + if ((_collectServiceTxts(p_rService)) && + (_writeMDNSServiceDomain(p_rService, true, false, 0, p_rSendParameter)) && // MyESP._http._tcp.local + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), p_rSendParameter)) && // TTL + (_write16(p_rService.m_Txts.length(), p_rSendParameter))) // RDLength + { + + bResult = true; + // RData Txts + for (stcServiceTxt* pTxt = p_rService.m_Txts.m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) + { + unsigned char ucLengthByte = pTxt->length(); + bResult = ((_udpAppendBuffer((unsigned char*)&ucLengthByte, sizeof(ucLengthByte))) && // Length + (p_rSendParameter.shiftOffset(sizeof(ucLengthByte))) && + ((size_t)os_strlen(pTxt->m_pcKey) == m_rUDPContext.append(pTxt->m_pcKey, os_strlen(pTxt->m_pcKey))) && // Key + (p_rSendParameter.shiftOffset((size_t)os_strlen(pTxt->m_pcKey))) && + (1 == m_rUDPContext.append("=", 1)) && // = + (p_rSendParameter.shiftOffset(1)) && + ((!pTxt->m_pcValue) || + (((size_t)os_strlen(pTxt->m_pcValue) == m_rUDPContext.append(pTxt->m_pcValue, os_strlen(pTxt->m_pcValue))) && // Value + (p_rSendParameter.shiftOffset((size_t)os_strlen(pTxt->m_pcValue)))))); + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_TXT: FAILED to write %sTxt %s=%s!\n"), _DH(), (pTxt->m_bTemp ? "temp. " : ""), (pTxt->m_pcKey ? : "?"), (pTxt->m_pcValue ? : "?"));); + } + } + + DEBUG_EX_INFO(if (bResult) + DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_TXT %s._%s._%s.local Type:%s Class:0x%04X TTL:%u \n"), + _DH(), + p_rService.m_pcName, + p_rService.m_pcServiceType, + p_rService.m_pcProtocol, + _RRType2Name(attributes.m_u16Type), + attributes.m_u16Class, + (p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), + p_rService.m_pcName, + p_rService.m_pcServiceType, + p_rService.m_pcProtocol); + ); + + _releaseTempServiceTxts(p_rService); + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_TXT: FAILED!\n"), _DH());); + return bResult; +} + +#ifdef MDNS_IPV6_SUPPORT +/* + MDNSResponder::_writeMDNSAnswer_AAAA + + Write a MDNS AAAA answer to the UDP output buffer. + See: '_writeMDNSAnswer_AAAA' + + eg. esp8266.local AAAA 0x8001 120 16 xxxx::xx + http://www.zytrax.com/books/dns/ch8/aaaa.html +*/ +bool MDNSResponder::clsHost::_writeMDNSAnswer_AAAA(IPAddress p_IPAddress, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_AAAA (%s)%s\n"), p_IPAddress.toString().c_str(), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); + + stcRRAttributes attributes(DNS_RRTYPE_AAAA, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + bool bResult = ((p_IPAddress.isV6()) && + (_writeMDNSHostDomain(m_pcHostName, false, 0, p_rSendParameter)) && // esp8266.local + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL + (_write16(MDNS_IPV6_SIZE, p_rSendParameter)) && // RDLength + (_udpAppendBuffer((uint8_t*)p_IPAddress.raw6(), MDNS_IPV6_SIZE)) && // RData + (p_rSendParameter.shiftOffset(MDNS_IPV6_SIZE))); + + DEBUG_EX_INFO(if (bResult) + DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_AAAA %s.local Type:%s Class:0x%04X TTL:%u %s\n"), + _DH(), + m_pcHostName, + _RRType2Name(attributes.m_u16Type), + attributes.m_u16Class, + (p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), + p_IPAddress.toString().c_str()); + ); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_AAAA: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_writeMDNSAnswer_PTR_IPv6 + + Write a MDNS reverse IPv6 PTR answer to the UDP output buffer. + See: '_writeMDNSAnswer_AAAA' + + eg. xxxx::xx.ip6.arpa PTR 0x8001 120 15 esp8266.local + Used while answering reverse IPv6 questions +*/ +bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_IPv6(IPAddress p_IPAddress, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_IPv6%s\n"), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); + + stcRRDomain reverseIPv6Domain; + stcRRAttributes attributes(DNS_RRTYPE_PTR, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + bool bResult = ((p_IPAddress.isV6()) && + (_buildDomainForReverseIPv6(p_IPAddress, reverseIPv6Domain)) && // xxxx::xx.ip6.arpa + (_writeMDNSRRDomain(reverseIPv6Domain, p_rSendParameter)) && + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL + (_writeMDNSHostDomain(m_pcHostName, true, 0, p_rSendParameter))); // RDLength & RData (host domain, eg. esp8266.local) + + DEBUG_EX_INFO(if (bResult) + DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_IPv6 "), _DH()); + _printRRDomain(reverseIPv6Domain); + DEBUG_OUTPUT.printf_P(PSTR(" Type:%s Class:0x%04X TTL:%u %s.local\n"), + _RRType2Name(attributes.m_u16Type), + attributes.m_u16Class, + (p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), + m_pcHostName); + ); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_IPv6: FAILED!\n"), _DH());); + return bResult; +} +#endif + +/* + MDNSResponder::_writeMDNSAnswer_SRV + + eg. MyESP._http.tcp.local SRV 0x8001 120 0 0 60068 esp8266.local + http://www.zytrax.com/books/dns/ch8/srv.html ???? Include instance name ???? +*/ +bool MDNSResponder::clsHost::_writeMDNSAnswer_SRV(MDNSResponder::clsHost::stcService& p_rService, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_SRV%s\n"), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); + + uint16_t u16CachedDomainOffset = (p_rSendParameter.m_bLegacyQuery + ? 0 + : p_rSendParameter.findCachedDomainOffset((const void*)m_pcHostName, false)); + + stcRRAttributes attributes(DNS_RRTYPE_SRV, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + stcRRDomain hostDomain; + bool bResult = ((_writeMDNSServiceDomain(p_rService, true, false, 0, p_rSendParameter)) && // MyESP._http._tcp.local + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL/*MDNS_SERVICE_TTL*/)), p_rSendParameter)) && // TTL + (!u16CachedDomainOffset + // No cache for domain name (or no compression allowed) + ? ((_buildDomainForHost(m_pcHostName, hostDomain)) && + (_write16((sizeof(uint16_t /*Prio*/) + // RDLength + sizeof(uint16_t /*Weight*/) + + sizeof(uint16_t /*Port*/) + + hostDomain.m_u16NameLength), p_rSendParameter)) && // Domain length + (_write16(MDNS_SRV_PRIORITY, p_rSendParameter)) && // Priority + (_write16(MDNS_SRV_WEIGHT, p_rSendParameter)) && // Weight + (_write16(p_rService.m_u16Port, p_rSendParameter)) && // Port + (p_rSendParameter.addDomainCacheItem((const void*)m_pcHostName, false, p_rSendParameter.m_u16Offset)) && + (_writeMDNSRRDomain(hostDomain, p_rSendParameter))) // Host, eg. esp8266.local + // Cache available for domain + : ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset + (_write16((sizeof(uint16_t /*Prio*/) + // RDLength + sizeof(uint16_t /*Weight*/) + + sizeof(uint16_t /*Port*/) + + 2), p_rSendParameter)) && // Length of 'C0xx' + (_write16(MDNS_SRV_PRIORITY, p_rSendParameter)) && // Priority + (_write16(MDNS_SRV_WEIGHT, p_rSendParameter)) && // Weight + (_write16(p_rService.m_u16Port, p_rSendParameter)) && // Port + (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) + (_write8((uint8_t)u16CachedDomainOffset, p_rSendParameter))))); // Offset + + DEBUG_EX_INFO(if (bResult) + DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_SRV %s._%s._%s.local Type:%s Class:0x%04X TTL:%u %u %u %u %s.local\n"), + _DH(), + p_rService.m_pcName, + p_rService.m_pcServiceType, + p_rService.m_pcProtocol, + _RRType2Name(attributes.m_u16Type), + attributes.m_u16Class, + (p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), + MDNS_SRV_PRIORITY, + MDNS_SRV_WEIGHT, + p_rService.m_u16Port, + m_pcHostName); + ); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_SRV: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_createNSECBitmap +*/ +MDNSResponder::clsHost::stcNSECBitmap* MDNSResponder::clsHost::_createNSECBitmap(uint32_t p_u32NSECContent) +{ + // Currently 6 bytes (6*8 -> 0..47) are long enough, and only this is implemented + stcNSECBitmap* pNSECBitmap = new stcNSECBitmap; + if (pNSECBitmap) + { + if (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::A)) + { + pNSECBitmap->setBit(DNS_RRTYPE_A); // 01/0x01 + } + if ((p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)) || + (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv6))) + { + pNSECBitmap->setBit(DNS_RRTYPE_PTR); // 12/0x0C + } + if (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::AAAA)) + { + pNSECBitmap->setBit(DNS_RRTYPE_AAAA); // 28/0x1C + } + if (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::TXT)) + { + pNSECBitmap->setBit(DNS_RRTYPE_TXT); // 16/0x10 + } + if (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::SRV)) + { + pNSECBitmap->setBit(DNS_RRTYPE_SRV); // 33/0x21 + } + if (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::NSEC)) + { + pNSECBitmap->setBit(DNS_RRTYPE_NSEC); // 47/0x2F + } + } + return pNSECBitmap; +} + +/* + MDNSResponder::_writeMDNSNSECBitmap +*/ +bool MDNSResponder::clsHost::_writeMDNSNSECBitmap(const MDNSResponder::clsHost::stcNSECBitmap& p_NSECBitmap, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + /* DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("_writeMDNSNSECBitmap: ")); + for (uint16_t u=0; u<p_NSECBitmap.m_u16BitmapLength; ++u) { + DEBUG_OUTPUT.printf_P(PSTR("0x%02X "), p_NSECBitmap.m_pu8BitmapData[u]); + } + DEBUG_OUTPUT.printf_P(PSTR("\n")); + );*/ + + bool bResult = ((_write16(p_NSECBitmap.length(), p_rSendParameter)) && + ((_udpAppendBuffer(p_NSECBitmap.m_au8BitmapData, p_NSECBitmap.length())) && + (p_rSendParameter.shiftOffset(p_NSECBitmap.length())))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSNSECBitmap: FAILED!\n"), _DH());); + return bResult; +} + +/* + MDNSResponder::_writeMDNSAnswer_NSEC(host) + + eg. esp8266.local NSEC 0x8001 120 XX esp8266.local xxx + http://www.zytrax.com/books/dns/ch8/nsec.html +*/ +bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC(uint32_t p_u32NSECContent, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC (host: %s)%s\n"), _replyFlags2String(p_u32NSECContent), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); + + stcRRAttributes attributes(DNS_RRTYPE_NSEC, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + stcNSECBitmap* pNSECBitmap = _createNSECBitmap(p_u32NSECContent); + bool bResult = ((pNSECBitmap) && // NSEC bitmap created + (_writeMDNSHostDomain(m_pcHostName, false, 0, p_rSendParameter)) && // esp8266.local + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL + (_writeMDNSHostDomain(m_pcHostName, true, (2 + pNSECBitmap->length()), p_rSendParameter)) && // XX esp8266.local + (_writeMDNSNSECBitmap(*pNSECBitmap, p_rSendParameter))); // NSEC bitmap + + DEBUG_EX_INFO(if (bResult) + DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC %s.local Type:%s Class:0x%04X TTL:%u %s %s\n"), + _DH(), + m_pcHostName, + _RRType2Name(attributes.m_u16Type), + attributes.m_u16Class, + (p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), + m_pcHostName, + _NSECBitmap2String(pNSECBitmap)); + ); + + if (pNSECBitmap) + { + delete pNSECBitmap; + pNSECBitmap = 0; + } + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC (host): FAILED!\n"), _DH());); + return bResult; +} + + +#ifdef MDNS_IPV4_SUPPORT +/* + MDNSResponder::_writeMDNSAnswer_NSEC_PTR_IPv4(host) + + eg. 012.789.456.123.in-addr.arpa NSEC 0x8001 120 XX 012.789.456.123.in-addr.arpa xxx + http://www.zytrax.com/books/dns/ch8/nsec.html +*/ +bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC_PTR_IPv4(IPAddress p_IPAddress, + stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC_PTR_IPv4\n"));); + + stcRRAttributes attributes(DNS_RRTYPE_NSEC, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + stcNSECBitmap* pNSECBitmap = _createNSECBitmap(static_cast<uint32_t>(enuContentFlag::PTR_IPv4)); + stcRRDomain reverseIPv4Domain; + bool bResult = ((p_IPAddress.isV4()) && + (pNSECBitmap) && // NSEC bitmap created + (_buildDomainForReverseIPv4(p_IPAddress, reverseIPv4Domain)) && // 012.789.456.123.in-addr.arpa + (_writeMDNSRRDomain(reverseIPv4Domain, p_rSendParameter)) && // 012.789.456.123.in-addr.arpa + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL + (_write16((reverseIPv4Domain.m_u16NameLength + (2 + pNSECBitmap->length())), p_rSendParameter)) && + (_writeMDNSRRDomain(reverseIPv4Domain, p_rSendParameter)) && // 012.789.456.123.in-addr.arpa + (_writeMDNSNSECBitmap(*pNSECBitmap, p_rSendParameter))); // NSEC bitmap + + DEBUG_EX_INFO(if (bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC_PTR_IPv4 "), _DH()); + _printRRDomain(reverseIPv4Domain); + DEBUG_OUTPUT.printf_P(PSTR(" Type:%s Class:0x%04X TTL:%u "), + _RRType2Name(attributes.m_u16Type), + attributes.m_u16Class, + (p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL))); + _printRRDomain(reverseIPv4Domain); + DEBUG_OUTPUT.printf_P(PSTR(" %s\n"), _NSECBitmap2String(pNSECBitmap)); + }); + + if (pNSECBitmap) + { + delete pNSECBitmap; + pNSECBitmap = 0; + } + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC_PTR_IPv4 (host): FAILED!\n"), _DH());); + return bResult; +} +#endif + + +#ifdef MDNS_IPV6_SUPPORT +/* + MDNSResponder::_writeMDNSAnswer_NSEC_PTR_IPv6(host) + + eg. 9.0.0.0.0.0.0.0.0.0.0.0.0.7.8.5.6.3.4.1.2.ip6.arpa NSEC 0x8001 120 XX 9.0.0.0.0.0.0.0.0.0.0.0.0.7.8.5.6.3.4.1.2.ip6.arpa xxx + http://www.zytrax.com/books/dns/ch8/nsec.html +*/ +bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC_PTR_IPv6(IPAddress p_IPAddress, + stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC_PTR_IPv6\n"));); + + stcRRAttributes attributes(DNS_RRTYPE_NSEC, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + stcNSECBitmap* pNSECBitmap = _createNSECBitmap(static_cast<uint32_t>(enuContentFlag::PTR_IPv6)); + stcRRDomain reverseIPv6Domain; + bool bResult = ((p_IPAddress.isV6()) && + (pNSECBitmap) && // NSEC bitmap created + (_buildDomainForReverseIPv6(p_IPAddress, reverseIPv6Domain)) && // 9.0.0.0.0.0.0.0.0.0.0.0.0.7.8.5.6.3.4.1.2.ip6.arpa + (_writeMDNSRRDomain(reverseIPv6Domain, p_rSendParameter)) && // 9.0.0.0.0.0.0.0.0.0.0.0.0.7.8.5.6.3.4.1.2.ip6.arpa + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL + (_write16((reverseIPv6Domain.m_u16NameLength + (2 + pNSECBitmap->length())), p_rSendParameter)) && + (_writeMDNSRRDomain(reverseIPv6Domain, p_rSendParameter)) && // 9.0.0.0.0.0.0.0.0.0.0.0.0.7.8.5.6.3.4.1.2.ip6.arpa + (_writeMDNSNSECBitmap(*pNSECBitmap, p_rSendParameter))); // NSEC bitmap + + DEBUG_EX_INFO(if (bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC_PTR_IPv6 "), _DH()); + _printRRDomain(reverseIPv6Domain); + DEBUG_OUTPUT.printf_P(PSTR(" Type:%s Class:0x%04X TTL:%u "), + _RRType2Name(attributes.m_u16Type), + attributes.m_u16Class, + (p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL))); + _printRRDomain(reverseIPv6Domain); + DEBUG_OUTPUT.printf_P(PSTR(" %s\n"), _NSECBitmap2String(pNSECBitmap)); + }); + + if (pNSECBitmap) + { + delete pNSECBitmap; + pNSECBitmap = 0; + } + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC_PTR_IPv6 (host): FAILED!\n"), _DH());); + return bResult; +} +#endif + +/* + MDNSResponder::_writeMDNSAnswer_NSEC(service) + + eg. MyESP._http.tcp.local NSEC 0x8001 4500 XX MyESP._http.tcp.local xxx + http://www.zytrax.com/books/dns/ch8/nsec.html +*/ +bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC(MDNSResponder::clsHost::stcService& p_rService, + uint32_t p_u32NSECContent, + MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC (service: %s)\n"), _DH(), _replyFlags2String(p_u32NSECContent));); + + stcRRAttributes attributes(DNS_RRTYPE_NSEC, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + stcNSECBitmap* pNSECBitmap = _createNSECBitmap(p_u32NSECContent); + bool bResult = ((pNSECBitmap) && // NSEC bitmap created + (_writeMDNSServiceDomain(p_rService, true, false, 0, p_rSendParameter)) && // MyESP._http._tcp.local + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), p_rSendParameter)) && // TTL + (_writeMDNSServiceDomain(p_rService, true, true, (2 + pNSECBitmap->length()), p_rSendParameter)) && // XX MyESP._http._tcp.local + (_writeMDNSNSECBitmap(*pNSECBitmap, p_rSendParameter))); // NSEC bitmap + + DEBUG_EX_INFO(if (bResult) + DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC %s._%s._%s.local Type:%s Class:0x%04X TTL:%u %s\n"), + _DH(), + p_rService.m_pcName, + p_rService.m_pcServiceType, + p_rService.m_pcProtocol, + _RRType2Name(attributes.m_u16Type), + attributes.m_u16Class, + (p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), + _NSECBitmap2String(pNSECBitmap)); + ); + + if (pNSECBitmap) + { + delete pNSECBitmap; + pNSECBitmap = 0; + } + + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC (service): FAILED!\n"), _DH());); + return bResult; +} + +} // namespace MDNSImplementation + +} // namespace esp8266 + + + + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h new file mode 100755 index 0000000000..240700b7cf --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h @@ -0,0 +1,169 @@ +/* + LEAmDNS2_Priv.h + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#ifndef LEAMDNS2_PRIV_H +#define LEAMDNS2_PRIV_H + +namespace esp8266 +{ + +/* + LEAmDNS +*/ + +namespace experimental +{ + +// Enable class debug functions +#define ESP_8266_MDNS_INCLUDE +#define DEBUG_ESP_MDNS_RESPONDER + + +#ifndef LWIP_OPEN_SRC +#define LWIP_OPEN_SRC +#endif + +// +// If ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE is defined, the mDNS responder ignores a successful probing +// This allows to drive the responder in a environment, where 'update()' isn't called in the loop +//#define ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE + +// Enable/disable debug trace macros +#ifdef DEBUG_ESP_MDNS_RESPONDER +#define DEBUG_ESP_MDNS_INFO +#define DEBUG_ESP_MDNS_ERR +#define DEBUG_ESP_MDNS_TX +#define DEBUG_ESP_MDNS_RX +#endif + +#ifdef DEBUG_ESP_MDNS_RESPONDER +#ifdef DEBUG_ESP_MDNS_INFO +#define DEBUG_EX_INFO(A) A +#else +#define DEBUG_EX_INFO(A) +#endif +#ifdef DEBUG_ESP_MDNS_ERR +#define DEBUG_EX_ERR(A) A +#else +#define DEBUG_EX_ERR(A) +#endif +#ifdef DEBUG_ESP_MDNS_TX +#define DEBUG_EX_TX(A) A +#else +#define DEBUG_EX_TX(A) +#endif +#ifdef DEBUG_ESP_MDNS_RX +#define DEBUG_EX_RX(A) A +#else +#define DEBUG_EX_RX(A) +#endif + +#ifdef DEBUG_ESP_PORT +#define DEBUG_OUTPUT DEBUG_ESP_PORT +#else +#define DEBUG_OUTPUT Serial +#endif +#else +#define DEBUG_EX_INFO(A) +#define DEBUG_EX_ERR(A) +#define DEBUG_EX_TX(A) +#define DEBUG_EX_RX(A) +#endif + +/* + This is NOT the TTL (Time-To-Live) for MDNS records, but the + subnet level distance MDNS records should travel. + 1 sets the subnet distance to 'local', which is default for MDNS. + (Btw.: 255 would set it to 'as far as possible' -> internet) + + However, RFC 3171 seems to force 255 instead +*/ +#define MDNS_MULTICAST_TTL 255 /* some say 1 is right*/ + +/* + This is the MDNS record TTL + Host level records are set to 2min (120s) + service level records are set to 75min (4500s) +*/ +#define MDNS_LEGACY_TTL 10 +#define MDNS_HOST_TTL 120 +#define MDNS_SERVICE_TTL 4500 + +/* + Compressed labels are flaged by the two topmost bits of the length byte being set +*/ +#define MDNS_DOMAIN_COMPRESS_MARK 0xC0 +/* + Avoid endless recursion because of malformed compressed labels +*/ +#define MDNS_DOMAIN_MAX_REDIRCTION 6 + +/* + Default service priority and weight in SRV answers +*/ +#define MDNS_SRV_PRIORITY 0 +#define MDNS_SRV_WEIGHT 0 + +/* + Delay between and number of probes for host and service domains + Delay between and number of announces for host and service domains + Delay between and number of queries; the delay is multiplied by the resent number in '_checkQueryCache' +*/ +#define MDNS_PROBE_DELAY 250 +#define MDNS_PROBE_COUNT 3 +#define MDNS_ANNOUNCE_DELAY 1000 +#define MDNS_ANNOUNCE_COUNT 3 +#define MDNS_DYNAMIC_QUERY_RESEND_DELAY 1000 + + +/* + Force host domain to use only lowercase letters +*/ +//#define MDNS_FORCE_LOWERCASE_HOSTNAME + +/* + Enable/disable the usage of the F() macro in debug trace printf calls. + There needs to be an PGM comptible printf function to use this. + + USE_PGM_PRINTF and F +*/ +#define USE_PGM_PRINTF + +#ifdef USE_PGM_PRINTF +#else +#ifdef F +#undef F +#endif +#define F(A) A +#endif + +} // namespace MDNSImplementation + +} // namespace esp8266 + +// Include the main header, so the submodlues only need to include this header +#include "LEAmDNS2.h" + + +#endif // LEAMDNS2_PRIV_H diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h b/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h new file mode 100755 index 0000000000..b28ea2a26e --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h @@ -0,0 +1,44 @@ +/* + LEAmDNS2_lwIPdefs.h + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#ifndef LEAMDNS2_LWIPDEFS_H +#define LEAMDNS2_LWIPDEFS_H + +#include <lwip/init.h> +#if LWIP_VERSION_MAJOR == 1 + +#include <lwip/mdns.h> // DNS_RRTYPE_xxx + +// cherry pick from lwip1 dns.c/mdns.c source files: +#define DNS_MQUERY_PORT 5353 +#define DNS_MQUERY_IPV4_GROUP_INIT IPAddress(224,0,0,251) /* resolver1.opendns.com */ +#define DNS_RRCLASS_ANY 255 /* any class */ + +#else // lwIP > 1 + +#include <lwip/prot/dns.h> // DNS_RRTYPE_xxx, DNS_MQUERY_PORT + +#endif + +#endif // LEAMDNS2_LWIPDEFS_H From 560c2a5ca1ecdd066940ae292c56f0e29a8c2b14 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 8 May 2020 00:28:47 +0200 Subject: [PATCH 003/152] updated Source files from LEA --- .../LEAmDNS/TwoInterfaces/TwoInterfaces.ino | 165 + libraries/ESP8266mDNS/src/ESP8266mDNS.h | 7 +- libraries/ESP8266mDNS/src/LEAmDNS2.h | 1303 ------ libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 1428 ++++++ libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 1658 +++++++ ...t_Control.cpp => LEAmDNS2Host_Control.cpp} | 1134 +++-- ..._Host_Debug.cpp => LEAmDNS2Host_Debug.cpp} | 153 +- .../ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 3253 +++++++++++++ ...Transfer.cpp => LEAmDNS2Host_Transfer.cpp} | 932 ++-- libraries/ESP8266mDNS/src/LEAmDNS2_API.cpp | 4164 ----------------- .../ESP8266mDNS/src/LEAmDNS2_APIHelpers.cpp | 354 -- .../ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 339 ++ libraries/ESP8266mDNS/src/LEAmDNS2_Host.cpp | 1336 ------ libraries/ESP8266mDNS/src/LEAmDNS2_Host.hpp | 1177 ----- .../ESP8266mDNS/src/LEAmDNS2_Host_Structs.cpp | 2435 ---------- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 1493 ++++++ libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h | 679 +++ libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h | 169 - libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h | 0 19 files changed, 10156 insertions(+), 12023 deletions(-) create mode 100644 libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino delete mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2.h create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2Host.h rename libraries/ESP8266mDNS/src/{LEAmDNS2_Host_Control.cpp => LEAmDNS2Host_Control.cpp} (66%) mode change 100755 => 100644 rename libraries/ESP8266mDNS/src/{LEAmDNS2_Host_Debug.cpp => LEAmDNS2Host_Debug.cpp} (65%) mode change 100755 => 100644 create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp rename libraries/ESP8266mDNS/src/{LEAmDNS2_Host_Transfer.cpp => LEAmDNS2Host_Transfer.cpp} (71%) mode change 100755 => 100644 delete mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_API.cpp delete mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_APIHelpers.cpp create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp delete mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_Host.cpp delete mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_Host.hpp delete mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_Host_Structs.cpp create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h delete mode 100755 libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h mode change 100755 => 100644 libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino new file mode 100644 index 0000000000..3434454491 --- /dev/null +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino @@ -0,0 +1,165 @@ + +#include <Arduino.h> +#include <PolledTimeout.h> + +#include <ESP8266mDNS.h> +#include <ESP8266WebServer.h> + + +clsMDNSHost mDNSHost_AP; +clsMDNSHost mDNSHost_STA; +ESP8266WebServer server(80); + +void connectToWiFi(const char* p_pcSSID, + const char* p_pcPWD, + uint32_t p_u32Timeout = 20) +{ + WiFi.begin(p_pcSSID, p_pcPWD); + Serial.println(""); + + // Wait for connection + uint8 u8Tries = p_u32Timeout; + while ((WiFi.status() != WL_CONNECTED) && + (u8Tries--)) { + delay(500); + Serial.print("."); + } + if (WiFi.status() == WL_CONNECTED) + { + Serial.println(""); + Serial.print("Connected to "); + Serial.println(p_pcSSID); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + } + else + { + Serial.printf("FAILED to connect to '%s'!\n", p_pcSSID); + } +} + +void setup(void) +{ + Serial.begin(115200); + Serial.setDebugOutput(false); + delay(2000); + Serial.printf("\nStart\n"); + + // Setup WiFi and AP + WiFi.setAutoConnect(false); + WiFi.mode(WIFI_AP_STA); + WiFi.softAP("ESP8266", "12345678"); + Serial.print("Created AP "); + Serial.println("ESP8266"); + Serial.print("AP-IP address: "); + Serial.println(WiFi.softAPIP()); + + if (mDNSHost_AP.begin("ESP8266", WIFI_AP, [](clsMDNSHost& p_rMDNSHost, + const char* p_pcDomainName, + bool p_bProbeResult)->void + { + Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); + + // Unattended added service + p_rMDNSHost.addService(0, "http", "tcp", 80); + })) + { + Serial.println("mDNS-AP started"); + } + else + { + Serial.println("FAILED to start mDNS-AP"); + } + + // Connect to WiFi network, with WRONG password + connectToWiFi("AP8", "WRONG_PW", 5); + + if (mDNSHost_STA.begin("esp8266", WIFI_STA, [](clsMDNSHost& p_rMDNSHost, + const char* p_pcDomainName, + bool p_bProbeResult)->void + { + Serial.printf("mDNSHost_STA::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); + if (p_bProbeResult) + { + p_rMDNSHost.addService("LEA_Weather", "http", "tcp", 80, [](clsMDNSHost::clsService& p_rService, + const char* p_pcInstanceName, + bool p_bProbeResult)->void + { + Serial.printf("mDNSHost_STA::HTTP-Service::ProbeResultCallback: '%s' is %s\n", p_pcInstanceName, (p_bProbeResult ? "FREE" : "USED!")); + if (p_bProbeResult) + { + if (!p_rService.addServiceTxt("path", "/")) + { + Serial.println("FAILED to add service TXT item!"); + } + p_rService.setDynamicServiceTxtCallback([](clsMDNSHost::clsService& p_rService)->void + { + Serial.printf("mDNSHost_STA::HTTP-Service::DynamicTXTCallback\n"); + + p_rService.addDynamicServiceTxt("user", "admin"); + static uint32_t u32Counter = 0; + p_rService.addDynamicServiceTxt("cnt", ++u32Counter); + }); + } + else + { + if (p_rService.indexInstanceName()) + { + Serial.printf("Changed service instance name to '%s'\n", p_rService.instanceName()); + } + else + { + Serial.println("FAILED to index service instance name!"); + } + } + }); + + // Unattended added service + p_rMDNSHost.addService("MQTTInstance", "mqtt", "tcp", 1883); + } + else + { + p_rMDNSHost.indexHostName(); + } + })) + { + Serial.println("mDNS-STA started"); + } + else + { + Serial.println("FAILED to start mDNS-STA"); + } + + // Non-synchronized added service + mDNSHost_STA.addService(0, "test", "tcp", 999); + + // Setup HTTP server + server.on("/", [](void) + { + Serial.println("server.on"); + server.send(200, "text/plain", "test"); + }); + server.begin(); + Serial.println("HTTP server started"); +} + +void loop(void) +{ + server.handleClient(); + mDNSHost_AP.update(); + mDNSHost_STA.update(); + + static esp8266::polledTimeout::oneShotMs timer2(esp8266::polledTimeout::oneShotMs::alwaysExpired); + if (timer2) + { + Serial.println("FIX PASSWORD"); + connectToWiFi("AP8", "_______"); + + timer2.reset(esp8266::polledTimeout::oneShotMs::neverExpires); + } +} + + + + + diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index 585ddfbbec..fdcf489fb0 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -44,15 +44,16 @@ #include "ESP8266mDNS_Legacy.h" #include "LEAmDNS.h" -#include "LEAmDNS2.h" +#include "LEAmDNS2Host.h" #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) // Maps the implementation to use to the global namespace type //using MDNSResponder = Legacy_MDNSResponder::MDNSResponder; //legacy -using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; //new +//using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; //new //using MDNSResponder = esp8266::experimental::MDNSResponder; //new^2 not compatible +using clsMDNSHost = esp8266::experimental::clsLEAMDNSHost; -extern MDNSResponder MDNS; +//extern MDNSResponder MDNS; #endif diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2.h b/libraries/ESP8266mDNS/src/LEAmDNS2.h deleted file mode 100755 index 7aa3bb0160..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2.h +++ /dev/null @@ -1,1303 +0,0 @@ -/* - LEAmDNS2.h - (c) 2018, LaborEtArs - - Version 0.9 beta - - Some notes (from LaborEtArs, 2018): - Essentially, this is an rewrite of the original EPS8266 Multicast DNS code (ESP8266mDNS). - The target of this rewrite was to keep the existing interface as stable as possible while - adding and extending the supported set of mDNS features. - A lot of the additions were basicly taken from Erik Ekman's lwIP mdns app code. - - Supported mDNS features (in some cases somewhat limited): - - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service - - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented - - Probing host and service domains for uniqueness in the local network - - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak) - - Announcing available services after successful probing - - Using fixed service TXT items or - - Using dynamic service TXT items for presented services (via callback) - - Remove services (and un-announcing them to the observers by sending goodbye-messages) - - Static queries for DNS-SD services (creating a fixed answer set after a certain timeout period) - - Dynamic queries for DNS-SD services with cached and updated answers and user notifications - - - Usage: - In most cases, this implementation should work as a 'drop-in' replacement for the original - ESP8266 Multicast DNS code. Adjustments to the existing code would only be needed, if some - of the new features should be used. - - For presenting services: - In 'setup()': - Install a callback for the probing of host (and service) domains via 'MDNS.setProbeResultCallback(probeResultCallback, &userData);' - Register DNS-SD services with 'MDNSResponder::hMDNSService hService = MDNS.addService("MyESP", "http", "tcp", 5000);' - (Install additional callbacks for the probing of these service domains via 'MDNS.setServiceProbeResultCallback(hService, probeResultCallback, &userData);') - Add service TXT items with 'MDNS.addServiceTxt(hService, "c#", "1");' or by installing a service TXT callback - using 'MDNS.setDynamicServiceTxtCallback(dynamicServiceTxtCallback, &userData);' or service specific - 'MDNS.setDynamicServiceTxtCallback(hService, dynamicServiceTxtCallback, &userData);' - Call MDNS.begin("MyHostName"); - - In 'probeResultCallback(MDNSResponder* p_MDNSResponder, const char* p_pcDomain, MDNSResponder:hMDNSService p_hMDNSService, bool p_bProbeResult, void* p_pUserdata)': - Check the probe result and update the host or service domain name if the probe failed - - In 'dynamicServiceTxtCallback(MDNSResponder* p_MDNSResponder, const hMDNSService p_hMDNSService, void* p_pUserdata)': - Add dynamic TXT items by calling 'MDNS.addDynamicServiceTxt(p_hMDNSService, "c#", "1");' - - In loop(): - Call 'MDNS.update();' - - - For querying services/hosts: - Static: - Call 'uint32_t u32AnswerCount = MDNS.queryService("http", "tcp");' or 'MDNS.queryHost("esp8266")'; - Iterate answers by: 'for (uint32_t u=0; u<u32AnswerCount; ++u) { const char* pHostName = MDNS.answerHostName(u); }' - You should call MDNS.removeQuery() sometimes later (when the answers are not needed anymore) - - Dynamic: - Install a dynamic service query by calling 'DNSResponder::hMDNSQuery hQuery = MDNS.installServiceQuery("http", "tcp", serviceQueryCallback, &userData);' - The callback 'serviceQueryCallback(MDNSResponder* p_MDNSResponder, const stcAnswerAccessor& p_MDNSAnswerAccessor, typeQueryAnswerType p_QueryAnswerTypeFlags, bool p_bSetContent)' - is called for any change in the answer set. - Call 'MDNS.removeQuery(hServiceQuery);' when the answers are not needed anymore - - - Reference: - Used mDNS messages: - A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 - AAAA (0x1C): eg. esp8266.local AAAA OP TTL 1234:5678::90 - PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local - PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local - PTR (0x0C, IPv4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local - PTR (0x0C, IPv6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local - SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local - TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 - NSEC (0x2F): eg. esp8266.local ... (DNSSEC) - - Some NOT used message types: - OPT (0x29): eDNS - - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#ifndef LEAMDNS2_H -#define LEAMDNS2_H - -#include <functional> // for UdpContext.h -#include <list> -#include <limits> -#include <map> - -#include "lwip/netif.h" -#include "WiFiUdp.h" -#include "lwip/udp.h" -#include "debug.h" -#include "include/UdpContext.h" -#include <PolledTimeout.h> - -#include "ESP8266WiFi.h" - - -namespace esp8266 -{ - -/** - LEAmDNS -*/ -namespace experimental -{ - -//this should be user-defined at build time -#ifndef ARDUINO_BOARD -#define ARDUINO_BOARD "generic" -#endif - -#define MDNS_IPV4_SUPPORT -#if LWIP_IPV6 -#define MDNS_IPV6_SUPPORT // If we've got IPv6 support, then we need IPv6 support :-) -#endif - - -#ifdef MDNS_IPV4_SUPPORT -#define MDNS_IPV4_SIZE 4 -#endif -#ifdef MDNS_IPV6_SUPPORT -#define MDNS_IPV6_SIZE 16 -#endif -/* - Maximum length for all service txts for one service -*/ -#define MDNS_SERVICE_TXT_MAXLENGTH 1300 -/* - Maximum length for a full domain name eg. MyESP._http._tcp.local -*/ -#define MDNS_DOMAIN_MAXLENGTH 256 -/* - Maximum length of on label in a domain name (length info fits into 6 bits) -*/ -#define MDNS_DOMAIN_LABEL_MAXLENGTH 63 -/* - Maximum length of a service name eg. http -*/ -#define MDNS_SERVICE_NAME_LENGTH 15 -/* - Maximum length of a service protocol name eg. tcp -*/ -#define MDNS_SERVICE_PROTOCOL_LENGTH 3 -/* - Default timeout for static service queries -*/ -#define MDNS_QUERYSERVICES_WAIT_TIME 5000 - -/* - DNS_RRTYPE_NSEC -*/ -#ifndef DNS_RRTYPE_NSEC -#define DNS_RRTYPE_NSEC 0x2F -#endif - - -/** - MDNSResponder -*/ -class MDNSResponder -{ -protected: -#include "LEAmDNS2_Host.hpp" - -public: - // MISC HELPERS - // Domain name helper - static bool indexDomain(char*& p_rpcDomain, - const char* p_pcDivider = "-", - const char* p_pcDefaultDomain = 0); - // Host name helper - static bool setNetIfHostName(netif* p_pNetIf, - const char* p_pcHostName); - - // INTERFACE - MDNSResponder(void); - virtual ~MDNSResponder(void); - - // HANDLEs for opaque access to responder objects - /** - hMDNSHost - */ - using hMDNSHost = const void*; - /** - hMDNSService - */ - using hMDNSService = const void*; - /** - hMDNSTxt - */ - using hMDNSTxt = const void*; - /** - hMDNSQuery - */ - using hMDNSQuery = const void*; - - // CALLBACKS - /** - MDNSHostProbeResultCallbackFn - Callback function for host domain probe results - */ - using MDNSHostProbeResultCallbackFn = std::function<void(MDNSResponder& p_rMDNSResponder, - const hMDNSHost p_hMDNSHost, - const char* p_pcDomainName, - bool p_bProbeResult)>; - - // Create a MDNS netif responder netif by setting the default hostname - // Later call 'update()' in every 'loop' to run the process loop - // (probing, announcing, responding, ...) - // If no callback is given, the (maybe) already installed callback stays set - hMDNSHost begin(const char* p_pcHostName, - netif* p_pNetIf, - MDNSHostProbeResultCallbackFn p_fnCallback = 0); - bool begin(const char* p_pcHostName, - WiFiMode_t p_WiFiMode, - MDNSHostProbeResultCallbackFn p_fnCallback = 0); - bool begin(const char* p_pcHostName, - MDNSHostProbeResultCallbackFn p_fnCallback = 0); - - // Finish MDNS processing - bool close(const hMDNSHost p_hMDNSHost); - bool close(void); - - hMDNSHost getMDNSHost(netif* p_pNetIf) const; - hMDNSHost getMDNSHost(WiFiMode_t p_WiFiMode) const; - - // Change hostname (probing is restarted) - // If no callback is given, the (maybe) already installed callback stays set - bool setHostName(const hMDNSHost p_hMDNSHost, - const char* p_pcHostName, - MDNSHostProbeResultCallbackFn p_fnCallback = 0); - - const char* hostName(const hMDNSHost p_hMDNSHost) const; - - // Set a callback function for host probe results - // The callback function is called, when the probeing for the host domain - // succeededs or fails. - // In case of failure, the failed domain name should be changed. - bool setHostProbeResultCallback(const hMDNSHost p_hMDNSHost, - MDNSHostProbeResultCallbackFn p_fnCallback); - - // Returns 'true' is host domain probing is done - bool status(const hMDNSHost p_hMDNSHost) const; - - // Add a 'global' default' instance name for new services - bool setInstanceName(const hMDNSHost p_hMDNSHost, - const char* p_pcInstanceName); - const char* instanceName(const hMDNSHost p_hMDNSHost) const; - - /** - MDNSServiceProbeResultCallbackFn - Callback function for service domain probe results - */ - using MDNSServiceProbeResultCallbackFn = std::function<void(MDNSResponder& p_rMDNSResponder, - const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcServiceName, - bool p_bProbeResult)>; - // Add a new service to the MDNS responder. If no name (instance name) is given (p_pcName = 0) - // the current hostname is used. If the hostname is changed later, the instance names for - // these 'auto-named' services are changed to the new name also (and probing is restarted). - // The usual '_' before p_pcService (eg. http) and protocol (eg. tcp) may be given.# - // If no callback is given, the (maybe) already installed callback stays set - hMDNSService addService(const hMDNSHost p_hMDNSHost, - const char* p_pcName, - const char* p_pcServiceType, - const char* p_pcProtocol, - uint16_t p_u16Port, - MDNSServiceProbeResultCallbackFn p_fnCallback = 0); - // Removes a service from the MDNS responder - bool removeService(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService); - bool removeService(const hMDNSHost p_hMDNSHost, - const char* p_pcInstanceName, - const char* p_pcServiceType, - const char* p_pcProtocol); - hMDNSService findService(const hMDNSHost p_hMDNSHost, - const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol); - - // Change the services instance name (and restart probing). - // If no callback is given, the (maybe) already installed callback stays set - bool setServiceName(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcInstanceName, - MDNSServiceProbeResultCallbackFn p_fnCallback = 0); - const char* serviceName(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const; - const char* serviceType(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const; - const char* serviceProtocol(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const; - uint16_t servicePort(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const; - - // Set a service specific probe result callcack - bool setServiceProbeResultCallback(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - MDNSServiceProbeResultCallbackFn p_fnCallback); - - bool serviceStatus(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const; - - // Add a (static) MDNS TXT item ('key' = 'value') to the service - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - const char* p_pcValue); - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint32_t p_u32Value); - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint16_t p_u16Value); - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint8_t p_u8Value); - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - int32_t p_i32Value); - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - int16_t p_i16Value); - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - int8_t p_i8Value); - - // Remove an existing (static) MDNS TXT item from the service - bool removeServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const hMDNSTxt p_hTxt); - bool removeServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey); - - /** - MDNSDynamicServiceTxtCallbackFn - Callback function for dynamic MDNS TXT items - */ - using MDNSDynamicServiceTxtCallbackFn = std::function<void(MDNSResponder& p_rMDNSResponder, - const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService)>; - bool setDynamicServiceTxtCallback(const hMDNSHost p_hMDNSHost, - MDNSDynamicServiceTxtCallbackFn p_fnCallback); - bool setDynamicServiceTxtCallback(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - MDNSDynamicServiceTxtCallbackFn p_fnCallback); - - // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service - // Dynamic TXT items are removed right after one-time use. So they need to be added - // every time the value s needed (via callback). - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - const char* p_pcValue); - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint32_t p_u32Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint16_t p_u16Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint8_t p_u8Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - int32_t p_i32Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - int16_t p_i16Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - int8_t p_i8Value); - - // QUERIES & ANSWERS - /** - clsMDNSAnswerAccessor & clsAnswerAccessorVector - */ - struct clsMDNSAnswerAccessor - { - protected: - /** - stcCompareTxtKey - */ - struct stcCompareTxtKey - { - bool operator()(char const* p_pA, char const* p_pB) const; - }; - public: - clsMDNSAnswerAccessor(const clsHost::stcQuery::stcAnswer* p_pAnswer); - ~clsMDNSAnswerAccessor(void); - - /** - clsTxtKeyValueMap - */ - using clsTxtKeyValueMap = std::map<const char*, const char*, stcCompareTxtKey>; - - bool serviceDomainAvailable(void) const; - const char* serviceDomain(void) const; - bool hostDomainAvailable(void) const; - const char* hostDomain(void) const; - bool hostPortAvailable(void) const; - uint16_t hostPort(void) const; -#ifdef MDNS_IPV4_SUPPORT - bool IPv4AddressAvailable(void) const; - std::vector<IPAddress> IPv4Addresses(void) const; -#endif -#ifdef MDNS_IPV6_SUPPORT - bool IPv6AddressAvailable(void) const; - std::vector<IPAddress> IPv6Addresses(void) const; -#endif - bool txtsAvailable(void) const; - const char* txts(void) const; - const clsTxtKeyValueMap& txtKeyValues(void) const; - const char* txtValue(const char* p_pcKey) const; - - size_t printTo(Print& p_Print) const; - - protected: - const clsHost::stcQuery::stcAnswer* m_pAnswer; - clsTxtKeyValueMap m_TxtKeyValueMap; - }; - using clsMDNSAnswerAccessorVector = std::vector<clsMDNSAnswerAccessor>; - using typeQueryAnswerType = clsHost::typeQueryAnswerType; - using enuQueryAnswerType = clsHost::enuQueryAnswerType; - - // STATIC QUERY - // Perform a (static) service/host query. The function returns after p_u16Timeout milliseconds - // The answers (the number of received answers is returned) can be retrieved by calling - // - answerHostName (or hostname) - // - answerIP (or IP) - // - answerPort (or port) - uint32_t queryService(const hMDNSHost p_hMDNSHost, - const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); - uint32_t queryHost(const hMDNSHost p_hMDNSHost, - const char* p_pcHostName, - const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); - bool removeQuery(const hMDNSHost p_hMDNSHost); - bool hasQuery(const hMDNSHost p_hMDNSHost); - hMDNSQuery getQuery(const hMDNSHost p_hMDNSHost); - - clsMDNSAnswerAccessorVector answerAccessors(const hMDNSHost p_hMDNSHost); - uint32_t answerCount(const hMDNSHost p_hMDNSHost); - clsMDNSAnswerAccessor answerAccessor(const hMDNSHost p_hMDNSHost, - uint32_t p_u32AnswerIndex); - - // DYNAMIC QUERIES - /** - MDNSQueryCallbackFn - - Callback function for received answers for dynamic queries - */ - using MDNSQueryCallbackFn = std::function<void(MDNSResponder& p_pMDNSResponder, - hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hMDNSQuery, - const clsMDNSAnswerAccessor& p_MDNSAnswerAccessor, - typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item - bool p_bSetContent)>; // true: Answer component set, false: component deleted - - // Install a dynamic service/host query. For every received answer (part) the given callback - // function is called. The query will be updated every time, the TTL for an answer - // has timed-out. - // The answers can also be retrieved by calling - // - answerCount service/host (for host queries, this should never be >1) - // - answerServiceDomain service - // - hasAnswerHostDomain/answerHostDomain service/host - // - hasAnswerIPv4Address/answerIPv4Address service/host - // - hasAnswerIPv6Address/answerIPv6Address service/host - // - hasAnswerPort/answerPort service - // - hasAnswerTxts/answerTxts service - hMDNSQuery installServiceQuery(const hMDNSHost p_hMDNSHost, - const char* p_pcServiceType, - const char* p_pcProtocol, - MDNSQueryCallbackFn p_fnCallback); - hMDNSQuery installHostQuery(const hMDNSHost p_hMDNSHost, - const char* p_pcHostName, - MDNSQueryCallbackFn p_fnCallback); - // Remove a dynamic service query - bool removeQuery(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hMDNSQuery); - - - uint32_t answerCount(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hMDNSQuery); - clsMDNSAnswerAccessorVector answerAccessors(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hMDNSQuery); - clsMDNSAnswerAccessor answerAccessor(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hMDNSQuery, - uint32 p_u32AnswerIndex); - - /* bool hasAnswerServiceDomain(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - const char* answerServiceDomain(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerHostDomain(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - const char* answerHostDomain(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - #ifdef MDNS_IPV4_SUPPORT - bool hasAnswerIPv4Address(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIPv4AddressCount(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIPv4Address(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); - #endif - #ifdef MDNS_IPV6_SUPPORT - bool hasAnswerIPv6Address(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIPv6AddressCount(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIPv6Address(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); - #endif - bool hasAnswerPort(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - uint16_t answerPort(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerTxts(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - // Get the TXT items as a ';'-separated string - const char* answerTxts(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex);*/ - - // GENERAL MANAGEMENT - // Application should call this whenever AP is configured/disabled - bool notifyNetIfChange(netif* p_pNetIf); - - // 'update' should be called in every 'loop' to run the MDNS processing - bool update(const hMDNSHost p_hMDNSHost); - bool update(void); // Convenience - - // 'announce' can be called every time, the configuration of some service - // changes. Mainly, this would be changed content of TXT items. - bool announce(const hMDNSHost p_hMDNSHost); - bool announce(void); // Convenience - - // MISC - // Enable OTA update - hMDNSService enableArduino(const hMDNSHost p_hMDNSHost, - uint16_t p_u16Port, - bool p_bAuthUpload = false); - -protected: - /** Internal CLASSES & STRUCTS **/ - - // InstanceData - UdpContext* m_pUDPContext; - clsHostList m_HostList; - - // UDP CONTEXT - bool _allocUDPContext(void); - bool _releaseUDPContext(void); - bool _processUDPInput(void); - - // NETIF - clsHost* _createHost(netif* p_pNetIf); - bool _releaseHost(clsHost* p_pHost); - - const clsHost* _findHost(netif* p_pNetIf) const; - clsHost* _findHost(netif* p_pNetIf); - const clsHost* _findHost(const hMDNSHost p_hMDNSHost) const; - clsHost* _findHost(const hMDNSHost p_hMDNSHost); - - - // HANDLE HELPERS - bool _validateMDNSHostHandle(const hMDNSHost p_hMDNSHost) const; - bool _validateMDNSHostHandle(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const; - - clsHost* _NRH2Ptr(const hMDNSHost p_hMDNSHost); - const clsHost* _NRH2Ptr(const hMDNSHost p_hMDNSHost) const; - clsHost::stcService* _SH2Ptr(const hMDNSService p_hMDNSService); - const clsHost::stcService* _SH2Ptr(const hMDNSService p_hMDNSService) const; - - // INIT - clsHost* _begin(const char* p_pcHostName, - netif* p_pNetIf, - MDNSHostProbeResultCallbackFn p_fnCallback); - bool _close(clsHost& p_rHost); - - -#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER - - const char* _DH(hMDNSHost p_hMDNSResponder = 0) const; - -#endif // not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER - -}; - -#ifdef __MDNS_USE_LEGACY -/** - MDNSResponder_Legacy -*/ -class MDNSResponder_Legacy //: public MDNSResponder -{ -public: - /* INTERFACE */ - MDNSResponder_Legacy(void); - virtual ~MDNSResponder_Legacy(void); - - /** - hMDNSHost (opaque handle to access a netif binding) - */ - using hMDNSHost = const void*; - /** - hMDNSService (opaque handle to access the service) - */ - using hMDNSService = const void*; - /** - MDNSHostProbeResultCallbackFn - Callback function for host domain probe results - */ - using MDNSHostProbeResultCallbackFn = std::function<void(MDNSResponder* p_pMDNSResponder, - const hMDNSHost p_hMDNSHost, - const char* p_pcDomainName, - bool p_bProbeResult)>; - /* LEGACY 2 */ - using MDNSServiceProbeResultCallbackFn1 = std::function<void(MDNSResponder* p_pMDNSResponder, - const hMDNSService p_hMDNSService, - const char* p_pcServiceName, - bool p_bProbeResult)>; - using MDNSServiceProbeResultCallbackFn2 = std::function<void(const hMDNSService p_hMDNSService, - const char* p_pcServiceName, - bool p_bProbeResult)>; - /** - hMDNSTxt (opaque handle to access the TXT items) - */ - using hMDNSTxt = const void*; - /** - MDNSDynamicServiceTxtCallbackFn - Callback function for dynamic MDNS TXT items - */ - using MDNSDynamicServiceTxtCallbackFn = std::function<void(MDNSResponder* p_pMDNSResponder, - const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService)>; - // LEGACY - using MDNSDynamicServiceTxtCallbackFn1 = std::function<void(MDNSResponder* p_pMDNSResponder, - const hMDNSService p_hMDNSService)>; - using MDNSDynamicServiceTxtCallbackFn2 = std::function<void(const hMDNSService p_hMDNSService)>; - - - hMDNSHost getNetIfBinding(netif* p_pNetIf) const; - hMDNSHost getNetIfBinding(WiFiMode_t p_WiFiMode) const; - - // Create a MDNS responder netif binding by setting the default hostname - // Later call 'update()' in every 'loop' to run the process loop - // (probing, announcing, responding, ...) - - hMDNSHost begin(const char* p_pcHostName, - netif* p_pNetIf, - MDNSHostProbeResultCallbackFn p_fnCallback = 0); - bool begin(const char* p_pcHostName, - WiFiMode_t p_WiFiMode, - MDNSHostProbeResultCallbackFn p_fnCallback = 0); - bool begin(const char* p_pcHostName, - MDNSHostProbeResultCallbackFn p_fnCallback = 0); - - /* bool begin(const String& p_strHostName) {return begin(p_strHostName.c_str());} - // for compatibility - bool begin(const char* p_pcHostName, - IPAddress p_IPAddress, // ignored - uint32_t p_u32TTL = 120); // ignored - bool begin(const String& p_strHostName, - IPAddress p_IPAddress, // ignored - uint32_t p_u32TTL = 120) { // ignored - return begin(p_strHostName.c_str(), p_IPAddress, p_u32TTL); - }*/ - // Finish MDNS processing - bool close(const hMDNSHost p_hMDNSHost); - bool close(void); - // for ESP32 compatibility - bool end(void); - - // Change hostname (probing is restarted) - bool setHostName(const hMDNSHost p_hMDNSHost, - const char* p_pcHostName); - // for compatibility... - bool setHostname(const char* p_pcHostName); - bool setHostname(String p_strHostName); - - const char* hostName(const hMDNSHost p_hMDNSHost) const; - const char* hostname(void) const; - - // Returns 'true' is host domain probing is done - bool status(const hMDNSHost p_hMDNSHost) const; - bool status(void) const; - - bool setInstanceName(const hMDNSHost p_hMDNSHost, - const char* p_pcInstanceName); - bool setInstanceName(const char* p_pcInstanceName); - // for ESP32 compatibility - bool setInstanceName(const String& p_strHostName); - - // Add a new service to the MDNS responder. If no name (instance name) is given (p_pcName = 0) - // the current hostname is used. If the hostname is changed later, the instance names for - // these 'auto-named' services are changed to the new name also (and probing is restarted). - // The usual '_' before p_pcService (eg. http) and protocol (eg. tcp) may be given. - hMDNSService addService(const hMDNSHost p_hMDNSHost, - const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port); - hMDNSService addService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port); - // Removes a service from the MDNS responder - bool removeService(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService); - bool removeService(const hMDNSHost p_hMDNSHost, - const char* p_pcInstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol); - bool removeService(const hMDNSService p_hMDNSService); - bool removeService(const char* p_pcInstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol); - // for compatibility... - bool addService(String p_strServiceName, - String p_strProtocol, - uint16_t p_u16Port); - hMDNSService findService(const hMDNSHost p_hMDNSHost, - const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol); - hMDNSService findService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol); - - // Change the services instance name (and restart probing). - bool setServiceName(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcInstanceName); - bool setServiceName(const hMDNSService p_hMDNSService, - const char* p_pcInstanceName); - - const char* serviceName(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const; - const char* service(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const; - const char* serviceProtocol(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const; - /* LEGACY */ - const char* serviceName(const hMDNSService p_hMDNSService) const; - const char* service(const hMDNSService p_hMDNSService) const; - const char* serviceProtocol(const hMDNSService p_hMDNSService) const; - - bool serviceStatus(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const; - bool serviceStatus(const hMDNSService p_hMDNSService) const; - - // Add a (static) MDNS TXT item ('key' = 'value') to the service - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - const char* p_pcValue); - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint32_t p_u32Value); - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint16_t p_u16Value); - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint8_t p_u8Value); - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - int32_t p_i32Value); - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - int16_t p_i16Value); - hMDNSTxt addServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - int8_t p_i8Value); - // LEGACY - hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - const char* p_pcValue); - hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint32_t p_u32Value); - hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint16_t p_u16Value); - hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint8_t p_u8Value); - hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - int32_t p_i32Value); - hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - int16_t p_i16Value); - hMDNSTxt addServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - int8_t p_i8Value); - - // Remove an existing (static) MDNS TXT item from the service - bool removeServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const hMDNSTxt p_hTxt); - bool removeServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey); - bool removeServiceTxt(const hMDNSHost p_hMDNSHost, - const char* p_pcinstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol, - const char* p_pcKey); - bool removeServiceTxt(const hMDNSService p_hMDNSService, - const hMDNSTxt p_hTxt); - bool removeServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey); - bool removeServiceTxt(const char* p_pcinstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol, - const char* p_pcKey); - // for compatibility... - bool addServiceTxt(const char* p_pcService, - const char* p_pcProtocol, - const char* p_pcKey, - const char* p_pcValue); - bool addServiceTxt(String p_strService, - String p_strProtocol, - String p_strKey, - String p_strValue); - - bool setDynamicServiceTxtCallback(const hMDNSHost p_hMDNSHost, - MDNSDynamicServiceTxtCallbackFn p_fnCallback); - bool setDynamicServiceTxtCallback(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - MDNSDynamicServiceTxtCallbackFn p_fnCallback); - - // Set a global callback for dynamic MDNS TXT items. The callback function is called - // every time, a TXT item is needed for one of the installed services. - bool setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFn1 p_fnCallback); - bool setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFn2 p_fnCallback); - - // Set a service specific callback for dynamic MDNS TXT items. The callback function - // is called every time, a TXT item is needed for the given service. - bool setDynamicServiceTxtCallback(const hMDNSService p_hMDNSService, - MDNSDynamicServiceTxtCallbackFn1 p_fnCallback); - bool setDynamicServiceTxtCallback(const hMDNSService p_hMDNSService, - MDNSDynamicServiceTxtCallbackFn2 p_fnCallback); - - // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service - // Dynamic TXT items are removed right after one-time use. So they need to be added - // every time the value s needed (via callback). - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - const char* p_pcValue); - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint32_t p_u32Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint16_t p_u16Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint8_t p_u8Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - int32_t p_i32Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - int16_t p_i16Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcKey, - int8_t p_i8Value); - /* LEGACY */ - hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - const char* p_pcValue); - hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint32_t p_u32Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint16_t p_u16Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - uint8_t p_u8Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - int32_t p_i32Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - int16_t p_i16Value); - hMDNSTxt addDynamicServiceTxt(const hMDNSService p_hMDNSService, - const char* p_pcKey, - int8_t p_i8Value); - - /** - hMDNSQuery (opaque handle to access dynamic service queries) - */ - using hMDNSQuery = const void*; - //using hMDNSServiceQuery = hMDNSQuery; // for compatibility with V1 - - // Perform a (static) service/host query. The function returns after p_u16Timeout milliseconds - // The answers (the number of received answers is returned) can be retrieved by calling - // - answerHostName (or hostname) - // - answerIP (or IP) - // - answerPort (or port) - uint32_t queryService(const hMDNSHost p_hMDNSHost, - const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); - uint32_t queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); - // for compatibility... - uint32_t queryService(const String& p_strService, - const String& p_strProtocol); - uint32_t queryHost(const hMDNSHost p_hMDNSHost, - const char* p_pcHostName, - const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); - uint32_t queryHost(const char* p_pcHostName, - const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); - bool removeQuery(const hMDNSHost p_hMDNSHost); - bool removeQuery(void); - bool hasQuery(const hMDNSHost p_hMDNSHost); - bool hasQuery(void); - hMDNSQuery getQuery(const hMDNSHost p_hMDNSHost); - hMDNSQuery getQuery(void); - - const char* answerHostName(const hMDNSHost p_hMDNSHost, - const uint32_t p_u32AnswerIndex); - const char* answerHostName(const uint32_t p_u32AnswerIndex); - // for compatibility... - String hostname(const uint32_t p_u32AnswerIndex); -#ifdef MDNS_IPV4_SUPPORT - IPAddress answerIPv4(const hMDNSHost p_hMDNSHost, - const uint32_t p_u32AnswerIndex); - IPAddress answerIPv4(const uint32_t p_u32AnswerIndex); - // for compatibility - IPAddress answerIP(const uint32_t p_u32AnswerIndex); - IPAddress IP(const uint32_t p_u32AnswerIndex); -#endif -#ifdef MDNS_IPV6_SUPPORT - IPAddress answerIPv6(const hMDNSHost p_hMDNSHost, - const uint32_t p_u32AnswerIndex); - IPAddress answerIPv6(const uint32_t p_u32AnswerIndex); -#endif - uint16_t answerPort(const hMDNSHost p_hMDNSHost, - const uint32_t p_u32AnswerIndex); - uint16_t answerPort(const uint32_t p_u32AnswerIndex); - // for compatibility - uint16_t port(const uint32_t p_u32AnswerIndex); - - /** - typeQueryAnswerType & enuQueryAnswerType - */ - using typeQueryAnswerType = uint8_t; - enum class enuQueryAnswerType : typeQueryAnswerType - { - Unknown = 0x00, - ServiceDomain = 0x01, // Service domain - HostDomain = 0x02, // Host domain - Port = 0x04, // Port - Txts = 0x08, // TXT items -#ifdef MDNS_IPV4_SUPPORT - IPv4Address = 0x10, // IPv4 address -#endif -#ifdef MDNS_IPV6_SUPPORT - IPv6Address = 0x20, // IPv6 address -#endif - }; - //using AnswerType = enuQueryAnswerType; // for compatibility with V1 - - /** - stcAnswerAccessor - */ - struct stcAnswerAccessor - { - protected: - /** - stcCompareTxtKey - */ - struct stcCompareTxtKey - { - bool operator()(char const* p_pA, char const* p_pB) const; - }; - public: - stcAnswerAccessor(MDNSResponder& p_rMDNSResponder, - hMDNSQuery p_hQuery, - uint32_t p_u32AnswerIndex); - /** - clsTxtKeyValueMap - */ - using clsTxtKeyValueMap = std::map<const char*, const char*, stcCompareTxtKey>; - - bool serviceDomainAvailable(void) const; - const char* serviceDomain(void) const; - bool hostDomainAvailable(void) const; - const char* hostDomain(void) const; - bool hostPortAvailable(void) const; - uint16_t hostPort(void) const; -#ifdef MDNS_IPV4_SUPPORT - bool IPv4AddressAvailable(void) const; - std::vector<IPAddress> IPv4Addresses(void) const; -#endif -#ifdef MDNS_IPV6_SUPPORT - bool IPv6AddressAvailable(void) const; - std::vector<IPAddress> IPv6Addresses(void) const; -#endif - bool txtsAvailable(void) const; - const char* txts(void) const; - const clsTxtKeyValueMap& txtKeyValues(void) const; - const char* txtValue(const char* p_pcKey) const; - - size_t printTo(Print& p_Print) const; - - protected: - MDNSResponder& m_rMDNSResponder; - hMDNSQuery m_hQuery; - uint32_t m_u32AnswerIndex; - clsTxtKeyValueMap m_TxtKeyValueMap; - }; - - /** - MDNSQueryCallbackFn - - Callback function for received answers for dynamic queries - */ - using MDNSQueryCallbackFn = std::function<void(MDNSResponder* p_pMDNSResponder, - hMDNSHost p_hMDNSHost, - const stcAnswerAccessor& p_MDNSAnswerAccessor, - typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item - bool p_bSetContent)>; // true: Answer component set, false: component deleted - // LEGACY - using MDNSQueryCallbackFn1 = std::function<void(MDNSResponder* p_pMDNSResponder, - const stcAnswerAccessor& p_MDNSAnswerAccessor, - typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item - bool p_bSetContent)>; // true: Answer component set, false: component deleted - using MDNSQueryCallbackFn2 = std::function<void(const stcAnswerAccessor& p_MDNSAnswerAccessor, - typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item - bool p_bSetContent)>; // true: Answer component set, false: component deleted - //using MDNSServiceInfo = stcAnswerAccessor; // for compatibility with V1 - - // Install a dynamic service/host query. For every received answer (part) the given callback - // function is called. The query will be updated every time, the TTL for an answer - // has timed-out. - // The answers can also be retrieved by calling - // - answerCount service/host (for host queries, this should never be >1) - // - answerServiceDomain service - // - hasAnswerHostDomain/answerHostDomain service/host - // - hasAnswerIPv4Address/answerIPv4Address service/host - // - hasAnswerIPv6Address/answerIPv6Address service/host - // - hasAnswerPort/answerPort service - // - hasAnswerTxts/answerTxts service - hMDNSQuery installServiceQuery(const hMDNSHost p_hMDNSHost, - const char* p_pcService, - const char* p_pcProtocol, - MDNSQueryCallbackFn p_fnCallback); - hMDNSQuery installHostQuery(const hMDNSHost p_hMDNSHost, - const char* p_pcHostName, - MDNSQueryCallbackFn p_fnCallback); - - hMDNSQuery installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - MDNSQueryCallbackFn1 p_fnCallback); - hMDNSQuery installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - MDNSQueryCallbackFn2 p_fnCallback); - - hMDNSQuery installHostQuery(const char* p_pcHostName, - MDNSQueryCallbackFn1 p_fnCallback); - hMDNSQuery installHostQuery(const char* p_pcHostName, - MDNSQueryCallbackFn2 p_fnCallback); - // Remove a dynamic service query - bool removeDynamicQuery(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hMDNSQuery); - bool removeDynamicQuery(const hMDNSQuery p_hQuery); - - /** - clsMDNSAnswerAccessorVector - */ - using clsMDNSAnswerAccessorVector = std::vector<stcAnswerAccessor>; - - clsMDNSAnswerAccessorVector answerAccessors(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hMDNSQuery); - clsMDNSAnswerAccessorVector answerAccessors(const hMDNSQuery p_hQuery); - - uint32_t answerCount(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hMDNSQuery); - uint32_t answerCount(const hMDNSQuery p_hQuery); - - bool hasAnswerServiceDomain(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerServiceDomain(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - const char* answerServiceDomain(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - const char* answerServiceDomain(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerHostDomain(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerHostDomain(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - const char* answerHostDomain(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - const char* answerHostDomain(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); -#ifdef MDNS_IPV4_SUPPORT - bool hasAnswerIPv4Address(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIPv4AddressCount(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIPv4Address(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); - bool hasAnswerIPv4Address(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIPv4AddressCount(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIPv4Address(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); -#endif -#ifdef MDNS_IPV6_SUPPORT - bool hasAnswerIPv6Address(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIPv6AddressCount(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIPv6Address(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); - bool hasAnswerIPv6Address(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIPv6AddressCount(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIPv6Address(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); -#endif - bool hasAnswerPort(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerPort(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - uint16_t answerPort(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - /* uint16_t answerPort(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex);*/ - bool hasAnswerTxts(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerTxts(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - // Get the TXT items as a ';'-separated string - const char* answerTxts(const hMDNSHost p_hMDNSHost, - const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - const char* answerTxts(const hMDNSQuery p_hQuery, - const uint32_t p_u32AnswerIndex); - - // Set a callback function for host probe results - // The callback function is called, when the probeing for the host domain - // succeededs or fails. - // In case of failure, the failed domain name should be changed. - bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn p_fnCallback); - /* LEGACY 2 */ - using MDNSHostProbeResultCallbackFn1 = std::function<void(MDNSResponder* p_pMDNSResponder, - const char* p_pcDomainName, - bool p_bProbeResult)>; - using MDNSHostProbeResultCallbackFn2 = std::function<void(const char* p_pcDomainName, - bool p_bProbeResult)>; - - bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn1 p_fnCallback); - bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn2 p_fnCallback); - - /** - MDNSServiceProbeResultCallbackFn - Callback function for service domain probe results - */ - using MDNSServiceProbeResultCallbackFn = std::function<void(MDNSResponder* p_pMDNSResponder, - const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcServiceName, - bool p_bProbeResult)>; - // Set a service specific probe result callcack - bool setServiceProbeResultCallback(const hMDNSService p_hMDNSService, - MDNSServiceProbeResultCallbackFn p_fnCallback); - - bool setServiceProbeResultCallback(const hMDNSService p_hMDNSService, - MDNSServiceProbeResultCallbackFn1 p_fnCallback); - bool setServiceProbeResultCallback(const hMDNSService p_hMDNSService, - MDNSServiceProbeResultCallbackFn2 p_fnCallback); - - // Application should call this whenever AP is configured/disabled - bool notifyNetIfChange(netif* p_pNetIf); - - // 'update' should be called in every 'loop' to run the MDNS processing - bool update(const hMDNSHost p_hMDNSHost); - bool update(void); - - // 'announce' can be called every time, the configuration of some service - // changes. Mainly, this would be changed content of TXT items. - bool announce(const hMDNSHost p_hMDNSHost); - bool announce(void); - - // Enable OTA update - hMDNSService enableArduino(const hMDNSHost p_hMDNSHost, - uint16_t p_u16Port, - bool p_bAuthUpload = false); - hMDNSService enableArduino(uint16_t p_u16Port, - bool p_bAuthUpload = false); - - // Domain name helper - static bool indexDomain(char*& p_rpcDomain, - const char* p_pcDivider = "-", - const char* p_pcDefaultDomain = 0); - // Host name helper - static bool setNetIfHostName(netif* p_pNetIf, - const char* p_pcHostName); -}; -#endif - -} // namespace MDNSImplementation - -} // namespace esp8266 - -#endif // LEAMDNS2_H - - - diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp new file mode 100644 index 0000000000..dd46d09ad3 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -0,0 +1,1428 @@ +/* + LEAmDNS2Host.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#include "LEAmDNS2Host.h" + +#ifdef MDNS_IPV4_SUPPORT +#include <lwip/igmp.h> +#endif +#ifdef MDNS_IPV6_SUPPORT +#include <lwip/mld6.h> +#endif + + +namespace // anonymous +{ + +/* + strrstr (static) + + Backwards search for p_pcPattern in p_pcString + Based on: https://stackoverflow.com/a/1634398/2778898 + +*/ +const char* strrstr(const char*__restrict p_pcString, + const char*__restrict p_pcPattern) +{ + const char* pcResult = 0; + + size_t stStringLength = (p_pcString ? strlen(p_pcString) : 0); + size_t stPatternLength = (p_pcPattern ? strlen(p_pcPattern) : 0); + + if ((stStringLength) && + (stPatternLength) && + (stPatternLength <= stStringLength)) + { + // Pattern is shorter or has the same length than the string + for (const char* s = (p_pcString + stStringLength - stPatternLength); s >= p_pcString; --s) + { + if (0 == strncmp(s, p_pcPattern, stPatternLength)) + { + pcResult = s; + break; + } + } + } + return pcResult; +} + + +} // anonymous + + +namespace esp8266 +{ + + +namespace experimental +{ + + +/* + + HELPERS + +*/ + +/* + clsLEAmDNS2_Host::indexDomainName (static) + + Increments the given domain 'p_pcDomainName' by appending a delimiter and an index number. + + If the given domain name already has a numeric index (after the given delimiter), this index + is incremented. If not, the delimiter and index '2' is added. + + If 'p_pcDomainName' is empty (==0), the given default name 'p_pcDefaultDomainName' is used, + if no default is given, 'ESP8266' is used. + +*/ +//static +const char* clsLEAMDNSHost::indexDomainName(const char* p_pcDomainName, + const char* p_pcDivider /*= "-"*/, + const char* p_pcDefaultDomainName /*= 0*/) +{ + static char acResultDomainName[clsConsts::stDomainLabelMaxLength]; + *acResultDomainName = 0; + + // Ensure a divider exists; use '-' as default + const char* pcDivider = (p_pcDivider ? : "-"); + + if (p_pcDomainName) + { + // Given domain + const char* pFoundDivider = strrstr(p_pcDomainName, pcDivider); + if (pFoundDivider) // maybe already extended + { + char* pEnd = 0; + unsigned long ulIndex = strtoul((pFoundDivider + strlen(pcDivider)), &pEnd, 10); + if ((ulIndex) && + ((pEnd - p_pcDomainName) == (ptrdiff_t)strlen(p_pcDomainName)) && + (!*pEnd)) + { + // Valid (old) index found + char acIndexBuffer[16]; + sprintf(acIndexBuffer, "%lu", (++ulIndex)); + //size_t stLength = ((pFoundDivider - p_pcDomainName + strlen(pcDivider)) + strlen(acIndexBuffer) + 1); + + memcpy(acResultDomainName, p_pcDomainName, (pFoundDivider - p_pcDomainName + strlen(pcDivider))); + acResultDomainName[pFoundDivider - p_pcDomainName + strlen(pcDivider)] = 0; + strcat(acResultDomainName, acIndexBuffer); + } + else + { + pFoundDivider = 0; // Flag the need to (base) extend the hostname + } + } + + if (!pFoundDivider) + { + // not yet extended (or failed to increment extension) -> start indexing + //size_t stLength = strlen(p_pcDomainName) + (strlen(pcDivider) + 1 + 1); // Name + Divider + '2' + '\0' + sprintf(acResultDomainName, "%s%s2", p_pcDomainName, pcDivider); + } + } + else + { + // No given domain, use base or default + const char* cpcDefaultName = (p_pcDefaultDomainName ? : "ESP8266"); + size_t stLength = strlen(cpcDefaultName) + 1; // '\0' + strncpy(acResultDomainName, cpcDefaultName, stLength); + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[mDNS] indexDomainName: From '%s' to '%s'\n"), (p_pcDomainName ? : ""), acResultDomainName);); + return acResultDomainName; +} + + +/* + clsLEAmDNS2_Host::setStationHostName (static) + + Sets the staion hostname + +*/ +// static +bool clsLEAMDNSHost::setNetIfHostName(netif* p_pNetIf, + const char* p_pcHostName) +{ + if ((p_pNetIf) && + (p_pcHostName)) + { + netif_set_hostname(p_pNetIf, (char*)p_pcHostName); // LWIP 1.x forces 'char*' instead of 'const char*' + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[mDNS] setNetIfHostName host name: %s!\n"), p_pcHostName);); + } + return true; +} + + +/** + clsLEAmDNS2_Host::sm_pBackbone + +*/ +clsLEAMDNSHost::clsBackbone* clsLEAMDNSHost::clsBackbone::sm_pBackbone = 0; + +/** + Consts::... + +*/ +const char* clsLEAMDNSHost::clsConsts::pcLocal = "local"; +const char* clsLEAMDNSHost::clsConsts::pcServices = "services"; +const char* clsLEAMDNSHost::clsConsts::pcDNSSD = "dns-sd"; +const char* clsLEAMDNSHost::clsConsts::pcUDP = "udp"; +//const char* clsLEAMDNSHost::clsConsts::pcTCP = "tcp"; + +#ifdef MDNS_IPV4_SUPPORT +const char* clsLEAMDNSHost::clsConsts::pcReverseIPv4Domain = "in-addr"; +#endif +#ifdef MDNS_IPV6_SUPPORT +const char* clsLEAMDNSHost::clsConsts::pcReverseIPv6Domain = "ip6"; +#endif +const char* clsLEAMDNSHost::clsConsts::pcReverseTopDomain = "arpa"; + + +/* + clsLEAmDNS2_Host::clsLEAmDNS2_Host constructor + +*/ +clsLEAMDNSHost::clsLEAMDNSHost(void) + : m_pNetIf(0), + m_NetIfState(static_cast<typeNetIfState>(enuNetIfState::None)), + m_pUDPContext(0), + m_pcHostName(0), + m_pcDefaultInstanceName(0), + m_ProbeInformation() +{ +} + +/* + clsLEAmDNS2_Host::~clsLEAmDNS2_Host destructor + +*/ +clsLEAMDNSHost::~clsLEAMDNSHost(void) +{ + close(); +} + +/* + + INIT + +*/ + +/* + clsLEAmDNS2_Host::begin (hostname, netif, probe_callback) + + Creates a new mDNS host (adding the netif to the multicast groups), + sets up the instance data (hostname, ...) and starts the probing process + +*/ +bool clsLEAMDNSHost::begin(const char* p_pcHostName, + netif* p_pNetIf, + clsLEAMDNSHost::fnProbeResultCallback p_fnCallback /*= 0*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s, netif: %u)\n"), _DH(), (p_pcHostName ? : "_"), (p_pNetIf ? netif_get_index(p_pNetIf) : 0));); + + bool bResult = false; + + if (!((bResult = ((setHostName(p_pcHostName)) && + ((m_pNetIf = p_pNetIf)) && + (_joinMulticastGroups()) && + (p_fnCallback ? setProbeResultCallback(p_fnCallback) : true) && + ((m_pUDPContext = _allocBackbone())) && + (restart()))))) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s begin: FAILED for '%s'!\n"), _DH(), (p_pcHostName ? : "-"));); + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin: %s to init with hostname %s!\n"), _DH(), (bResult ? "Succeeded" : "FAILED"), (p_pcHostName ? : "-"));); + return bResult; +} + +/* + clsLEAmDNS2_Host::begin (hostname, probe_callback) + +*/ +bool clsLEAMDNSHost::begin(const char* p_pcHostName, + clsLEAMDNSHost::fnProbeResultCallback p_fnCallback /*= 0*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s)\n"), _DH(), (p_pcHostName ? : "_"));); + + return begin(p_pcHostName, (WiFiMode_t)wifi_get_opmode(), p_fnCallback); +} + +/* + clsLEAmDNS2_Host::begin (hostname, WiFiMode, probe_callback) + +*/ +bool clsLEAMDNSHost::begin(const char* p_pcHostName, + WiFiMode_t p_WiFiMode, + clsLEAMDNSHost::fnProbeResultCallback p_fnCallback /*= 0*/) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s, opmode: %u)\n"), _DH(), (p_pcHostName ? : "_"), (uint32_t)p_WiFiMode);); + + bool bResult = false; + + if (p_WiFiMode == WIFI_STA) + { + bResult = begin(p_pcHostName, netif_get_by_index(WIFI_STA), p_fnCallback); + } + else if (p_WiFiMode == WIFI_AP) + { + bResult = begin(p_pcHostName, netif_get_by_index(WIFI_AP), p_fnCallback); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s begin: FAILED for WiFi mode '%u'! Only 'WIFI_STA' or 'WIFI_AP' is allowed (HostName: %s)!\n"), _DH(), (bResult ? "Succeeded" : "FAILED"), p_WiFiMode, (p_pcHostName ? : "-"));); + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin: %s for WiFi mode '%u' (HostName: %s)!\n"), _DH(), (bResult ? "Succeeded" : "FAILED"), p_WiFiMode, (p_pcHostName ? : "-"));); + return bResult; +} + +/* + clsLEAmDNS2_Host::close + +*/ +bool clsLEAMDNSHost::close(void) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s close\n"), _DH());); + + m_pUDPContext = 0; + return ((_leaveMulticastGroups()) && + (_releaseBackbone())); +} + + +/* + + HOSTNAME + +*/ + +/* + clsLEAmDNS2_Host::setHostName + +*/ +bool clsLEAMDNSHost::setHostName(const char* p_pcHostName) +{ + bool bResult; + if ((bResult = _allocHostName(p_pcHostName))) + { + m_ProbeInformation.clear(false); + m_ProbeInformation.m_ProbingStatus = clsProbeInformation_Base::enuProbingStatus::ReadyToStart; + + // Replace 'auto-set' service names + for (clsService* pService : m_Services) + { + if ((pService->m_bAutoName) && + (!m_pcDefaultInstanceName)) + { + if (!((bResult = pService->setInstanceName(p_pcHostName)))) + { + break; + } + } + } + } + return bResult; +} + +/* + clsLEAmDNS2_Host::indexHostName + +*/ +bool clsLEAMDNSHost::indexHostName(void) +{ + return setHostName(clsLEAMDNSHost::indexDomainName(hostName(), "-", 0)); +} + +/* + clsLEAmDNS2_Host::hostName + +*/ +const char* clsLEAMDNSHost::hostName(void) const +{ + return m_pcHostName; +} + +/* + clsLEAmDNS2_Host::setProbeResultCallback + +*/ +bool clsLEAMDNSHost::setProbeResultCallback(clsLEAMDNSHost::fnProbeResultCallback p_fnCallback) +{ + m_ProbeInformation.m_fnProbeResultCallback = p_fnCallback; + return true; +} + +/* + clsLEAmDNS2_Host::probeStatus + +*/ +bool clsLEAMDNSHost::probeStatus(void) const +{ + return (clsProbeInformation_Base::enuProbingStatus::DoneFinally == m_ProbeInformation.m_ProbingStatus); +} + + +/* + + SERVICES + +*/ + +/* + clsLEAmDNS2_Host::setDefaultInstanceName + +*/ +bool clsLEAMDNSHost::setDefaultInstanceName(const char* p_pcDefaultInstanceName) +{ + bool bResult; + if ((bResult = _allocDefaultInstanceName(p_pcDefaultInstanceName))) + { + // Replace 'auto-set' service names + for (clsService* pService : m_Services) + { + if (pService->m_bAutoName) + { + if (!((bResult = pService->setInstanceName(p_pcDefaultInstanceName)))) + { + break; + } + } + } + } + return bResult; +} + +/* + clsLEAmDNS2_Host::defaultInstanceName + +*/ +const char* clsLEAMDNSHost::defaultInstanceName(void) const +{ + return m_pcDefaultInstanceName; +} + +/* + clsLEAmDNS2_Host::addService + +*/ +clsLEAMDNSHost::clsService* clsLEAMDNSHost::addService(const char* p_pcInstanceName, + const char* p_pcType, + const char* p_pcProtocol, + uint16_t p_u16Port, + clsLEAMDNSHost::clsService::fnProbeResultCallback p_fnCallback /*= 0*/) +{ + clsService* pService = 0; + + if (!((pService = findService(_instanceName(p_pcInstanceName), p_pcType, p_pcProtocol, p_u16Port)))) + { + // Not already used + if ((pService = new clsService)) + { + if ((pService->setInstanceName(_instanceName(p_pcInstanceName))) && + (pService->setType(p_pcType)) && + (pService->setProtocol(p_pcProtocol)) && + (pService->setPort(p_u16Port)) && + (p_fnCallback ? pService->setProbeResultCallback(p_fnCallback) : true)) + { + m_Services.push_back(pService); + } + else + { + delete pService; + pService = 0; + } + } + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s addService: %s to add service '%s.%s.%s.local'!\n"), _DH(pService), (pService ? "Succeeded" : "FAILED"), _instanceName(p_pcInstanceName, false), (p_pcType ? : ""), (p_pcProtocol ? : ""));); + DEBUG_EX_ERR(if (!pService) DEBUG_OUTPUT.printf_P(PSTR("%s addService: FAILED to add service '%s.%s.%s.local'!\n"), _DH(pService), _instanceName(p_pcInstanceName, false), (p_pcType ? : ""), (p_pcProtocol ? : ""));); + return pService; +} + +/* + clsLEAmDNS2_Host::removeService + +*/ +bool clsLEAMDNSHost::removeService(clsLEAMDNSHost::clsService* p_pService) +{ + bool bResult = false; + + if ((bResult = ((p_pService) && + (m_Services.end() != std::find(m_Services.begin(), m_Services.end(), p_pService)) && + (_announceService(*p_pService, false))))) + { + m_Services.remove(p_pService); + delete p_pService; + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _removeService: FAILED!\n"), _DH(p_pService));); + return bResult; +} + +/* + clsLEAmDNS2_Host::findService (const) + +*/ +const clsLEAMDNSHost::clsService* clsLEAMDNSHost::findService(const char* p_pcInstanceName, + const char* p_pcType, + const char* p_pcProtocol, + uint16_t p_u16Port/*= (uint16_t)(-1)*/) const +{ + clsService* pFoundService = 0; + + for (clsService* pService : m_Services) + { + if ((0 == strcmp(pService->instanceName(), _instanceName(p_pcInstanceName))) && + (0 == strcmp(pService->type(), p_pcType)) && + (0 == strcmp(pService->protocol(), p_pcProtocol)) && + (((uint16_t)(-1) == p_u16Port) || + (pService->port() == p_u16Port))) + { + pFoundService = pService; + break; + } + } + return pFoundService; +} + +/* + clsLEAmDNS2_Host::findService + +*/ +clsLEAMDNSHost::clsService* clsLEAMDNSHost::findService(const char* p_pcInstanceName, + const char* p_pcType, + const char* p_pcProtocol, + uint16_t p_u16Port /*= (uint16_t)(-1)*/) +{ + return (clsService*)((const clsLEAMDNSHost*)this)->findService(p_pcInstanceName, p_pcType, p_pcProtocol, p_u16Port); +} + +/* + clsLEAMDNSHost::services + +*/ +const clsLEAMDNSHost::clsService::list& clsLEAMDNSHost::services(void) const +{ + return m_Services; +} + + +/* + + QUERIES + +*/ + +/* + clsLEAmDNS2_Host::queryService + +*/ +clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryService(const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService '_%s._%s.local'\n"), _DH(), p_pcService, p_pcProtocol);); + + clsQuery* pQuery = 0; + if ((p_pcService) && (*p_pcService) && + (p_pcProtocol) && (*p_pcProtocol) && + (p_u16Timeout) && + ((pQuery = _allocQuery(clsQuery::enuQueryType::Service))) && + (_buildDomainForService(p_pcService, p_pcProtocol, pQuery->m_Domain))) + { + if ((_removeLegacyQuery()) && + ((pQuery->m_bStaticQuery = true)) && + (_sendQuery(*pQuery))) + { + // Wait for answers to arrive + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); + delay(p_u16Timeout); + + // All answers should have arrived by now -> stop adding new answers + pQuery->m_bAwaitingAnswers = false; + } + else + { + // FAILED to send query + _removeQuery(pQuery); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: INVALID input data!\n"), _DH());); + } + return ((pQuery) + ? pQuery->answerAccessors() + : clsQuery::clsAnswerAccessor::vector()); +} + +/* + clsLEAmDNS2_Host::queryHost + +*/ +clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryHost(const char* p_pcHostName, + const uint16_t p_u16Timeout) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost '%s.local'\n"), _DH(), p_pcHostName);); + + clsQuery* pQuery = 0; + if ((p_pcHostName) && (*p_pcHostName) && + (p_u16Timeout) && + ((pQuery = _allocQuery(clsQuery::enuQueryType::Host))) && + (_buildDomainForHost(p_pcHostName, pQuery->m_Domain))) + { + if ((_removeLegacyQuery()) && + ((pQuery->m_bStaticQuery = true)) && + (_sendQuery(*pQuery))) + { + // Wait for answers to arrive + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); + delay(p_u16Timeout); + + // All answers should have arrived by now -> stop adding new answers + pQuery->m_bAwaitingAnswers = false; + } + else + { + // FAILED to send query + _removeQuery(pQuery); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: INVALID input data!\n"), _DH());); + } + return ((pQuery) + ? pQuery->answerAccessors() + : clsQuery::clsAnswerAccessor::vector()); +} + +/* + clsLEAmDNS2_Host::removeQuery + +*/ +bool clsLEAMDNSHost::removeQuery(void) +{ + return _removeLegacyQuery(); +} + +/* + clsLEAmDNS2_Host::hasQuery + +*/ +bool clsLEAMDNSHost::hasQuery(void) +{ + return (0 != _findLegacyQuery()); +} + +/* + clsLEAmDNS2_Host::getQuery + +*/ +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::getQuery(void) +{ + return _findLegacyQuery(); +} + +/* + clsLEAmDNS2_Host::installServiceQuery (answer) + +*/ +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcService, + const char* p_pcProtocol, + clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) +{ + clsQuery* pQuery = 0; + if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) + { + pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; + } + return pQuery; +} + +/* + clsLEAmDNS2_Host::installServiceQuery (accessor) + +*/ +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcService, + const char* p_pcProtocol, + clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) +{ + clsQuery* pQuery = 0; + if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) + { + pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; + } + return pQuery; +} + +/* + clsLEAmDNS2_Host::installHostQuery (answer) +*/ +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, + clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) +{ + clsQuery* pQuery = 0; + if ((p_pcHostName) && (*p_pcHostName)) + { + clsRRDomain domain; + if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) + ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) + : 0))) + { + pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; + } + } + return pQuery; +} + +/* + clsLEAmDNS2_Host::installHostQuery (accessor) +*/ +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, + clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) +{ + clsQuery* pQuery = 0; + if ((p_pcHostName) && (*p_pcHostName)) + { + clsRRDomain domain; + if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) + ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) + : 0))) + { + pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; + } + } + return pQuery; +} + +/* + clsLEAmDNS2_Host::removeQuery +*/ +bool clsLEAMDNSHost::removeQuery(clsLEAMDNSHost::clsQuery* p_pMDNSQuery) +{ + bool bResult = ((p_pMDNSQuery) && + (_removeQuery(p_pMDNSQuery))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeQuery: FAILED!\n"), _DH());); + return bResult; +} + + +/* + PROCESSING +*/ + +/* + clsLEAmDNS2_Host::update +*/ +bool clsLEAMDNSHost::update(void) +{ + bool bResult = false; + + //if (clsBackbone::sm_pBackbone->setDelayUDPProcessing(true)) + //{ + bResult = ((_checkNetIfState()) && // Any changes in the netif state? + (_updateProbeStatus()) && // Probing and announcing + (_checkQueryCache())); + + // clsBackbone::sm_pBackbone->setDelayUDPProcessing(false); + //} + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s update: FAILED (Not connected?)!\n"), _DH());); + + return bResult; +} + +/* + clsLEAmDNS2_Host::announce +*/ +bool clsLEAMDNSHost::announce(bool p_bAnnounce /*= true*/, + bool p_bIncludeServices /*= true*/) +{ + return _announce(p_bAnnounce, p_bIncludeServices); +} + +/* + clsLEAmDNS2_Host::announceService +*/ +bool clsLEAMDNSHost::announceService(clsService* p_pService, + bool p_bAnnounce /*= true*/) +{ + return _announceService(*p_pService, p_bAnnounce); +} + +/* + clsLEAmDNS2_Host::restart +*/ +bool clsLEAMDNSHost::restart(void) +{ + return (_resetProbeStatus(true)); // Stop and restart probing +} + + + +/* + P R O T E C T E D +*/ + +/* + + BACKBONE + +*/ + +/* + clsLEAmDNS2_Host::_allocBackbone + +*/ +UdpContext* clsLEAMDNSHost::_allocBackbone(void) +{ + UdpContext* pUDPContext = 0; + + if (!clsBackbone::sm_pBackbone) + { + // Not yet created + clsBackbone::sm_pBackbone = new clsBackbone; + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocBackbone: Created backbone.\n"), _DH());); + + if ((clsBackbone::sm_pBackbone) && + (!clsBackbone::sm_pBackbone->init())) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _allocBackbone: FAILED to init backbone!\n"), _DH());); + + delete clsBackbone::sm_pBackbone; + clsBackbone::sm_pBackbone = 0; + } + } + if (clsBackbone::sm_pBackbone) + { + pUDPContext = clsBackbone::sm_pBackbone->addHost(this); + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocBackbone: %s to add host to backbone.\n"), _DH(), (pUDPContext ? "Succeeded" : "FAILED"));); + return pUDPContext; +} + +/* + clsLEAmDNS2_Host::_releaseBackbone + +*/ +bool clsLEAMDNSHost::_releaseBackbone(void) +{ + bool bResult = false; + + if ((clsBackbone::sm_pBackbone) && + ((bResult = clsBackbone::sm_pBackbone->removeHost(this))) && + (0 == clsBackbone::sm_pBackbone->hostCount())) + { + delete clsBackbone::sm_pBackbone; + clsBackbone::sm_pBackbone = 0; + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _releaseBackbone: Released backbone."), _DH());); + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _releaseBackbone: %s to remove host from backbone."), _DH(), (bResult ? "Succeeded" : "FAILED"));); + return bResult; +} + + +/* + + MULTICAST GROUPS + +*/ + +/* + clsLEAmDNS2_Host::_joinMulticastGroups +*/ +bool clsLEAMDNSHost::_joinMulticastGroups(void) +{ + bool bResult = false; + + // Join multicast group(s) + if (m_pNetIf) + { + bResult = true; + +#ifdef MDNS_IPV4_SUPPORT + ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; + if (!(m_pNetIf->flags & NETIF_FLAG_IGMP)) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: Setting flag: flags & NETIF_FLAG_IGMP\n"), _DH());); + m_pNetIf->flags |= NETIF_FLAG_IGMP; + + if (ERR_OK != igmp_start(m_pNetIf)) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: igmp_start FAILED!\n"), _DH());); + } + } + + bResult = ((bResult) && +#if LWIP_VERSION_MAJOR == 1 + (ERR_OK == igmp_joingroup(ip_2_ip4(&m_pNetIf->ip_addr), ip_2_ip4(&multicast_addr_V4)))); +#else + (ERR_OK == igmp_joingroup_netif(m_pNetIf, ip_2_ip4(&multicast_addr_V4)))); +#endif + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: igmp_joingroup_netif(%s) FAILED!\n"), _DH(), IPAddress(multicast_addr_V4).toString().c_str());); +#endif + +#ifdef MDNS_IPV6_SUPPORT + ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; + bResult = ((bResult) && + (ERR_OK == mld6_joingroup_netif(m_pNetIf, ip_2_ip6(&multicast_addr_V6)))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: mld6_joingroup_netif FAILED!\n"), _DH());); +#endif + } + return bResult; +} + +/* + clsLEAmDNS2_Host::_leaveMulticastGroups +*/ +bool clsLEAMDNSHost::_leaveMulticastGroups(void) +{ + bool bResult = false; + + if (m_pNetIf) + { + bResult = true; + /* _resetProbeStatus(false); // Stop probing + + _releaseQueries(); + _releaseServices(); + _releaseHostName();*/ + + // Leave multicast group(s) +#ifdef MDNS_IPV4_SUPPORT + ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; +#if LWIP_VERSION_MAJOR == 1 + if (ERR_OK != igmp_leavegroup(ip_2_ip4(&m_rNetIf.ip_addr), ip_2_ip4(&multicast_addr_V4))) +#else + if (ERR_OK != igmp_leavegroup_netif(m_pNetIf, ip_2_ip4(&multicast_addr_V4))) +#endif + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); + } +#endif +#ifdef MDNS_IPV6_SUPPORT + ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; + if (ERR_OK != mld6_leavegroup_netif(m_pNetIf, ip_2_ip6(&multicast_addr_V6)/*&(multicast_addr_V6.u_addr.ip6)*/)) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); + } +#endif + } + return bResult; +} + + +/* + NETIF +*/ + +/* + clsLEAmDNS2_Host::_getNetIfState + + Returns the current netif state. + +*/ +clsLEAMDNSHost::typeNetIfState clsLEAMDNSHost::_getNetIfState(void) const +{ + typeNetIfState curNetIfState = static_cast<typeNetIfState>(enuNetIfState::None); + + if ((m_pNetIf) && + (netif_is_up(m_pNetIf))) + { + curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::IsUp); + + // Check if netif link is up + if ((netif_is_link_up(m_pNetIf)) && + ((m_pNetIf != netif_get_by_index(WIFI_STA)) || + (STATION_GOT_IP == wifi_station_get_connect_status()))) + { + curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::LinkIsUp); + } + +#ifdef MDNS_IPV4_SUPPORT + // Check for IPv4 address + if (_getResponderIPAddress(enuIPProtocolType::V4).isSet()) + { + curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::IPv4); + } +#endif +#ifdef MDNS_IPV6_SUPPORT + // Check for IPv6 address + if (_getResponderIPAddress(enuIPProtocolType::V6).isSet()) + { + curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::IPv6); + } +#endif + } + return curNetIfState; +} + +/* + clsLEAmDNS2_Host::_checkNetIfState + + Checks the netif state. + If eg. a new address appears, the announcing is restarted. + +*/ +bool clsLEAMDNSHost::_checkNetIfState(void) +{ + typeNetIfState curNetIfState; + if (m_NetIfState != ((curNetIfState = _getNetIfState()))) + { + // Some state change happened + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: DID CHANGE NETIF STATE\n\n"), _DH());); + DEBUG_EX_INFO( + if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IsUp)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IsUp))) DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Netif is up: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IsUp)) ? "YES" : "NO")); + if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp))) DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Netif link is up: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp)) ? "YES" : "NO")); +#ifdef MDNS_IPV4_SUPPORT + if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4))) + { + DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv4 address is set: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4)) ? "YES" : "NO")); + if (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4)) + { + DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv4 address: %s\n"), _DH(), _getResponderIPAddress(enuIPProtocolType::V4).toString().c_str()); + } + } +#endif +#ifdef MDNS_IPV6_SUPPORT + if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6))) + { + DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv6 address is set: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6)) ? "YES" : "NO")); + if (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6)) + { + DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv6 address: %s\n"), _DH(), _getResponderIPAddress(enuIPProtocolType::V6).toString().c_str()); + } + } +#endif + ); + if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask))) + { + // Link came up or down + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Link state changed -> restarting\n"), _DH());); + restart(); + } + else if (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp)) + { + // Link is up (unchanged) + if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask))) + { + // IP state changed + // TODO: If just a new IP address was added, a simple re-announcement should be enough + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IP state changed -> restarting\n"), _DH());); + restart(); + } + } + /* if (enuProbingStatus::Done == m_HostProbeInformation.m_ProbingStatus) { + // Probing is done, prepare to (re)announce host + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Preparing to (re)announce host.\n"));); + //m_HostProbeInformation.m_ProbingStatus = enuProbingStatus::Done; + m_HostProbeInformation.m_u8SentCount = 0; + m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + }*/ + m_NetIfState = curNetIfState; + } + + bool bResult = ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask)) && // Continue if Link is UP + (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask))); // AND has any IP + DEBUG_EX_INFO(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Link is DOWN(%s) or NO IP address(%s)!\n"), _DH(), (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask) ? "NO" : "YES"), (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask) ? "NO" : "YES"));); + return bResult; +} + + +/* + PROCESSING +*/ + +/* + clsLEAmDNS2_Host::_processUDPInput +*/ +bool clsLEAMDNSHost::_processUDPInput(void) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput\n"), _DH());); + + bool bResult = _parseMessage(); + + /* bResult = ((_checkNetIfState()) && // Any changes in the netif state? + (_parseMessage()));*/ + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s processUDPInput: FAILED!\n"), _DH());); + + return bResult; +} + + +/* + DOMAIN NAMES +*/ + +/* + clsLEAmDNS2_Host::_allocDomainName +*/ +bool clsLEAMDNSHost::_allocDomainName(const char* p_pcNewDomainName, + char*& p_rpcDomainName) +{ + bool bResult = false; + + _releaseDomainName(p_rpcDomainName); + + size_t stLength = 0; + if ((p_pcNewDomainName) && + (clsConsts::stDomainLabelMaxLength >= (stLength = strlen(p_pcNewDomainName)))) // char max size for a single label + { + // Copy in hostname characters as lowercase + if ((bResult = (0 != (p_rpcDomainName = new char[stLength + 1])))) + { +#ifdef MDNS_FORCE_LOWERCASE_HOSTNAME + size_t i = 0; + for (; i < stLength; ++i) + { + p_rpcDomainName[i] = (isupper(p_pcNewDomainName[i]) ? tolower(p_pcNewDomainName[i]) : p_pcNewDomainName[i]); + } + p_rpcDomainName[i] = 0; +#else + strncpy(p_rpcDomainName, p_pcNewDomainName, (stLength + 1)); +#endif + } + } + return bResult; +} + +/* + clsLEAmDNS2_Host::_releaseDomainName +*/ +bool clsLEAMDNSHost::_releaseDomainName(char*& p_rpcDomainName) +{ + bool bResult; + if ((bResult = (0 != p_rpcDomainName))) + { + delete[] p_rpcDomainName; + p_rpcDomainName = 0; + } + return bResult; +} + +/* + clsLEAmDNS2_Host::_allocHostName +*/ +bool clsLEAMDNSHost::_allocHostName(const char* p_pcHostName) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocHostName (%s)\n"), _DH(), p_pcHostName);); + return _allocDomainName(p_pcHostName, m_pcHostName); +} + +/* + clsLEAmDNS2_Host::_releaseHostName +*/ +bool clsLEAMDNSHost::_releaseHostName(void) +{ + return _releaseDomainName(m_pcHostName); +} + +/* + clsLEAmDNS2_Host::_allocDefaultInstanceName +*/ +bool clsLEAMDNSHost::_allocDefaultInstanceName(const char* p_pcDefaultInstanceName) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocDefaultInstanceName (%s)\n"), _DH(), p_pcDefaultInstanceName);); + return _allocDomainName(p_pcDefaultInstanceName, m_pcDefaultInstanceName); +} + +/* + clsLEAmDNS2_Host::_releaseDefaultInstanceName +*/ +bool clsLEAMDNSHost::_releaseDefaultInstanceName(void) +{ + return _releaseDomainName(m_pcDefaultInstanceName); +} + +/* + clsLEAmDNS2_Host::_instanceName +*/ +const char* clsLEAMDNSHost::_instanceName(const char* p_pcInstanceName, + bool p_bReturnZero /*= true*/) const +{ + return (p_pcInstanceName ? : (m_pcDefaultInstanceName ? : (m_pcHostName ? : (p_bReturnZero ? 0 : "-")))); +} + + +/* + SERVICE TXT +*/ + +/* + clsLEAmDNS2_Host::_collectServiceTxts +*/ +bool clsLEAMDNSHost::_collectServiceTxts(clsLEAMDNSHost::clsService& p_rService) +{ + if (p_rService.m_fnTxtCallback) + { + p_rService.m_fnTxtCallback(p_rService); + } + return true; +} + +/* + clsLEAmDNS2_Host::_releaseTempServiceTxts +*/ +bool clsLEAMDNSHost::_releaseTempServiceTxts(clsLEAMDNSHost::clsService& p_rService) +{ + return (p_rService.m_Txts.removeTempTxts()); +} + + +/* + + QUERIES + +*/ + +/* + MDNSResponder::_allocQuery + +*/ +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_allocQuery(clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType) +{ + clsQuery* pQuery = new clsQuery(p_QueryType); + if (pQuery) + { + // Link to query list + m_Queries.push_back(pQuery); + } + return pQuery; +} + +/* + MDNSResponder:clsHost:::_removeQuery + +*/ +bool clsLEAMDNSHost::_removeQuery(clsLEAMDNSHost::clsQuery* p_pQuery) +{ + bool bResult = false; + + clsQuery::list::iterator it(p_pQuery + ? std::find(m_Queries.begin(), m_Queries.end(), p_pQuery) + : m_Queries.end()); + if (m_Queries.end() != it) + { + m_Queries.erase(it); + delete p_pQuery; + + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _releaseQuery: INVALID query!"), _DH());); + } + return bResult; +} + +/* + clsLEAmDNS2_Host::_removeLegacyQuery + +*/ +bool clsLEAMDNSHost::_removeLegacyQuery(void) +{ + clsQuery* pLegacyQuery = 0; + return (((pLegacyQuery = _findLegacyQuery())) + ? _removeQuery(pLegacyQuery) + : true); +} + +/* + clsLEAmDNS2_Host::_findLegacyQuery + +*/ +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findLegacyQuery(void) +{ + clsQuery* pLegacyQuery = 0; + + for (clsQuery* pQuery : m_Queries) + { + if (pQuery->m_bStaticQuery) + { + pLegacyQuery = pQuery; + break; + } + } + return pLegacyQuery; +} + +/* + clsLEAmDNS2_Host::_releaseQueries + +*/ +bool clsLEAMDNSHost::_releaseQueries(void) +{ + for (clsQuery* pQuery : m_Queries) + { + delete pQuery; + } + m_Queries.clear(); + return true; +} + +/* + clsLEAmDNS2_Host::_findNextQueryByDomain + +*/ +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findNextQueryByDomain(const clsLEAMDNSHost::clsRRDomain& p_Domain, + const clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType, + const clsQuery* p_pPrevQuery) +{ + clsQuery* pMatchingQuery = 0; + + clsQuery::list::iterator it(m_Queries.begin()); + if (p_pPrevQuery) + { + if (m_Queries.end() != ((it = std::find(m_Queries.begin(), m_Queries.end(), p_pPrevQuery)))) + { // Found previous object + it++; + } + DEBUG_EX_ERR(else DEBUG_OUTPUT.printf_P(PSTR("%s _findNextQueryByDomain: FAILED to find 'previous' object!\n"), _DH());); // if not prev was found -> 'cancel' + } + + for (; it != m_Queries.end(); it++) + { + if (((clsQuery::enuQueryType::None == p_QueryType) || + ((*it)->m_QueryType == p_QueryType)) && + (p_Domain == (*it)->m_Domain)) + { + pMatchingQuery = *it; + break; + } + } + return pMatchingQuery; +} + +/* + clsLEAmDNS2_Host::_installServiceQuery + +*/ +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery(const char* p_pcService, + const char* p_pcProtocol) +{ + clsQuery* pMDNSQuery = 0; + + if ((p_pcService) && (*p_pcService) && + (p_pcProtocol) && (*p_pcProtocol) && + ((pMDNSQuery = _allocQuery(clsQuery::enuQueryType::Service))) && + (_buildDomainForService(p_pcService, p_pcProtocol, pMDNSQuery->m_Domain))) + { + pMDNSQuery->m_bStaticQuery = false; + + if (_sendQuery(*pMDNSQuery)) + { + pMDNSQuery->m_u8SentCount = 1; + pMDNSQuery->m_ResendTimeout.reset(clsConsts::u32DynamicQueryResendDelay); + } + else + { + _removeQuery(pMDNSQuery); + } + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _installServiceQuery: %s for '_%s._%s.local'!\n\n"), _DH(), (pMDNSQuery ? "Succeeded" : "FAILED"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); + DEBUG_EX_ERR(if (!pMDNSQuery) DEBUG_OUTPUT.printf_P(PSTR("%s _installServiceQuery: FAILED for '_%s._%s.local'!\n\n"), _DH(), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); + return pMDNSQuery; +} + +/* + clsLEAmDNS2_Host::_installDomainQuery +*/ +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installDomainQuery(clsLEAMDNSHost::clsRRDomain& p_Domain, + clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType) +{ + clsQuery* pQuery = 0; + + if ((pQuery = _allocQuery(p_QueryType))) + { + pQuery->m_Domain = p_Domain; + pQuery->m_bStaticQuery = false; + + if (_sendQuery(*pQuery)) + { + pQuery->m_u8SentCount = 1; + pQuery->m_ResendTimeout.reset(clsConsts::u32DynamicQueryResendDelay); + } + else + { + _removeQuery(pQuery); + } + } + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("%s _installDomainQuery: %s for "), (pQuery ? "Succeeded" : "FAILED"), _DH()); + _printRRDomain(p_Domain); + DEBUG_OUTPUT.println(); + ); + DEBUG_EX_ERR(if (!pQuery) +{ + DEBUG_OUTPUT.printf_P(PSTR("%s _installDomainQuery: FAILED for "), _DH()); + _printRRDomain(p_Domain); + DEBUG_OUTPUT.println(); + } + ); + return pQuery; +} + +/* + clsLEAmDNS2_Host::_hasQueriesWaitingForAnswers +*/ +bool clsLEAMDNSHost::_hasQueriesWaitingForAnswers(void) const +{ + bool bOpenQueries = false; + + for (const clsQuery* pQuery : m_Queries) + { + if (pQuery->m_bAwaitingAnswers) + { + bOpenQueries = true; + break; + } + } + return bOpenQueries; +} + +/* + clsLEAmDNS2_Host::_executeQueryCallback +*/ +bool clsLEAMDNSHost::_executeQueryCallback(const clsQuery& p_Query, + const clsQuery::clsAnswer& p_Answer, + clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, + bool p_bSetContent) +{ + if (p_Query.m_fnCallbackAnswer) + { + p_Query.m_fnCallbackAnswer(p_Query, p_Answer, p_QueryAnswerTypeFlags, p_bSetContent); + } + if (p_Query.m_fnCallbackAccessor) + { + p_Query.m_fnCallbackAccessor(p_Query, clsQuery::clsAnswerAccessor(&p_Answer), p_QueryAnswerTypeFlags, p_bSetContent); + } + return true; +} + + +} // namespace MDNSImplementation + + +} // namespace esp8266 + + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h new file mode 100644 index 0000000000..5a63d1f59e --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -0,0 +1,1658 @@ +/* + LEAmDNS2Host.h + (c) 2020, LaborEtArs + + Version 0.9 beta + + Some notes (from LaborEtArs, 2020): + + Supported mDNS features (in some cases somewhat limited): + - Announcing a DNS-SD service to interested observers, eg. a http server by announcing a esp8266._http._tcp.local. service + - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented + - Probing host and service domains for uniqueness in the local network + - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak) + - Announcing available services after successful probing + - Using fixed service TXT items or + - Using dynamic service TXT items for presented services (via callback) + - Remove services (and un-announcing them to the observers by sending goodbye-messages) + - Static queries for hosts or DNS-SD services (creating a fixed answer set after a certain timeout period) + - Dynamic queries for hosts or DNS-SD services with cached and updated answers and user notifications + + + Usage: + A LEAmDNS2Host is attached to an existing netif (Network Interface). + If more than one netif is used (eg. in WIFI_AP_STA mode) and mDNS support is needed, every used netif needs its own LEAmDNS2Host! + + For presenting services: + In 'setup()': + Create an clsLEAMDNSHost instance for every netif you plan to use. + Call 'begin' on every instance with the intended hostname and the associated netif (or WiFi mode, WIFI_STA). + The given hostname is the 'probed' for uniqueness in the netifs local link. If domain name conflicts occure, the host name + will be automatically changed until it is unique in the local link. + Optionally a callback can be registered in 'begin', to control the probing process manually. + Next you can register DNS-SD services with 'addService("MyESP", "http", "tcp", 5000)' + All added service domain names are also probed for uniqueness and updated if needed. + Optionally a 'probe result' callback can be given for every service in 'addService', too. + + Finally you can add service TXT items with 'pService->addServiceTxt("c#", "1")' or by installing a service TXT callback + using 'pService->setDynamicServiceTxtCallback()' and calling 'pService->addDynamicServiceTxt("c#", "1")' inside. + + In 'loop()': + Call 'update()' for every clsLEAmDNS_Host instance. + + For querying services/hosts: + Static: + Call 'queryService("http", "tcp")' or 'queryHost("esp8266")'; + You should call MDNS.removeQuery() sometimes later (when the answers are not needed anymore) + + Dynamic: + Install a dynamic service query by calling 'installService/HostQuery("http", "tcp", serviceQueryCallback);' + The callback is called for any change in the answer set. + Call 'MDNS.removeQuery(pQuery)' when the answers are not needed anymore + + + Reference: + Used mDNS messages: + A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 + AAAA (0x1C): eg. esp8266.local AAAA OP TTL 1234:5678::90 + PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local + PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local + PTR (0x0C, IPv4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local + PTR (0x0C, IPv6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local + SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local + TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 + NSEC (0x2F): eg. esp8266.local ... (DNSSEC) + + Some NOT used message types: + OPT (0x29): eDNS + + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#ifndef __LEAMDNS2HOST_H__ +#define __LEAMDNS2HOST_H__ + +#include <list> +#include <vector> +#include <map> +#include <functional> +#include <PolledTimeout.h> + +#include <lwip/netif.h> +#include <WiFiUdp.h> +#include <lwip/udp.h> +#include <debug.h> +#include <include/UdpContext.h> + +#include <ESP8266WiFi.h> + +#include "LEAmDNS2_lwIPdefs.h" + + +#define MDNS_IPV4_SUPPORT +#if LWIP_IPV6 +#define MDNS_IPV6_SUPPORT // If we've got IPv6 support, then we need IPv6 support :-) +#endif + +/* + LWIP_OPEN_SRC +*/ +#ifndef LWIP_OPEN_SRC +#define LWIP_OPEN_SRC +#endif + +/* + Enable class debug functions +*/ +#define ESP_8266_MDNS_INCLUDE +#define DEBUG_ESP_MDNS_RESPONDER + +/* + Enable/disable debug trace macros +*/ +#ifdef DEBUG_ESP_MDNS_RESPONDER +//#define DEBUG_ESP_MDNS_INFO +//#define DEBUG_ESP_MDNS_INFO2 +#define DEBUG_ESP_MDNS_ERR +#define DEBUG_ESP_MDNS_TX +#define DEBUG_ESP_MDNS_RX +#endif + +#ifdef DEBUG_ESP_MDNS_RESPONDER +#ifdef DEBUG_ESP_MDNS_INFO +#define DEBUG_EX_INFO(A) A +#else +#define DEBUG_EX_INFO(A) +#endif +#ifdef DEBUG_ESP_MDNS_INFO2 +#define DEBUG_EX_INFO2(A) A +#else +#define DEBUG_EX_INFO2(A) +#endif +#ifdef DEBUG_ESP_MDNS_ERR +#define DEBUG_EX_ERR(A) A +#else +#define DEBUG_EX_ERR(A) +#endif +#ifdef DEBUG_ESP_MDNS_TX +#define DEBUG_EX_TX(A) A +#else +#define DEBUG_EX_TX(A) +#endif +#ifdef DEBUG_ESP_MDNS_RX +#define DEBUG_EX_RX(A) A +#else +#define DEBUG_EX_RX(A) +#endif + +#ifdef DEBUG_ESP_PORT +#define DEBUG_OUTPUT DEBUG_ESP_PORT +#else +#define DEBUG_OUTPUT Serial +#endif +#else +#define DEBUG_EX_INFO(A) +#define DEBUG_EX_INFO2(A) +#define DEBUG_EX_ERR(A) +#define DEBUG_EX_TX(A) +#define DEBUG_EX_RX(A) +#endif + +/* + Enable/disable the usage of the F() macro in debug trace printf calls. + There needs to be an PGM comptible printf function to use this. + + USE_PGM_PRINTF and F +*/ +#define USE_PGM_PRINTF + +#ifdef USE_PGM_PRINTF +#else +#ifdef F +#undef F +#endif +#define F(A) A +#endif + + +namespace esp8266 +{ + + +namespace experimental +{ + + +/** + clsLEAMDNSHost +*/ +class clsLEAMDNSHost +{ +protected: + /* + clsConsts + */ + class clsConsts + { + public: +#ifdef MDNS_IPV4_SUPPORT + static const uint16_t u16IPv4Size = 4; // IPv4 address size in bytes +#endif +#ifdef MDNS_IPV6_SUPPORT + static const uint16_t u16IPv6Size = 16; // IPv6 address size in bytes +#endif + static const size_t stServiceTxtMaxLength = 1300; // Maximum length for all service txts for one service + static const size_t stDomainMaxLength = 256; // Maximum length for a full domain name eg. MyESP._http._tcp.local + static const size_t stDomainLabelMaxLength = 63; // Maximum length of on label in a domain name (length info fits into 6 bits) + static const size_t stServiceTypeMaxLength = 15; // Maximum length of a service name eg. http + static const size_t stServiceProtocolMaxLength = 3; // Maximum length of a service protocol name eg. tcp + + static const uint32_t u32LegacyTTL = 10; // Legacy DNS record TTL + static const uint32_t u32HostTTL = 120; // Host level records are set to 2min (120s) + static const uint32_t u32ServiceTTL = 4500; // Service level records are set to 75min (4500s) + + static const uint16_t u16SRVPriority = 0; // Default service priority and weight in SRV answers + static const uint16_t u16SRVWeight = 0; // + static const uint8_t u8DomainCompressMark = 0xC0; // Compressed labels are flaged by the two topmost bits of the length byte being set + static const uint8_t u8DomainMaxRedirections = 6; // Avoid endless recursion because of malformed compressed labels + + static const uint32_t u32ProbeDelay = 1000; // Default 250, but ESP is slow...; delay between and number of probes for host and service domains + static const uint32_t u32ProbeCount = 3; + static const uint32_t u32AnnounceDelay = 1000; // Delay between and number of announces for host and service domains + static const uint32_t u32AnnounceCount = 3; + static const uint32_t u32DynamicQueryResendDelay = 1000; // Delay between and number of queries; the delay is multiplied by the resent number in '_checkQueryCache' + + static const char* pcLocal; // "local"; + static const char* pcServices; // "services"; + static const char* pcDNSSD; // "dns-sd"; + static const char* pcUDP; // "udp"; + //static const char* pcTCP; // "tcp"; + +#ifdef MDNS_IPV4_SUPPORT + static const char* pcReverseIPv4Domain; // "in-addr"; +#endif +#ifdef MDNS_IPV6_SUPPORT + static const char* pcReverseIPv6Domain; // "ip6"; +#endif + static const char* pcReverseTopDomain; // "arpa"; + +#ifdef DNS_RRTYPE_NSEC + static const uint8_t u8DNS_RRTYPE_NSEC = DNS_RRTYPE_NSEC; +#else + static const uint8_t u8DNS_RRTYPE_NSEC = 0x2F; +#endif + static const uint32_t u32SendCooldown = 50; // Delay (ms) between to 'UDPContext->send()' calls + + }; + + /** + list + */ + using list = std::list<clsLEAMDNSHost*>; + + // File: ..._Backbone + /** + clsBackbone + */ + class clsBackbone + { + public: + static clsBackbone* sm_pBackbone; + clsBackbone(void); + ~clsBackbone(void); + + bool init(void); + + UdpContext* addHost(clsLEAMDNSHost* p_pHost); + bool removeHost(clsLEAMDNSHost* p_pHost); + size_t hostCount(void) const; + bool setDelayUDPProcessing(bool p_bDelayProcessing); + + protected: + UdpContext* m_pUDPContext; + bool m_bDelayUDPProcessing; + uint32_t m_u32DelayedDatagrams; + list m_HostList; + + bool _allocUDPContext(void); + bool _releaseUDPContext(void); + + bool _processUDPInput(void); + + const clsLEAMDNSHost* _findHost(netif* p_pNetIf) const; + clsLEAMDNSHost* _findHost(netif* p_pNetIf); + + const char* _DH(void) const; + }; + + + // File: ..._Host_Structs + /** + typeIPProtocolType & enuIPProtocolType + */ + using typeIPProtocolType = uint8_t; + enum class enuIPProtocolType : typeIPProtocolType + { +#ifdef MDNS_IPV4_SUPPORT + V4 = 0x01, +#endif +#ifdef MDNS_IPV6_SUPPORT + V6 = 0x02, +#endif + }; + + /** + typeNetIfState & enuNetIfState + */ + using typeNetIfState = uint8_t; + enum class enuNetIfState : typeNetIfState + { + None = 0x00, + + IsUp = 0x01, + UpMask = (IsUp), + + LinkIsUp = 0x02, + LinkMask = (LinkIsUp), + + IPv4 = 0x04, + IPv6 = 0x08, + IPMask = (IPv4 | IPv6), + }; + +public: + /** + clsServiceTxt + */ + class clsServiceTxt + { + public: + char* m_pcKey; + char* m_pcValue; + bool m_bTemp; + + clsServiceTxt(const char* p_pcKey = 0, + const char* p_pcValue = 0, + bool p_bTemp = false); + clsServiceTxt(const clsServiceTxt& p_Other); + ~clsServiceTxt(void); + + clsServiceTxt& operator=(const clsServiceTxt& p_Other); + bool clear(void); + + char* allocKey(size_t p_stLength); + bool setKey(const char* p_pcKey, + size_t p_stLength); + bool setKey(const char* p_pcKey); + bool releaseKey(void); + + char* allocValue(size_t p_stLength); + bool setValue(const char* p_pcValue, + size_t p_stLength); + bool setValue(const char* p_pcValue); + bool releaseValue(void); + + bool set(const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp = false); + + bool update(const char* p_pcValue); + + size_t length(void) const; + + /** + list + */ + using list = std::list<clsServiceTxt*>; + }; + + /** + clsServiceTxts + */ + class clsServiceTxts + { + public: + clsServiceTxt::list m_Txts; + char* m_pcCache; + + clsServiceTxts(void); + clsServiceTxts(const clsServiceTxts& p_Other); + ~clsServiceTxts(void); + + clsServiceTxts& operator=(const clsServiceTxts& p_Other); + + bool clear(void); + bool clearCache(void); + + bool add(clsServiceTxt* p_pTxt); + bool remove(clsServiceTxt* p_pTxt); + + size_t count(void) const; + + bool removeTempTxts(void); + + clsServiceTxt* find(const char* p_pcKey); + const clsServiceTxt* find(const char* p_pcKey) const; + clsServiceTxt* find(const clsServiceTxt* p_pTxt); + + size_t length(void) const; + + size_t c_strLength(void) const; + bool c_str(char* p_pcBuffer); + const char* c_str(void) const; + + size_t bufferLength(void) const; + bool buffer(char* p_pcBuffer); + + bool compare(const clsServiceTxts& p_Other) const; + bool operator==(const clsServiceTxts& p_Other) const; + bool operator!=(const clsServiceTxts& p_Other) const; + }; + +protected: + /** + clsProbeInformation_Base + */ + class clsProbeInformation_Base + { + public: + /** + typeProbingStatus & enuProbingStatus + */ + using typeProbingStatus = uint8_t; + enum class enuProbingStatus : typeProbingStatus + { + WaitingForData, + ReadyToStart, + InProgress, + ReadyToAnnounce, + DoneFinally + }; + + enuProbingStatus m_ProbingStatus; + uint8_t m_u8SentCount; // Used for probes and announcements + esp8266::polledTimeout::oneShot m_Timeout; // Used for probes and announcements + bool m_bConflict; + bool m_bTiebreakNeeded; + + clsProbeInformation_Base(void); + + bool clear(void); // No 'virtual' needed, no polymorphic use (save 4 bytes) + }; + +public: + /** + fnProbeResultCallback + Callback function for host domain probe results + */ + using fnProbeResultCallback = std::function<void(clsLEAMDNSHost& p_rHost, + const char* p_pcDomainName, + bool p_bProbeResult)>; + +protected: + /** + clsProbeInformation + */ + class clsProbeInformation : public clsProbeInformation_Base + { + public: + fnProbeResultCallback m_fnProbeResultCallback; + + clsProbeInformation(void); + + bool clear(bool p_bClearUserdata = false); + }; + +public: + /** + clsService + */ + struct clsService + { + public: + /** + fnDynamicServiceTxtCallback + */ + using fnDynamicServiceTxtCallback = std::function<void(clsService& p_rMDNSService)>; + + /** + fnProbeResultCallback + */ + using fnProbeResultCallback = std::function<void(clsService& p_rMDNSService, + const char* p_pcInstanceName, + bool p_bProbeResult)>; + + protected: + friend clsLEAMDNSHost; + /** + clsProbeInformation + */ + class clsProbeInformation : public clsProbeInformation_Base + { + public: + fnProbeResultCallback m_fnProbeResultCallback; + + clsProbeInformation(void); + + bool clear(bool p_bClearUserdata = false); + }; + + char* m_pcInstanceName; + bool m_bAutoName; // Name was set automatically to hostname (if no name was supplied) + char* m_pcType; + char* m_pcProtocol; + uint16_t m_u16Port; + uint32_t m_u32ReplyMask; + clsServiceTxts m_Txts; + fnDynamicServiceTxtCallback m_fnTxtCallback; + clsProbeInformation m_ProbeInformation; + + clsService(void); + ~clsService(void); + + bool _releaseInstanceName(void); + bool _releaseType(void); + bool _releaseProtocol(void); + + void _resetProbeStatus(void); + + clsServiceTxt* _addServiceTxt(const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp); + clsServiceTxt* _addServiceTxt(const char* p_pcKey, + uint32_t p_u32Value, + bool p_bTemp); + clsServiceTxt* _addServiceTxt(const char* p_pcKey, + uint16_t p_u16Value, + bool p_bTemp); + clsServiceTxt* _addServiceTxt(const char* p_pcKey, + uint8_t p_u8Value, + bool p_bTemp); + clsServiceTxt* _addServiceTxt(const char* p_pcKey, + int32_t p_i32Value, + bool p_bTemp); + clsServiceTxt* _addServiceTxt(const char* p_pcKey, + int16_t p_i16Value, + bool p_bTemp); + clsServiceTxt* _addServiceTxt(const char* p_pcKey, + int8_t p_i8Value, + bool p_bTemp); + + public: + bool setInstanceName(const char* p_pcInstanceName); + bool indexInstanceName(void); + const char* instanceName(void) const; + + bool setType(const char* p_pcType); + const char* type(void) const; + + bool setProtocol(const char* p_pcProtocol); + const char* protocol(void) const; + + bool setPort(uint16_t p_i16Port); + uint16_t port(void) const; + + bool setProbeResultCallback(fnProbeResultCallback p_fnProbeResultCallback); + bool probeStatus(void) const; + + // TXT + // Add a (static) MDNS TXT item ('key' = 'value') to the service + clsServiceTxt* addServiceTxt(const char* p_pcKey, + const char* p_pcValue); + clsServiceTxt* addServiceTxt(const char* p_pcKey, + uint32_t p_u32Value); + clsServiceTxt* addServiceTxt(const char* p_pcKey, + uint16_t p_u16Value); + clsServiceTxt* addServiceTxt(const char* p_pcKey, + uint8_t p_u8Value); + clsServiceTxt* addServiceTxt(const char* p_pcKey, + int32_t p_i32Value); + clsServiceTxt* addServiceTxt(const char* p_pcKey, + int16_t p_i16Value); + clsServiceTxt* addServiceTxt(const char* p_pcKey, + int8_t p_i8Value); + + bool removeServiceTxt(const char* p_pcKey); + bool removeServiceTxt(clsServiceTxt* p_pTxt); + const clsServiceTxt* findServiceTxt(const char* p_pcKey) const; + clsServiceTxt* findServiceTxt(const char* p_pcKey); + + // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service + // Dynamic TXT items are removed right after one-time use. So they need to be added + // every time the value s needed (via callback). + clsServiceTxt* addDynamicServiceTxt(const char* p_pcKey, + const char* p_pcValue); + clsServiceTxt* addDynamicServiceTxt(const char* p_pcKey, + uint32_t p_u32Value); + clsServiceTxt* addDynamicServiceTxt(const char* p_pcKey, + uint16_t p_u16Value); + clsServiceTxt* addDynamicServiceTxt(const char* p_pcKey, + uint8_t p_u8Value); + clsServiceTxt* addDynamicServiceTxt(const char* p_pcKey, + int32_t p_i32Value); + clsServiceTxt* addDynamicServiceTxt(const char* p_pcKey, + int16_t p_i16Value); + clsServiceTxt* addDynamicServiceTxt(const char* p_pcKey, + int8_t p_i8Value); + + bool setDynamicServiceTxtCallback(fnDynamicServiceTxtCallback p_fnCallback); + + /** + list + */ + using list = std::list<clsService*>; + }; + +protected: + /** + typeContentFlag & enuContentFlag + */ + using typeContentFlag = uint16_t; + enum class enuContentFlag : typeContentFlag + { + // Host + A = 0x0001, + PTR_IPv4 = 0x0002, + PTR_IPv6 = 0x0004, + AAAA = 0x0008, + // Service + PTR_TYPE = 0x0010, + PTR_NAME = 0x0020, + TXT = 0x0040, + SRV = 0x0080, + // DNSSEC + NSEC = 0x0100, + + PTR = (PTR_IPv4 | PTR_IPv6 | PTR_TYPE | PTR_NAME) + }; + + /** + clsMsgHeader + */ + class clsMsgHeader + { + public: + uint16_t m_u16ID; // Identifier + bool m_1bQR : 1; // Query/Response flag + uint8_t m_4bOpcode : 4; // Operation code + bool m_1bAA : 1; // Authoritative Answer flag + bool m_1bTC : 1; // Truncation flag + bool m_1bRD : 1; // Recursion desired + bool m_1bRA : 1; // Recursion available + uint8_t m_3bZ : 3; // Zero + uint8_t m_4bRCode : 4; // Response code + uint16_t m_u16QDCount; // Question count + uint16_t m_u16ANCount; // Answer count + uint16_t m_u16NSCount; // Authority Record count + uint16_t m_u16ARCount; // Additional Record count + + clsMsgHeader(uint16_t p_u16ID = 0, + bool p_bQR = false, + uint8_t p_u8Opcode = 0, + bool p_bAA = false, + bool p_bTC = false, + bool p_bRD = false, + bool p_bRA = false, + uint8_t p_u8RCode = 0, + uint16_t p_u16QDCount = 0, + uint16_t p_u16ANCount = 0, + uint16_t p_u16NSCount = 0, + uint16_t p_u16ARCount = 0); + }; + + /** + clsRRDomain + */ + class clsRRDomain + { + public: + char m_acName[clsConsts::stDomainMaxLength]; // Encoded domain name + uint16_t m_u16NameLength; // Length (incl. '\0') + char* m_pcDecodedName; + + clsRRDomain(void); + clsRRDomain(const clsRRDomain& p_Other); + ~clsRRDomain(void); + + clsRRDomain& operator=(const clsRRDomain& p_Other); + + bool clear(void); + bool clearNameCache(void); + + bool addLabel(const char* p_pcLabel, + bool p_bPrependUnderline = false); + + bool compare(const clsRRDomain& p_Other) const; + bool operator==(const clsRRDomain& p_Other) const; + bool operator!=(const clsRRDomain& p_Other) const; + bool operator>(const clsRRDomain& p_Other) const; + + size_t c_strLength(void) const; + bool c_str(char* p_pcBuffer) const; + const char* c_str(void) const; + }; + + /** + clsRRAttributes + */ + class clsRRAttributes + { + public: + uint16_t m_u16Type; // Type + uint16_t m_u16Class; // Class, nearly always 'IN' + + clsRRAttributes(uint16_t p_u16Type = 0, + uint16_t p_u16Class = 1 /*DNS_RRCLASS_IN Internet*/); + clsRRAttributes(const clsRRAttributes& p_Other); + + clsRRAttributes& operator=(const clsRRAttributes& p_Other); + }; + + /** + clsRRHeader + */ + class clsRRHeader + { + public: + clsRRDomain m_Domain; + clsRRAttributes m_Attributes; + + clsRRHeader(void); + clsRRHeader(const clsRRHeader& p_Other); + + clsRRHeader& operator=(const clsRRHeader& p_Other); + + bool clear(void); + }; + + /** + clsRRQuestion + */ + struct clsRRQuestion + { + clsRRHeader m_Header; + bool m_bUnicast; // Unicast reply requested + + /** + list + */ + using list = std::list<clsRRQuestion*>; + + clsRRQuestion(void); + }; + + /** + clsNSECBitmap + */ + class clsNSECBitmap + { + public: + uint8_t m_au8BitmapData[6]; // 6 bytes data + + clsNSECBitmap(void); + + bool clear(void); + uint16_t length(void) const; + bool setBit(uint16_t p_u16Bit); + bool getBit(uint16_t p_u16Bit) const; + }; + + /** + typeAnswerType & enuAnswerType + */ + using typeAnswerType = uint8_t; + enum class enuAnswerType : typeAnswerType + { + A, + PTR, + TXT, + AAAA, + SRV, + //NSEC, + Generic + }; + + /** + clsRRAnswer + */ + struct clsRRAnswer + { + clsRRAnswer* m_pNext; + const enuAnswerType m_AnswerType; + clsRRHeader m_Header; + bool m_bCacheFlush; // Cache flush command bit + uint32_t m_u32TTL; // Validity time in seconds + + virtual ~clsRRAnswer(void); + + enuAnswerType answerType(void) const; + + bool clear(void); + + protected: + clsRRAnswer(enuAnswerType p_AnswerType, + const clsRRHeader& p_Header, + uint32_t p_u32TTL); + }; + +#ifdef MDNS_IPV4_SUPPORT + /** + clsRRAnswerA + */ + class clsRRAnswerA : public clsRRAnswer + { + public: + IPAddress m_IPAddress; + + clsRRAnswerA(const clsRRHeader& p_Header, + uint32_t p_u32TTL); + ~clsRRAnswerA(void); + + bool clear(void); + }; +#endif + + /** + clsRRAnswerPTR + */ + class clsRRAnswerPTR : public clsRRAnswer + { + public: + clsRRDomain m_PTRDomain; + + clsRRAnswerPTR(const clsRRHeader& p_Header, + uint32_t p_u32TTL); + ~clsRRAnswerPTR(void); + + bool clear(void); + }; + + /** + clsRRAnswerTXT + */ + class clsRRAnswerTXT : public clsRRAnswer + { + public: + clsServiceTxts m_Txts; + + clsRRAnswerTXT(const clsRRHeader& p_Header, + uint32_t p_u32TTL); + ~clsRRAnswerTXT(void); + + bool clear(void); + }; + +#ifdef MDNS_IPV6_SUPPORT + /** + clsRRAnswerAAAA + */ + class clsRRAnswerAAAA : public clsRRAnswer + { + public: + IPAddress m_IPAddress; + + clsRRAnswerAAAA(const clsRRHeader& p_Header, + uint32_t p_u32TTL); + ~clsRRAnswerAAAA(void); + + bool clear(void); + }; +#endif + + /** + clsRRAnswerSRV + */ + class clsRRAnswerSRV : public clsRRAnswer + { + public: + uint16_t m_u16Priority; + uint16_t m_u16Weight; + uint16_t m_u16Port; + clsRRDomain m_SRVDomain; + + clsRRAnswerSRV(const clsRRHeader& p_Header, + uint32_t p_u32TTL); + ~clsRRAnswerSRV(void); + + bool clear(void); + }; + + /** + clsRRAnswerGeneric + */ + class clsRRAnswerGeneric : public clsRRAnswer + { + public: + uint16_t m_u16RDLength; // Length of variable answer + uint8_t* m_pu8RDData; // Offset of start of variable answer in packet + + clsRRAnswerGeneric(const clsRRHeader& p_Header, + uint32_t p_u32TTL); + ~clsRRAnswerGeneric(void); + + bool clear(void); + }; + + + /** + clsSendParameter + */ + class clsSendParameter + { + protected: + /** + clsDomainCacheItem + */ + class clsDomainCacheItem + { + public: + const void* m_pHostNameOrService; // Opaque id for host or service domain (pointer) + bool m_bAdditionalData; // Opaque flag for special info (service domain included) + uint16_t m_u16Offset; // Offset in UDP output buffer + + /** + list + */ + using list = std::list<clsDomainCacheItem*>; + + clsDomainCacheItem(const void* p_pHostNameOrService, + bool p_bAdditionalData, + uint32_t p_u16Offset); + }; + + public: + /** + typeResponseType & enuResponseType + */ + using typeResponseType = uint8_t; + enum class enuResponseType : typeResponseType + { + None, + Response, + Unsolicited + }; + + uint16_t m_u16ID; // Query ID (used only in lagacy queries) + clsRRQuestion::list m_RRQuestions; // A list of queries + uint32_t m_u32HostReplyMask; // Flags for reply components/answers + bool m_bLegacyDNSQuery; // Flag: Legacy query + enuResponseType m_Response; // Enum: Response to a query + bool m_bAuthorative; // Flag: Authorative (owner) response + bool m_bCacheFlush; // Flag: Clients should flush their caches + bool m_bUnicast; // Flag: Unicast response + bool m_bUnannounce; // Flag: Unannounce service + + // Temp content; created while processing _prepareMessage + uint16_t m_u16Offset; // Current offset in UDP write buffer (mainly for domain cache) + clsDomainCacheItem::list m_DomainCacheItems; // Cached host and service domains + + clsSendParameter(void); + ~clsSendParameter(void); + + bool clear(void); + bool flushQuestions(void); + bool flushDomainCache(void); + bool flushTempContent(void); + + bool shiftOffset(uint16_t p_u16Shift); + + bool addDomainCacheItem(const void* p_pHostNameOrService, + bool p_bAdditionalData, + uint16_t p_u16Offset); + uint16_t findCachedDomainOffset(const void* p_pHostNameOrService, + bool p_bAdditionalData) const; + }; + +public: + // QUERIES & ANSWERS + + /** + clsQuery + */ + class clsQuery + { + public: + /** + clsAnswer + */ + class clsAnswer + { + public: + /** + typeQueryAnswerType & enuQueryAnswerType + */ + using typeQueryAnswerType = uint8_t; + enum class enuQueryAnswerType : typeQueryAnswerType + { + Unknown = 0x00, + ServiceDomain = 0x01, // Service domain + HostDomain = 0x02, // Host domain + Port = 0x04, // Port + Txts = 0x08, // TXT items +#ifdef MDNS_IPV4_SUPPORT + IPv4Address = 0x10, // IPv4 address +#endif +#ifdef MDNS_IPV6_SUPPORT + IPv6Address = 0x20, // IPv6 address +#endif + }; + + /** + stcTTL + */ + class clsTTL + { + public: + /** + typeTimeoutLevel & enuTimeoutLevel + */ + using typeTimeoutLevel = uint8_t; + enum class enuTimeoutLevel : typeTimeoutLevel + { + None = 0, + Base = 80, + Interval = 5, + Final = 100 + }; + + uint32_t m_u32TTL; + esp8266::polledTimeout::oneShot m_TTLTimeout; + typeTimeoutLevel m_TimeoutLevel; + + clsTTL(void); + bool set(uint32_t p_u32TTL); + + bool flagged(void) const; + bool restart(void); + + bool prepareDeletion(void); + bool finalTimeoutLevel(void) const; + + unsigned long timeout(void) const; + }; + + /** + clsIPAddressWithTTL + */ + class clsIPAddressWithTTL + { + public: + IPAddress m_IPAddress; + clsTTL m_TTL; + + /** + list + */ + using list = std::list<clsIPAddressWithTTL*>; + + clsIPAddressWithTTL(IPAddress p_IPAddress, + uint32_t p_u32TTL = 0); + }; + + // The service domain is the first 'answer' (from PTR answer, using service and protocol) to be set + // Defines the key for additional answer, like host domain, etc. + clsRRDomain m_ServiceDomain; // 1. level answer (PTR), eg. MyESP._http._tcp.local + clsTTL m_TTLServiceDomain; + clsRRDomain m_HostDomain; // 2. level answer (SRV, using service domain), eg. esp8266.local + uint16_t m_u16Port; // 2. level answer (SRV, using service domain), eg. 5000 + clsTTL m_TTLHostDomainAndPort; + clsServiceTxts m_Txts; // 2. level answer (TXT, using service domain), eg. c#=1 + clsTTL m_TTLTxts; +#ifdef MDNS_IPV4_SUPPORT + clsIPAddressWithTTL::list m_IPv4Addresses; // 3. level answer (A, using host domain), eg. 123.456.789.012 +#endif +#ifdef MDNS_IPV6_SUPPORT + clsIPAddressWithTTL::list m_IPv6Addresses; // 3. level answer (AAAA, using host domain), eg. 1234::09 +#endif + typeQueryAnswerType m_QueryAnswerFlags; // enuQueryAnswerType + + /** + list + */ + using list = std::list<clsAnswer*>; + + clsAnswer(void); + ~clsAnswer(void); + + bool clear(void); + +#ifdef MDNS_IPV4_SUPPORT + bool releaseIPv4Addresses(void); + bool addIPv4Address(clsIPAddressWithTTL* p_pIPAddress); + bool removeIPv4Address(clsIPAddressWithTTL* p_pIPAddress); + const clsIPAddressWithTTL* findIPv4Address(const IPAddress& p_IPAddress) const; + clsIPAddressWithTTL* findIPv4Address(const IPAddress& p_IPAddress); + uint32_t IPv4AddressCount(void) const; + const clsIPAddressWithTTL* IPv4AddressAtIndex(uint32_t p_u32Index) const; + clsIPAddressWithTTL* IPv4AddressAtIndex(uint32_t p_u32Index); +#endif +#ifdef MDNS_IPV6_SUPPORT + bool releaseIPv6Addresses(void); + bool addIPv6Address(clsIPAddressWithTTL* p_pIPAddress); + bool removeIPv6Address(clsIPAddressWithTTL* p_pIPAddress); + const clsIPAddressWithTTL* findIPv6Address(const IPAddress& p_IPAddress) const; + clsIPAddressWithTTL* findIPv6Address(const IPAddress& p_IPAddress); + uint32_t IPv6AddressCount(void) const; + const clsIPAddressWithTTL* IPv6AddressAtIndex(uint32_t p_u32Index) const; + clsIPAddressWithTTL* IPv6AddressAtIndex(uint32_t p_u32Index); +#endif + }; // clsAnswer + + /** + clsAnswerAccessor + */ + class clsAnswerAccessor + { + protected: + /** + stcCompareTxtKey + */ + struct stcCompareTxtKey + { + bool operator()(char const* p_pA, char const* p_pB) const; + }; + public: + clsAnswerAccessor(const clsAnswer* p_pAnswer); + ~clsAnswerAccessor(void); + + /** + clsTxtKeyValueMap + */ + using clsTxtKeyValueMap = std::map<const char*, const char*, stcCompareTxtKey>; + /** + clsIPAddressVector + */ + using clsIPAddressVector = std::vector<IPAddress>; + /** + vector + */ + using vector = std::vector<clsAnswerAccessor>; + + bool serviceDomainAvailable(void) const; + const char* serviceDomain(void) const; + bool hostDomainAvailable(void) const; + const char* hostDomain(void) const; + bool hostPortAvailable(void) const; + uint16_t hostPort(void) const; +#ifdef MDNS_IPV4_SUPPORT + bool IPv4AddressAvailable(void) const; + clsIPAddressVector IPv4Addresses(void) const; +#endif +#ifdef MDNS_IPV6_SUPPORT + bool IPv6AddressAvailable(void) const; + clsIPAddressVector IPv6Addresses(void) const; +#endif + bool txtsAvailable(void) const; + const char* txts(void) const; + const clsTxtKeyValueMap& txtKeyValues(void) const; + const char* txtValue(const char* p_pcKey) const; + + size_t printTo(Print& p_Print) const; + + protected: + const clsAnswer* m_pAnswer; + clsTxtKeyValueMap m_TxtKeyValueMap; + }; + + /** + typeQueryType & enuQueryType + */ + using typeQueryType = uint8_t; + enum class enuQueryType : typeQueryType + { + None, + Service, + Host + }; + + /** + QueryCallbackAnswerFn + */ + using QueryCallbackAnswerFn = std::function<void(const clsQuery& p_Query, + const clsAnswer& p_Answer, + clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)>; // true: Answer component set, false: component deleted + /** + QueryCallbackAccessorFn + */ + using QueryCallbackAccessorFn = std::function<void(const clsQuery& p_Query, + const clsAnswerAccessor& p_AnswerAccessor, + clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)>; // true: Answer component set, false: component deleted + + protected: + friend clsLEAMDNSHost; + + enuQueryType m_QueryType; + clsRRDomain m_Domain; // Type:Service -> _http._tcp.local; Type:Host -> esp8266.local + QueryCallbackAnswerFn m_fnCallbackAnswer; + QueryCallbackAccessorFn m_fnCallbackAccessor; + bool m_bStaticQuery; + uint8_t m_u8SentCount; + esp8266::polledTimeout::oneShot m_ResendTimeout; + bool m_bAwaitingAnswers; + clsAnswer::list m_Answers; + + /** + list + */ + using list = std::list<clsQuery*>; + + clsQuery(const enuQueryType p_QueryType); + ~clsQuery(void); + + bool clear(void); + + bool addAnswer(clsAnswer* p_pAnswer); + bool removeAnswer(clsAnswer* p_pAnswer); + + clsAnswer* findAnswerForServiceDomain(const clsRRDomain& p_ServiceDomain); + clsAnswer* findAnswerForHostDomain(const clsRRDomain& p_HostDomain); + + public: + uint32_t answerCount(void) const; + const clsAnswer* answer(uint32_t p_u32Index) const; + uint32_t indexOfAnswer(const clsAnswer* p_pAnswer) const; + + clsAnswerAccessor::vector answerAccessors(void) const; + clsAnswerAccessor answerAccessor(uint32 p_u32AnswerIndex) const; + }; + +public: + static const char* indexDomainName(const char* p_pcDomainName, + const char* p_pcDivider = "-", + const char* p_pcDefaultDomainName = 0); + static bool setNetIfHostName(netif* p_pNetIf, + const char* p_pcHostName); + + clsLEAMDNSHost(void); + ~clsLEAMDNSHost(void); + + // INIT + // Create a MDNS host by setting the default hostname + // Later call 'update()' in every 'loop' to run the process loop + // (probing, announcing, responding, ...) + // If no callback is given, the (maybe) already installed callback stays set + bool begin(const char* p_pcHostName, + netif* p_pNetIf, + fnProbeResultCallback p_fnCallback = 0); + bool begin(const char* p_pcHostName, + WiFiMode_t p_WiFiMode, + fnProbeResultCallback p_fnCallback = 0); + bool begin(const char* p_pcHostName, + fnProbeResultCallback p_fnCallback = 0); + + bool close(void); + + // HOST + bool setHostName(const char* p_pcHostName); + bool indexHostName(void); + const char* hostName(void) const; + + bool setProbeResultCallback(fnProbeResultCallback p_fnCallback); + + // Returns 'true' is host domain probing is done + bool probeStatus(void) const; + + // SERVICE + bool setDefaultInstanceName(const char* p_pcInstanceName); + const char* defaultInstanceName(void) const; + + clsService* addService(const char* p_pcInstanceName, + const char* p_pcServiceType, + const char* p_pcProtocol, + uint16_t p_u16Port, + clsService::fnProbeResultCallback p_fnCallback = 0); + bool removeService(clsService* p_pMDNSService); + + const clsService* findService(const char* p_pcInstanceName, + const char* p_pcType, + const char* p_pcProtocol, + uint16_t p_u16Port = (uint16_t)(-1)) const; + clsService* findService(const char* p_pcInstanceName, + const char* p_pcType, + const char* p_pcProtocol, + uint16_t p_u16Port = (uint16_t)(-1)); + const clsService::list& services(void) const; + + // QUERIES + + // - STATIC + // Perform a (static) service/host query. The function returns after p_u16Timeout milliseconds + // The answers (the number of received answers is returned) can be retrieved by calling + // - answerHostName (or hostname) + // - answerIP (or IP) + // - answerPort (or port) + clsQuery::clsAnswerAccessor::vector queryService(const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout); + clsQuery::clsAnswerAccessor::vector queryHost(const char* p_pcHostName, + const uint16_t p_u16Timeout); + bool removeQuery(void); + bool hasQuery(void); + clsQuery* getQuery(void); + + // - DYNAMIC + // Install a dynamic service/host query. For every received answer (part) the given callback + // function is called. The query will be updated every time, the TTL for an answer + // has timed-out. + // The answers can also be retrieved by calling + // - answerCount service/host (for host queries, this should never be >1) + // - answerServiceDomain service + // - hasAnswerHostDomain/answerHostDomain service/host + // - hasAnswerIPv4Address/answerIPv4Address service/host + // - hasAnswerIPv6Address/answerIPv6Address service/host + // - hasAnswerPort/answerPort service + // - hasAnswerTxts/answerTxts service + clsQuery* installServiceQuery(const char* p_pcServiceType, + const char* p_pcProtocol, + clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); + clsQuery* installServiceQuery(const char* p_pcServiceType, + const char* p_pcProtocol, + clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); + clsQuery* installHostQuery(const char* p_pcHostName, + clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); + clsQuery* installHostQuery(const char* p_pcHostName, + clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); + // Remove a dynamic service query + bool removeQuery(clsQuery* p_pQuery); + + // PROCESSING + bool update(void); + + bool announce(bool p_bAnnounce = true, + bool p_bIncludeServices = true); + bool announceService(clsService* p_pService, + bool p_bAnnounce = true); + + bool restart(void); + +protected: + // File: ..._Host + UdpContext* _allocBackbone(void); + bool _releaseBackbone(void); + + bool _joinMulticastGroups(void); + bool _leaveMulticastGroups(void); + + // NETIF + typeNetIfState _getNetIfState(void) const; + bool _checkNetIfState(void); + + // PROCESSING + bool _processUDPInput(void); + + // DOMAIN NAMES + bool _allocDomainName(const char* p_pcNewDomainName, + char*& p_rpcDomainName); + bool _releaseDomainName(char*& p_rpcDomainName); + bool _allocHostName(const char* p_pcHostName); + bool _releaseHostName(void); + + bool _allocDefaultInstanceName(const char* p_pcInstanceName); + bool _releaseDefaultInstanceName(void); + const char* _instanceName(const char* p_pcInstanceName, + bool p_bReturnZero = true) const; + + // SERVICE + clsService* _allocService(const char* p_pcName, + const char* p_pcServiceType, + const char* p_pcProtocol, + uint16_t p_u16Port); + bool _releaseService(clsService* p_pService); + + // SERVICE TXT + clsServiceTxt* _allocServiceTxt(clsService* p_pService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp); + bool _releaseServiceTxt(clsService* p_pService, + clsServiceTxt* p_pTxt); + clsServiceTxt* _updateServiceTxt(clsService* p_pService, + clsServiceTxt* p_pTxt, + const char* p_pcValue, + bool p_bTemp); + clsServiceTxt* _findServiceTxt(clsService* p_pService, + const char* p_pcKey); + clsServiceTxt* _addServiceTxt(clsService* p_pService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp); + clsServiceTxt* _answerKeyValue(const clsQuery p_pQuery, + const uint32_t p_u32AnswerIndex); + bool _collectServiceTxts(clsService& p_rService); + bool _releaseTempServiceTxts(clsService& p_rService); + + + // QUERIES + clsQuery* _allocQuery(clsQuery::enuQueryType p_QueryType); + bool _removeQuery(clsQuery* p_pQuery); + bool _removeLegacyQuery(void); + clsQuery* _findLegacyQuery(void); + bool _releaseQueries(void); + clsQuery* _findNextQueryByDomain(const clsRRDomain& p_Domain, + const clsQuery::enuQueryType p_QueryType, + const clsQuery* p_pPrevQuery); + clsQuery* _installServiceQuery(const char* p_pcService, + const char* p_pcProtocol); + clsQuery* _installDomainQuery(clsRRDomain& p_Domain, + clsQuery::enuQueryType p_QueryType); + bool _hasQueriesWaitingForAnswers(void) const; + bool _executeQueryCallback(const clsQuery& p_Query, + const clsQuery::clsAnswer& p_Answer, + clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, + bool p_SetContent); + + + // File: ..._Host_Control + // RECEIVING + bool _parseMessage(void); + bool _parseQuery(const clsMsgHeader& p_Header); + + bool _parseResponse(const clsMsgHeader& p_Header); + bool _processAnswers(const clsRRAnswer* p_pPTRAnswers); + bool _processPTRAnswer(const clsRRAnswerPTR* p_pPTRAnswer, + bool& p_rbFoundNewKeyAnswer); + bool _processSRVAnswer(const clsRRAnswerSRV* p_pSRVAnswer, + bool& p_rbFoundNewKeyAnswer); + bool _processTXTAnswer(const clsRRAnswerTXT* p_pTXTAnswer); +#ifdef MDNS_IPV4_SUPPORT + bool _processAAnswer(const clsRRAnswerA* p_pAAnswer); +#endif +#ifdef MDNS_IPV6_SUPPORT + bool _processAAAAAnswer(const clsRRAnswerAAAA* p_pAAAAAnswer); +#endif + + // PROBING + bool _updateProbeStatus(void); + bool _resetProbeStatus(bool p_bRestart = true); + bool _hasProbesWaitingForAnswers(void) const; + bool _sendHostProbe(void); + bool _sendServiceProbe(clsService& p_rService); + bool _cancelProbingForHost(void); + bool _cancelProbingForService(clsService& p_rService); + bool _callHostProbeResultCallback(bool p_bResult); + bool _callServiceProbeResultCallback(clsService& p_rService, + bool p_bResult); + + // ANNOUNCE + bool _announce(bool p_bAnnounce, + bool p_bIncludeServices); + bool _announceService(clsService& p_pService, + bool p_bAnnounce = true); + + // QUERY CACHE + bool _checkQueryCache(void); + + uint32_t _replyMaskForHost(const clsRRHeader& p_RRHeader, + bool* p_pbFullNameMatch = 0) const; + uint32_t _replyMaskForService(const clsRRHeader& p_RRHeader, + clsService& p_rService, + bool* p_pbFullNameMatch = 0); + + + // File: ..._Host_Transfer + // SENDING + bool _sendMessage(clsSendParameter& p_SendParameter); + bool _sendMessage_Multicast(clsSendParameter& p_rSendParameter, + uint8_t p_IPProtocolTypes); + bool _prepareMessage(clsSendParameter& p_SendParameter); + bool _addQueryRecord(clsSendParameter& p_rSendParameter, + const clsRRDomain& p_QueryDomain, + uint16_t p_u16QueryType); + bool _sendQuery(const clsQuery& p_Query, + clsQuery::clsAnswer::list* p_pKnownAnswers = 0); + bool _sendQuery(const clsRRDomain& p_QueryDomain, + uint16_t p_u16RecordType, + clsQuery::clsAnswer::list* p_pKnownAnswers = 0); + + IPAddress _getResponderIPAddress(enuIPProtocolType p_IPProtocolType) const; + + // RESOURCE RECORD + bool _readRRQuestion(clsRRQuestion& p_rQuestion); + bool _readRRAnswer(clsRRAnswer*& p_rpAnswer); +#ifdef MDNS_IPV4_SUPPORT + bool _readRRAnswerA(clsRRAnswerA& p_rRRAnswerA, + uint16_t p_u16RDLength); +#endif + bool _readRRAnswerPTR(clsRRAnswerPTR& p_rRRAnswerPTR, + uint16_t p_u16RDLength); + bool _readRRAnswerTXT(clsRRAnswerTXT& p_rRRAnswerTXT, + uint16_t p_u16RDLength); +#ifdef MDNS_IPV6_SUPPORT + bool _readRRAnswerAAAA(clsRRAnswerAAAA& p_rRRAnswerAAAA, + uint16_t p_u16RDLength); +#endif + bool _readRRAnswerSRV(clsRRAnswerSRV& p_rRRAnswerSRV, + uint16_t p_u16RDLength); + bool _readRRAnswerGeneric(clsRRAnswerGeneric& p_rRRAnswerGeneric, + uint16_t p_u16RDLength); + + bool _readRRHeader(clsRRHeader& p_rHeader); + bool _readRRDomain(clsRRDomain& p_rRRDomain); + bool _readRRDomain_Loop(clsRRDomain& p_rRRDomain, + uint8_t p_u8Depth); + bool _readRRAttributes(clsRRAttributes& p_rAttributes); + + // DOMAIN NAMES + bool _buildDomainForHost(const char* p_pcHostName, + clsRRDomain& p_rHostDomain) const; + bool _buildDomainForDNSSD(clsRRDomain& p_rDNSSDDomain) const; + bool _buildDomainForService(const clsService& p_Service, + bool p_bIncludeName, + clsRRDomain& p_rServiceDomain) const; + bool _buildDomainForService(const char* p_pcService, + const char* p_pcProtocol, + clsRRDomain& p_rServiceDomain) const; +#ifdef MDNS_IPV4_SUPPORT + bool _buildDomainForReverseIPv4(IPAddress p_IPv4Address, + clsRRDomain& p_rReverseIPv4Domain) const; +#endif +#ifdef MDNS_IPV6_SUPPORT + bool _buildDomainForReverseIPv6(IPAddress p_IPv4Address, + clsRRDomain& p_rReverseIPv6Domain) const; +#endif + + // UDP + bool _udpReadBuffer(unsigned char* p_pBuffer, + size_t p_stLength); + bool _udpRead8(uint8_t& p_ru8Value); + bool _udpRead16(uint16_t& p_ru16Value); + bool _udpRead32(uint32_t& p_ru32Value); + + bool _udpAppendBuffer(const unsigned char* p_pcBuffer, + size_t p_stLength); + bool _udpAppend8(uint8_t p_u8Value); + bool _udpAppend16(uint16_t p_u16Value); + bool _udpAppend32(uint32_t p_u32Value); + +#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER + bool _udpDump(bool p_bMovePointer = false); + bool _udpDump(unsigned p_uOffset, + unsigned p_uLength); +#endif + + // READ/WRITE MDNS STRUCTS + bool _readMDNSMsgHeader(clsMsgHeader& p_rMsgHeader); + + bool _write8(uint8_t p_u8Value, + clsSendParameter& p_rSendParameter); + bool _write16(uint16_t p_u16Value, + clsSendParameter& p_rSendParameter); + bool _write32(uint32_t p_u32Value, + clsSendParameter& p_rSendParameter); + + bool _writeMDNSMsgHeader(const clsMsgHeader& p_MsgHeader, + clsSendParameter& p_rSendParameter); + bool _writeMDNSRRAttributes(const clsRRAttributes& p_Attributes, + clsSendParameter& p_rSendParameter); + bool _writeMDNSRRDomain(const clsRRDomain& p_Domain, + clsSendParameter& p_rSendParameter); + bool _writeMDNSHostDomain(const char* m_pcHostName, + bool p_bPrependRDLength, + uint16_t p_u16AdditionalLength, + clsSendParameter& p_rSendParameter); + bool _writeMDNSServiceDomain(const clsService& p_Service, + bool p_bIncludeName, + bool p_bPrependRDLength, + uint16_t p_u16AdditionalLength, + clsSendParameter& p_rSendParameter); + + bool _writeMDNSQuestion(clsRRQuestion& p_Question, + clsSendParameter& p_rSendParameter); + +#ifdef MDNS_IPV4_SUPPORT + bool _writeMDNSAnswer_A(IPAddress p_IPAddress, + clsSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_PTR_IPv4(IPAddress p_IPAddress, + clsSendParameter& p_rSendParameter); +#endif + bool _writeMDNSAnswer_PTR_TYPE(clsService& p_rService, + clsSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_PTR_NAME(clsService& p_rService, + clsSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_TXT(clsService& p_rService, + clsSendParameter& p_rSendParameter); +#ifdef MDNS_IPV6_SUPPORT + bool _writeMDNSAnswer_AAAA(IPAddress p_IPAddress, + clsSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_PTR_IPv6(IPAddress p_IPAddress, + clsSendParameter& p_rSendParameter); +#endif + bool _writeMDNSAnswer_SRV(clsService& p_rService, + clsSendParameter& p_rSendParameter); + clsNSECBitmap* _createNSECBitmap(uint32_t p_u32NSECContent); + bool _writeMDNSNSECBitmap(const clsNSECBitmap& p_NSECBitmap, + clsSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_NSEC(uint32_t p_u32NSECContent, + clsSendParameter& p_rSendParameter); +#ifdef MDNS_IPV4_SUPPORT + bool _writeMDNSAnswer_NSEC_PTR_IPv4(IPAddress p_IPAddress, + clsSendParameter& p_rSendParameter); +#endif +#ifdef MDNS_IPV6_SUPPORT + bool _writeMDNSAnswer_NSEC_PTR_IPv6(IPAddress p_IPAddress, + clsSendParameter& p_rSendParameter); +#endif + bool _writeMDNSAnswer_NSEC(clsService& p_rService, + uint32_t p_u32NSECContent, + clsSendParameter& p_rSendParameter); + + + // File: ..._Host_Debug +#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER + const char* _DH(const clsService* p_pMDNSService = 0) const; + const char* _service2String(const clsService* p_pMDNSService) const; + + bool _printRRDomain(const clsRRDomain& p_rRRDomain) const; + bool _printRRAnswer(const clsRRAnswer& p_RRAnswer) const; + const char* _RRType2Name(uint16_t p_u16RRType) const; + const char* _RRClass2String(uint16_t p_u16RRClass, + bool p_bIsQuery) const; + const char* _replyFlags2String(uint32_t p_u32ReplyFlags) const; + const char* _NSECBitmap2String(const clsNSECBitmap* p_pNSECBitmap) const; +#endif + + +protected: + netif* m_pNetIf; + typeNetIfState m_NetIfState; + UdpContext* m_pUDPContext; + + char* m_pcHostName; + char* m_pcDefaultInstanceName; + clsService::list m_Services; + clsQuery::list m_Queries; + clsProbeInformation m_ProbeInformation; +}; + + +} // namespace MDNSImplementation + + +} // namespace esp8266 + + +#endif // __LEAMDNS2HOST_H__ + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp old mode 100755 new mode 100644 similarity index 66% rename from libraries/ESP8266mDNS/src/LEAmDNS2_Host_Control.cpp rename to libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index 7b4402c587..11fece09c1 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1,5 +1,5 @@ /* - LEAmDNS2_Host_Control.cpp + LEAmDNS2Host_Control.cpp License (MIT license): Permission is hereby granted, free of charge, to any person obtaining a copy @@ -22,54 +22,41 @@ */ -#include <arch/cc.h> -#include <sys/time.h> -#include <HardwareSerial.h> -#include <IPAddress.h> -#include <lwip/ip_addr.h> -#include <WString.h> -#include <cstdint> +#include "LEAmDNS2Host.h" -/* - ESP8266mDNS Control.cpp -*/ - -extern "C" { -#include "user_interface.h" -} - -#include "LEAmDNS2_lwIPdefs.h" -#include "LEAmDNS2_Priv.h" namespace esp8266 { -/* - LEAmDNS -*/ + + namespace experimental { -/** + +/* + RECEIVING + */ /* - MDNSResponder::clsHost::_parseMessage + clsLEAmDNS2_Host::_parseMessage + */ -bool MDNSResponder::clsHost::_parseMessage(void) +bool clsLEAMDNSHost::_parseMessage(void) { DEBUG_EX_INFO( unsigned long ulStartTime = millis(); unsigned uStartMemory = ESP.getFreeHeap(); DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage (Time: %lu ms, heap: %u bytes, from %s, to %s)\n"), _DH(), ulStartTime, uStartMemory, - m_rUDPContext.getRemoteAddress().toString().c_str(), - m_rUDPContext.getDestAddress().toString().c_str()); + m_pUDPContext->getRemoteAddress().toString().c_str(), + m_pUDPContext->getDestAddress().toString().c_str()); ); //DEBUG_EX_INFO(_udpDump();); bool bResult = false; - stcMsgHeader header; + clsMsgHeader header; if (_readMDNSMsgHeader(header)) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), @@ -81,15 +68,18 @@ bool MDNSResponder::clsHost::_parseMessage(void) (unsigned)header.m_u16ANCount, (unsigned)header.m_u16NSCount, (unsigned)header.m_u16ARCount)); - if (0 == header.m_4bOpcode) // A standard query + if (0 == header.m_4bOpcode) { - if (header.m_1bQR) // Received a response -> answers to a query + // A standard query + if (header.m_1bQR) { + // Received a response -> answers to a query //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: Reading answers: ID:%u, Q:%u, A:%u, NS:%u, AR:%u\n"), _DH(), header.m_u16ID, header.m_u16QDCount, header.m_u16ANCount, header.m_u16NSCount, header.m_u16ARCount);); bResult = _parseResponse(header); } - else // Received a query (Questions) + else { + // Received a query (Questions) //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: Reading query: ID:%u, Q:%u, A:%u, NS:%u, AR:%u\n"), _DH(), header.m_u16ID, header.m_u16QDCount, header.m_u16ANCount, header.m_u16NSCount, header.m_u16ARCount);); bResult = _parseQuery(header); } @@ -97,13 +87,13 @@ bool MDNSResponder::clsHost::_parseMessage(void) else { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: Received UNEXPECTED opcode:%u. Ignoring message!\n"), _DH(), header.m_4bOpcode);); - m_rUDPContext.flush(); + m_pUDPContext->flush(); } } else { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: FAILED to read header\n"), _DH());); - m_rUDPContext.flush(); + m_pUDPContext->flush(); } DEBUG_EX_INFO( unsigned uFreeHeap = ESP.getFreeHeap(); @@ -113,7 +103,7 @@ bool MDNSResponder::clsHost::_parseMessage(void) } /* - MDNSResponder::clsHost::_parseQuery + clsLEAmDNS2_Host::_parseQuery Queries are of interest in two cases: 1. allow for tiebreaking while probing in the case of a race condition between two instances probing for @@ -127,17 +117,17 @@ bool MDNSResponder::clsHost::_parseMessage(void) As any mDNS responder should be able to handle 'legacy' queries (from DNS clients), this case is handled here also. Legacy queries have got only one (unicast) question and are directed to the local DNS port (not the multicast port). - 1. */ -bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHeader& p_MsgHeader) +bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader) { bool bResult = true; - stcSendParameter sendParameter; - uint32_t u32HostOrServiceReplies = 0; + clsSendParameter sendParameter; + uint32_t u32HostOrServiceReplies = 0; + bool bHostOrServiceTiebreakNeeded = false; for (uint16_t qd = 0; ((bResult) && (qd < p_MsgHeader.m_u16QDCount)); ++qd) { - stcRRQuestion questionRR; + clsRRQuestion questionRR; if ((bResult = _readRRQuestion(questionRR))) { // Define host replies, BUT only answer queries after probing is done @@ -148,26 +138,28 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea DEBUG_EX_INFO(if (u32HostOrServiceReplies) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Host reply needed %s\n"), _DH(), _replyFlags2String(u32HostOrServiceReplies));); // Check tiebreak need for host domain - if (enuProbingStatus::InProgress == m_HostProbeInformation.m_ProbingStatus) + if (clsProbeInformation_Base::clsProbeInformation_Base::enuProbingStatus::InProgress == m_ProbeInformation.m_ProbingStatus) { bool bFullNameMatch = false; if ((_replyMaskForHost(questionRR.m_Header, &bFullNameMatch)) && (bFullNameMatch)) { // We're in 'probing' state and someone is asking for our host domain: this might be - // a race-condition: Two host with the same domain names try simutanously to probe their domains + // a race-condition: Two hosts with the same domain names try simutanously to probe their domains // See: RFC 6762, 8.2 (Tiebraking) // However, we're using a max. reduced approach for tiebreaking here: The higher IP-address wins! DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Possible race-condition for host domain detected while probing.\n"), _DH());); - Serial.printf_P(PSTR("%s _parseQuery: Possible race-condition for host domain detected while probing.\n"), _DH()); - m_HostProbeInformation.m_bTiebreakNeeded = true; + bHostOrServiceTiebreakNeeded = + m_ProbeInformation.m_bTiebreakNeeded = true; } } // Define service replies - for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) + for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) { + clsService* pService = *it; + // Define service replies, BUT only answer queries after probing is done uint32_t u32ReplyMaskForQuestion = ((pService->probeStatus()) ? _replyMaskForService(questionRR.m_Header, *pService, 0) @@ -176,7 +168,7 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea DEBUG_EX_INFO(if (u32ReplyMaskForQuestion) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service reply needed: %s\n"), _DH(pService), _replyFlags2String(u32ReplyMaskForQuestion));); // Check tiebreak need for service domain - if (enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) + if (clsProbeInformation_Base::clsProbeInformation_Base::enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) { bool bFullNameMatch = false; if ((_replyMaskForService(questionRR.m_Header, *pService, &bFullNameMatch)) && @@ -187,26 +179,25 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea // See: RFC 6762, 8.2 (Tiebraking) // However, we're using a max. reduced approach for tiebreaking here: The 'higher' SRV host wins! DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Possible race-condition for service domain detected while probing.\n"), _DH(pService));); - Serial.printf_P(PSTR("%s _parseQuery: Possible race-condition for service domain detected while probing.\n"), _DH(pService)); - pService->m_ProbeInformation.m_bTiebreakNeeded = true; + bHostOrServiceTiebreakNeeded = + pService->m_ProbeInformation.m_bTiebreakNeeded = true; } } } // Handle unicast and legacy specialities // If only one question asks for unicast reply, the whole reply packet is send unicast - if (((DNS_MQUERY_PORT != m_rUDPContext.getRemotePort()) || // Unicast (maybe legacy) query OR + if (((DNS_MQUERY_PORT != m_pUDPContext->getRemotePort()) || // Unicast (maybe legacy) query OR (questionRR.m_bUnicast)) && // Expressivly unicast query (!sendParameter.m_bUnicast)) { - sendParameter.m_bUnicast = true; //sendParameter.m_bCacheFlush = false; - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Unicast response asked for %s!\n"), _DH(), m_rUDPContext.getRemoteAddress().toString().c_str());); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Unicast response asked for %s!\n"), _DH(), m_pUDPContext->getRemoteAddress().toString().c_str());); //Serial.printf_P(PSTR("%s _parseQuery: Ignored Unicast response asked for by %s!\n"), _DH(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str()); - if ((DNS_MQUERY_PORT != m_rUDPContext.getRemotePort()) && // Unicast (maybe legacy) query AND + if ((DNS_MQUERY_PORT != m_pUDPContext->getRemotePort()) && // Unicast (maybe legacy) query AND (1 == p_MsgHeader.m_u16QDCount) && // Only one question AND ((sendParameter.m_u32HostReplyMask) || // Host replies OR (u32HostOrServiceReplies))) // Host or service replies available @@ -217,22 +208,23 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea #ifdef MDNS_IPV4_SUPPORT ip_info IPInfo_Local; #endif - if ( + if ((m_pNetIf) && + (m_pUDPContext) && #ifdef MDNS_IPV4_SUPPORT - (m_rUDPContext.getRemoteAddress().isV4()) && - ((wifi_get_ip_info(netif_get_index(&m_rNetIf), &IPInfo_Local))) && - (ip4_addr_netcmp(ip_2_ip4((const ip_addr_t*)m_rUDPContext.getRemoteAddress()), &IPInfo_Local.ip, &IPInfo_Local.netmask)) + (m_pUDPContext->getRemoteAddress().isV4()) && + ((wifi_get_ip_info(netif_get_index(m_pNetIf), &IPInfo_Local))) && + (ip4_addr_netcmp(ip_2_ip4((const ip_addr_t*)m_pUDPContext->getRemoteAddress()), &IPInfo_Local.ip, &IPInfo_Local.netmask)) #else (true) #endif && #ifdef MDNS_IPV6_SUPPORT - (m_rUDPContext.getRemoteAddress().isV6()) && - (ip6_addr_islinklocal(ip_2_ip6((const ip_addr_t*)m_rUDPContext.getRemoteAddress()))) + (m_pUDPContext->getRemoteAddress().isV6()) && + (ip6_addr_islinklocal(ip_2_ip6((const ip_addr_t*)m_pUDPContext->getRemoteAddress()))) #else (true) #endif - ) + ) { /* ip_info IPInfo_Local; ip_info IPInfo_Remote; @@ -243,27 +235,29 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea (ip4_addr_netcmp(&IPInfo_Remote.ip, &IPInfo_Local.ip, &IPInfo_Local.netmask))))) // Remote IP in STATION's subnet {*/ Serial.println("\n\n\nUNICAST QUERY\n\n"); - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Legacy query from local host %s!\n"), _DH(), m_rUDPContext.getRemoteAddress().toString().c_str());); + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Legacy DNS query from local host %s!\n"), _DH(), m_pUDPContext->getRemoteAddress().toString().c_str());); sendParameter.m_u16ID = p_MsgHeader.m_u16ID; - sendParameter.m_bLegacyQuery = true; + sendParameter.m_bLegacyDNSQuery = true; sendParameter.m_bCacheFlush = false; - sendParameter.m_pQuestions = new stcRRQuestion; - if ((bResult = (0 != sendParameter.m_pQuestions))) + clsRRQuestion* pNewRRQuestion = new clsRRQuestion; + if (pNewRRQuestion) { - sendParameter.m_pQuestions->m_Header.m_Domain = questionRR.m_Header.m_Domain; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = questionRR.m_Header.m_Attributes.m_u16Type; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = questionRR.m_Header.m_Attributes.m_u16Class; + pNewRRQuestion->m_Header.m_Domain = questionRR.m_Header.m_Domain; + pNewRRQuestion->m_Header.m_Attributes.m_u16Type = questionRR.m_Header.m_Attributes.m_u16Type; + pNewRRQuestion->m_Header.m_Attributes.m_u16Class = questionRR.m_Header.m_Attributes.m_u16Class; + + sendParameter.m_RRQuestions.push_back(pNewRRQuestion); } else { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: FAILED to add legacy question!\n"), _DH());); + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: FAILED to add legacy DNS question!\n"), _DH());); } } else { - Serial.println("\n\n\nINVALID UNICAST QUERY\n\n"); - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Legacy query from NON-LOCAL host!\n"), _DH());); + Serial.printf("\n\n\nINVALID UNICAST QUERY from %s\n\n\n", m_pUDPContext->getRemoteAddress().toString().c_str()); + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Legacy DNS query from NON-LOCAL host at %s!\n"), _DH(), m_pUDPContext->getRemoteAddress().toString().c_str());); bResult = false; } } @@ -276,30 +270,31 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea } // for questions //DEBUG_EX_INFO(if (u8HostOrServiceReplies) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Reply needed: %u (%s: %s->%s)\n"), _DH(), u8HostOrServiceReplies, clsTimeSyncer::timestr(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str(), IPAddress(m_pUDPContext->getDestAddress()).toString().c_str());); + //bHostOrServiceTiebreakNeeded = false; // Handle known answers uint32_t u32Answers = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); - if ((u32HostOrServiceReplies) && + if (((u32HostOrServiceReplies) || + (bHostOrServiceTiebreakNeeded)) && (u32Answers)) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Reading known answers(%u):\n"), _DH(), u32Answers);); for (uint32_t an = 0; ((bResult) && (an < u32Answers)); ++an) { - stcRRAnswer* pKnownRRAnswer = 0; + clsRRAnswer* pKnownRRAnswer = 0; if (((bResult = _readRRAnswer(pKnownRRAnswer))) && (pKnownRRAnswer)) { - if ((DNS_RRTYPE_ANY != pKnownRRAnswer->m_Header.m_Attributes.m_u16Type) && // No ANY type answer (DNS_RRCLASS_ANY != (pKnownRRAnswer->m_Header.m_Attributes.m_u16Class & (~0x8000)))) // No ANY class answer { - - // Find match between planned answer (sendParameter.m_u8HostReplyMask) and this 'known answer' - uint32_t u32HostMatchMask = (sendParameter.m_u32HostReplyMask & _replyMaskForHost(pKnownRRAnswer->m_Header)); - if ((u32HostMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND - ((MDNS_HOST_TTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new host TTL (120s) - { + /* - RFC6762 7.1 Suppression only for 'Shared Records' - + // Find match between planned answer (sendParameter.m_u8HostReplyMask) and this 'known answer' + uint32_t u32HostMatchMask = (sendParameter.m_u32HostReplyMask & _replyMaskForHost(pKnownRRAnswer->m_Header)); + if ((u32HostMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND + ((Consts::u32HostTTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new host TTL (120s) + { // Compare contents if (enuAnswerType::PTR == pKnownRRAnswer->answerType()) @@ -309,41 +304,41 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea (((stcRRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain == hostDomain)) { // Host domain match -#ifdef MDNS_IPV4_SUPPORT + #ifdef MDNS_IPV4_SUPPORT if (u32HostMatchMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)) { // IPv4 PTR was asked for, but is already known -> skipping - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: IPv4 PTR already known... skipping!\n"), _DH());); + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: IPv4 PTR already known (TTL:%u)... skipping!\n"), _DH(), pKnownRRAnswer->m_u32TTL);); sendParameter.m_u32HostReplyMask &= ~static_cast<uint32_t>(enuContentFlag::PTR_IPv4); } -#endif -#ifdef MDNS_IPV6_SUPPORT + #endif + #ifdef MDNS_IPV6_SUPPORT if (u32HostMatchMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv6)) { // IPv6 PTR was asked for, but is already known -> skipping - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: IPv6 PTR already known... skipping!\n"), _DH());); + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: IPv6 PTR already known (TTL:%u)... skipping!\n"), _DH(), pKnownRRAnswer->m_u32TTL);); sendParameter.m_u32HostReplyMask &= ~static_cast<uint32_t>(enuContentFlag::PTR_IPv6); } -#endif + #endif } } else if (u32HostMatchMask & static_cast<uint32_t>(enuContentFlag::A)) { // IPv4 address was asked for -#ifdef MDNS_IPV4_SUPPORT + #ifdef MDNS_IPV4_SUPPORT if ((enuAnswerType::A == pKnownRRAnswer->answerType()) && (((stcRRAnswerA*)pKnownRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V4))) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: IPv4 address already known... skipping!\n"), _DH());); + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: IPv4 address already known (TTL:%u)... skipping!\n"), _DH(), pKnownRRAnswer->m_u32TTL);); sendParameter.m_u32HostReplyMask &= ~static_cast<uint32_t>(enuContentFlag::A); } // else: RData NOT IPv4 length !! -#endif + #endif } else if (u32HostMatchMask & static_cast<uint32_t>(enuContentFlag::AAAA)) { // IPv6 address was asked for -#ifdef MDNS_IPV6_SUPPORT + #ifdef MDNS_IPV6_SUPPORT if ((enuAnswerType::AAAA == pKnownRRAnswer->answerType()) && (((stcRRAnswerAAAA*)pKnownRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V6))) { @@ -351,15 +346,16 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: IPv6 address already known... skipping!\n"), _DH());); sendParameter.m_u32HostReplyMask &= ~static_cast<uint32_t>(enuContentFlag::AAAA); } // else: RData NOT IPv6 length !! -#endif + #endif } - } // Host match /*and TTL*/ + } // Host match and TTL + */ // // Check host tiebreak possibility - if (m_HostProbeInformation.m_bTiebreakNeeded) + if (m_ProbeInformation.m_bTiebreakNeeded) { - stcRRDomain hostDomain; + clsRRDomain hostDomain; if ((_buildDomainForHost(m_pcHostName, hostDomain)) && (pKnownRRAnswer->m_Header.m_Domain == hostDomain)) { @@ -369,26 +365,26 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea { // CHECK IPAddress localIPAddress(_getResponderIPAddress(enuIPProtocolType::V4)); - if (((stcRRAnswerA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) + if (((clsRRAnswerA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) { // SAME IP address -> We've received an old message from ourselfs (same IP) DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv4) WON (was an old message)!\n"), _DH());); - m_HostProbeInformation.m_bTiebreakNeeded = false; + m_ProbeInformation.m_bTiebreakNeeded = false; } else { - if ((uint32_t)(((stcRRAnswerA*)pKnownRRAnswer)->m_IPAddress) > (uint32_t)localIPAddress) // The OTHER IP is 'higher' -> LOST + if ((uint32_t)(((clsRRAnswerA*)pKnownRRAnswer)->m_IPAddress) > (uint32_t)localIPAddress) // The OTHER IP is 'higher' -> LOST { // LOST tiebreak - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv4) LOST (lower)!\n"), _DH());); + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv4) LOST (lower IPv4)!\n"), _DH());); _cancelProbingForHost(); - m_HostProbeInformation.m_bTiebreakNeeded = false; + m_ProbeInformation.m_bTiebreakNeeded = false; } - else // WON tiebreak + else { - //TiebreakState = TiebreakState_Won; // We received an 'old' message from ourselfs -> Just ignore - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv4) WON (higher IP)!\n"), _DH());); - m_HostProbeInformation.m_bTiebreakNeeded = false; + // WON tiebreak + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv4) WON (higher IPv4)!\n"), _DH());); + m_ProbeInformation.m_bTiebreakNeeded = false; } } } @@ -396,28 +392,28 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea #ifdef MDNS_IPV6_SUPPORT if (enuAnswerType::AAAA == pKnownRRAnswer->answerType()) { - // TODO / CHECK IPAddress localIPAddress(_getResponderIPAddress(enuIPProtocolType::V6)); - if (((stcRRAnswerAAAA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) + if (((clsRRAnswerAAAA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) { // SAME IP address -> We've received an old message from ourselfs (same IP) DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv6) WON (was an old message)!\n"), _DH());); - m_HostProbeInformation.m_bTiebreakNeeded = false; + m_ProbeInformation.m_bTiebreakNeeded = false; } else { - if ((uint32_t)(((stcRRAnswerAAAA*)pKnownRRAnswer)->m_IPAddress) > (uint32_t)localIPAddress) // The OTHER IP is 'higher' -> LOST + // memcmp delivers >0 (positive) if the first non-matching byte in A is higher than in B + if (0 < memcmp((((clsRRAnswerAAAA*)pKnownRRAnswer)->m_IPAddress).raw6(), localIPAddress.raw6(), clsConsts::u16IPv6Size)) // The OTHER IP is 'higher' -> LOST { // LOST tiebreak - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv6) LOST (lower)!\n"), _DH());); + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv6) LOST (lower IPv6)!\n"), _DH());); _cancelProbingForHost(); - m_HostProbeInformation.m_bTiebreakNeeded = false; + m_ProbeInformation.m_bTiebreakNeeded = false; } - else // WON tiebreak + else { - //TiebreakState = TiebreakState_Won; // We received an 'old' message from ourselfs -> Just ignore - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv6) WON (higher IP)!\n"), _DH());); - m_HostProbeInformation.m_bTiebreakNeeded = false; + // WON tiebreak + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv6) WON (higher IPv6)!\n"), _DH());); + m_ProbeInformation.m_bTiebreakNeeded = false; } } } @@ -426,97 +422,98 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea } // Host tiebreak possibility // Check service answers - for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) + for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) { + clsService* pService = *it; uint32_t u32ServiceMatchMask = (pService->m_u32ReplyMask & _replyMaskForService(pKnownRRAnswer->m_Header, *pService)); if ((u32ServiceMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND - ((MDNS_SERVICE_TTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new service TTL (4500s) + ((clsConsts::u32ServiceTTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new service TTL (4500s) { - if (enuAnswerType::PTR == pKnownRRAnswer->answerType()) { - stcRRDomain serviceDomain; + clsRRDomain serviceDomain; if ((u32ServiceMatchMask & static_cast<uint32_t>(enuContentFlag::PTR_TYPE)) && (_buildDomainForService(*pService, false, serviceDomain)) && - (serviceDomain == ((stcRRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) + (serviceDomain == ((clsRRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service type PTR already known... skipping!\n"), _DH());); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service type PTR already known (TTL:%u)... skipping!\n"), _DH(pService), pKnownRRAnswer->m_u32TTL);); pService->m_u32ReplyMask &= ~static_cast<uint32_t>(enuContentFlag::PTR_TYPE); } if ((u32ServiceMatchMask & static_cast<uint32_t>(enuContentFlag::PTR_NAME)) && (_buildDomainForService(*pService, true, serviceDomain)) && - (serviceDomain == ((stcRRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) + (serviceDomain == ((clsRRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service name PTR already known... skipping!\n"), _DH());); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service name PTR already known (TTL:%u)... skipping!\n"), _DH(pService), pKnownRRAnswer->m_u32TTL);); pService->m_u32ReplyMask &= ~static_cast<uint32_t>(enuContentFlag::PTR_NAME); } } - else if (u32ServiceMatchMask & static_cast<uint32_t>(enuContentFlag::SRV)) - { - DEBUG_EX_ERR(if (enuAnswerType::SRV != pKnownRRAnswer->answerType()) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: ERROR! INVALID answer type (SRV)!\n"), _DH());); + /* - RFC6762 7.1 Suppression only for 'Shared Records' + else if (u32ServiceMatchMask & static_cast<uint32_t>(enuContentFlag::SRV)) + { + DEBUG_EX_ERR(if (enuAnswerType::SRV != pKnownRRAnswer->answerType()) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: ERROR! INVALID answer type (SRV)!\n"), _DH(pService));); stcRRDomain hostDomain; if ((_buildDomainForHost(m_pcHostName, hostDomain)) && (hostDomain == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain)) // Host domain match { - if ((MDNS_SRV_PRIORITY == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_u16Priority) && - (MDNS_SRV_WEIGHT == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_u16Weight) && + if ((Consts::u16SRVPriority == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_u16Priority) && + (Consts::u16SRVWeight == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_u16Weight) && (pService->m_u16Port == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_u16Port)) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service SRV answer already known... skipping!\n"), _DH());); + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service SRV answer already known (TTL:%u)... skipping!\n"), _DH(pService), pKnownRRAnswer->m_u32TTL);); pService->m_u32ReplyMask &= ~static_cast<uint32_t>(enuContentFlag::SRV); } // else: Small differences -> send update message } - } - else if (u32ServiceMatchMask & static_cast<uint32_t>(enuContentFlag::TXT)) - { - DEBUG_EX_ERR(if (enuAnswerType::TXT != pKnownRRAnswer->answerType()) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: ERROR! INVALID answer type (TXT)!\n"), _DH());); + }*/ + /* - RFC6762 7.1 Suppression only for 'Shared Records' + else if (u32ServiceMatchMask & static_cast<uint32_t>(enuContentFlag::TXT)) + { + DEBUG_EX_ERR(if (enuAnswerType::TXT != pKnownRRAnswer->answerType()) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: ERROR! INVALID answer type (TXT)!\n"), _DH(pService));); _collectServiceTxts(*pService); if (pService->m_Txts == ((stcRRAnswerTXT*)pKnownRRAnswer)->m_Txts) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service TXT answer already known... skipping!\n"), _DH());); + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service TXT answer already known (TTL:%u)... skipping!\n"), _DH(pService), pKnownRRAnswer->m_u32TTL);); pService->m_u32ReplyMask &= ~static_cast<uint32_t>(enuContentFlag::TXT); } _releaseTempServiceTxts(*pService); - } + }*/ } // Service match and enough TTL // // Check service tiebreak possibility if (pService->m_ProbeInformation.m_bTiebreakNeeded) { - stcRRDomain serviceDomain; + clsRRDomain serviceDomain; if ((_buildDomainForService(*pService, true, serviceDomain)) && (pKnownRRAnswer->m_Header.m_Domain == serviceDomain)) { // Service domain match if (enuAnswerType::SRV == pKnownRRAnswer->answerType()) { - stcRRDomain hostDomain; + clsRRDomain hostDomain; if ((_buildDomainForHost(m_pcHostName, hostDomain)) && - (hostDomain == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain)) // Host domain match + (hostDomain == ((clsRRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain)) // Host domain match { - // We've received an old message from ourselfs (same SRV) - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (SRV) won (was an old message)!\n"), _DH());); + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (SRV) won (was an old message)!\n"), _DH(pService));); pService->m_ProbeInformation.m_bTiebreakNeeded = false; } else { - if (((stcRRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain > hostDomain) // The OTHER domain is 'higher' -> LOST + if (((clsRRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain > hostDomain) // The OTHER domain is 'higher' -> LOST { // LOST tiebreak - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (SRV) LOST (lower)!\n"), _DH());); + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (SRV) LOST (lower)!\n"), _DH(pService));); _cancelProbingForService(*pService); pService->m_ProbeInformation.m_bTiebreakNeeded = false; } - else // WON tiebreak + else { - //TiebreakState = TiebreakState_Won; // We received an 'old' message from ourselfs -> Just ignore - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (SRV) won (higher)!\n"), _DH());); + // WON tiebreak + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (SRV) won (higher)!\n"), _DH(pService));); pService->m_ProbeInformation.m_bTiebreakNeeded = false; } } @@ -541,48 +538,47 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea else { DEBUG_EX_INFO(if (u32Answers) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Skipped %u known answers!\n"), _DH(), u32Answers);); - m_rUDPContext.flush(); + m_pUDPContext->flush(); } if (bResult) { // Check, if a reply is needed uint32_t u32ReplyNeeded = sendParameter.m_u32HostReplyMask; - for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) + for (const clsService* pService : m_Services) { u32ReplyNeeded |= pService->m_u32ReplyMask; } if (u32ReplyNeeded) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Sending answer(%s)...\n"), _DH(), _replyFlags2String(u32ReplyNeeded));); + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Sending %s answer(%s)...\n"), _DH(), (sendParameter.m_bUnicast ? "UC" : "MC"), _replyFlags2String(u32ReplyNeeded));); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Sending %s answer(%s)...\n"), _DH(), (sendParameter.m_bUnicast ? "UC" : "MC"), _replyFlags2String(u32ReplyNeeded));); - sendParameter.m_Response = stcSendParameter::enuResponseType::Response; + sendParameter.m_Response = clsSendParameter::enuResponseType::Response; sendParameter.m_bAuthorative = true; - bResult = _sendMDNSMessage(sendParameter); + bResult = _sendMessage(sendParameter); } - DEBUG_EX_INFO( - else + DEBUG_EX_INFO(else { DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: No reply needed\n"), _DH()); - } - ); + }); } else { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Something FAILED!\n"), _DH());); - m_rUDPContext.flush(); + m_pUDPContext->flush(); } // // Check and reset tiebreak-states - if (m_HostProbeInformation.m_bTiebreakNeeded) + if (m_ProbeInformation.m_bTiebreakNeeded) { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: UNSOLVED tiebreak-need for host domain!\n"), _DH());); - m_HostProbeInformation.m_bTiebreakNeeded = false; + m_ProbeInformation.m_bTiebreakNeeded = false; } - for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) + for (clsService* pService : m_Services) { if (pService->m_ProbeInformation.m_bTiebreakNeeded) { @@ -595,7 +591,7 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea } /* - MDNSResponder::clsHost::_parseResponse + clsLEAmDNS2_Host::_parseResponse Responses are of interest in two cases: 1. find domain name conflicts while probing @@ -621,7 +617,7 @@ bool MDNSResponder::clsHost::_parseQuery(const MDNSResponder::clsHost::stcMsgHea TXT - links the instance name to services TXTs Level 3: A/AAAA - links the host domain to an IP address */ -bool MDNSResponder::clsHost::_parseResponse(const MDNSResponder::clsHost::stcMsgHeader& p_MsgHeader) +bool clsLEAMDNSHost::_parseResponse(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse\n"));); //DEBUG_EX_INFO(_udpDump();); @@ -632,7 +628,6 @@ bool MDNSResponder::clsHost::_parseResponse(const MDNSResponder::clsHost::stcMsg if ((_hasQueriesWaitingForAnswers()) || // Waiting for query answers OR (_hasProbesWaitingForAnswers())) // Probe responses { - DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: Received a response\n"), _DH()); //_udpDump(); @@ -641,7 +636,7 @@ bool MDNSResponder::clsHost::_parseResponse(const MDNSResponder::clsHost::stcMsg bResult = true; // // Ignore questions here - stcRRQuestion dummyRRQ; + clsRRQuestion dummyRRQ; for (uint16_t qd = 0; ((bResult) && (qd < p_MsgHeader.m_u16QDCount)); ++qd) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: Received a response containing a question... ignoring!\n"), _DH());); @@ -650,11 +645,11 @@ bool MDNSResponder::clsHost::_parseResponse(const MDNSResponder::clsHost::stcMsg // // Read and collect answers - stcRRAnswer* pCollectedRRAnswers = 0; + clsRRAnswer* pCollectedRRAnswers = 0; uint32_t u32NumberOfAnswerRRs = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); for (uint32_t an = 0; ((bResult) && (an < u32NumberOfAnswerRRs)); ++an) { - stcRRAnswer* pRRAnswer = 0; + clsRRAnswer* pRRAnswer = 0; if (((bResult = _readRRAnswer(pRRAnswer))) && (pRRAnswer)) { @@ -684,14 +679,14 @@ bool MDNSResponder::clsHost::_parseResponse(const MDNSResponder::clsHost::stcMsg else // Some failure while reading answers { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: FAILED to read answers!\n"), _DH());); - m_rUDPContext.flush(); + m_pUDPContext->flush(); } // Delete collected answers while (pCollectedRRAnswers) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: DELETING answer!\n"), _DH());); - stcRRAnswer* pNextAnswer = pCollectedRRAnswers->m_pNext; + clsRRAnswer* pNextAnswer = pCollectedRRAnswers->m_pNext; delete pCollectedRRAnswers; pCollectedRRAnswers = pNextAnswer; } @@ -719,7 +714,7 @@ bool MDNSResponder::clsHost::_parseResponse(const MDNSResponder::clsHost::stcMsg } */ ); - m_rUDPContext.flush(); + m_pUDPContext->flush(); bResult = true; } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: FAILED!\n"), _DH());); @@ -727,7 +722,7 @@ bool MDNSResponder::clsHost::_parseResponse(const MDNSResponder::clsHost::stcMsg } /* - MDNSResponder::clsHost::_processAnswers + clsLEAmDNS2_Host::_processAnswers Host: A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 AAAA (01Cx): eg. esp8266.local AAAA OP TTL 1234:5678::90 @@ -740,7 +735,7 @@ bool MDNSResponder::clsHost::_parseResponse(const MDNSResponder::clsHost::stcMsg TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 */ -bool MDNSResponder::clsHost::_processAnswers(const MDNSResponder::clsHost::stcRRAnswer* p_pAnswers) +bool clsLEAMDNSHost::_processAnswers(const clsLEAMDNSHost::clsRRAnswer* p_pAnswers) { bool bResult = false; @@ -756,78 +751,70 @@ bool MDNSResponder::clsHost::_processAnswers(const MDNSResponder::clsHost::stcRR { bFoundNewKeyAnswer = false; - const stcRRAnswer* pRRAnswer = p_pAnswers; + const clsRRAnswer* pRRAnswer = p_pAnswers; while ((pRRAnswer) && (bResult)) { // 1. level answer (PTR) if (enuAnswerType::PTR == pRRAnswer->answerType()) - { - // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local - bResult = _processPTRAnswer((stcRRAnswerPTR*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new SRV or TXT answers to be linked to queries + { // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local + bResult = _processPTRAnswer((clsRRAnswerPTR*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new SRV or TXT answers to be linked to queries } // 2. level answers // SRV -> host domain and port else if (enuAnswerType::SRV == pRRAnswer->answerType()) - { - // eg. MyESP._http._tcp.local SRV xxxx xx yy zz 5000 esp8266.local - bResult = _processSRVAnswer((stcRRAnswerSRV*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new A/AAAA answers to be linked to queries + { // eg. MyESP._http._tcp.local SRV xxxx xx yy zz 5000 esp8266.local + bResult = _processSRVAnswer((clsRRAnswerSRV*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new A/AAAA answers to be linked to queries } // TXT -> Txts else if (enuAnswerType::TXT == pRRAnswer->answerType()) - { - // eg. MyESP_http._tcp.local TXT xxxx xx c#=1 - bResult = _processTXTAnswer((stcRRAnswerTXT*)pRRAnswer); + { // eg. MyESP_http._tcp.local TXT xxxx xx c#=1 + bResult = _processTXTAnswer((clsRRAnswerTXT*)pRRAnswer); } // 3. level answers #ifdef MDNS_IPV4_SUPPORT // A -> IPv4Address else if (enuAnswerType::A == pRRAnswer->answerType()) - { - // eg. esp8266.local A xxxx xx 192.168.2.120 - bResult = _processAAnswer((stcRRAnswerA*)pRRAnswer); + { // eg. esp8266.local A xxxx xx 192.168.2.120 + bResult = _processAAnswer((clsRRAnswerA*)pRRAnswer); } #endif #ifdef MDNS_IPV6_SUPPORT // AAAA -> IPv6Address else if (enuAnswerType::AAAA == pRRAnswer->answerType()) - { - // eg. esp8266.local AAAA xxxx xx 09cf::0c - bResult = _processAAAAAnswer((stcRRAnswerAAAA*)pRRAnswer); + { // eg. esp8266.local AAAA xxxx xx 09cf::0c + bResult = _processAAAAAnswer((clsRRAnswerAAAA*)pRRAnswer); } #endif // Finally check for probing conflicts // Host domain - if ((enuProbingStatus::InProgress == m_HostProbeInformation.m_ProbingStatus) && + if ((clsProbeInformation_Base::enuProbingStatus::InProgress == m_ProbeInformation.m_ProbingStatus) && ((enuAnswerType::A == pRRAnswer->answerType()) || (enuAnswerType::AAAA == pRRAnswer->answerType()))) { - - stcRRDomain hostDomain; + clsRRDomain hostDomain; if ((_buildDomainForHost(m_pcHostName, hostDomain)) && (pRRAnswer->m_Header.m_Domain == hostDomain)) { - bool bPossibleEcho = false; #ifdef MDNS_IPV4_SUPPORT if ((enuAnswerType::A == pRRAnswer->answerType()) && - (((stcRRAnswerA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V4))) + (((clsRRAnswerA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V4))) { - bPossibleEcho = true; } #endif #ifdef MDNS_IPV6_SUPPORT if ((enuAnswerType::AAAA == pRRAnswer->answerType()) && - (((stcRRAnswerAAAA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V6))) + (((clsRRAnswerAAAA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V6))) { - bPossibleEcho = true; } #endif if (!bPossibleEcho) { + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _processAnswers: Probing CONFLICT found with '%s.local'\n"), _DH(), m_pcHostName);); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processAnswers: Probing CONFLICT found with '%s.local'\n"), _DH(), m_pcHostName);); _cancelProbingForHost(); } @@ -838,19 +825,18 @@ bool MDNSResponder::clsHost::_processAnswers(const MDNSResponder::clsHost::stcRR } } // Service domains - for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) + for (clsService* pService : m_Services) { - if ((enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) && + if ((clsProbeInformation_Base::enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) && ((enuAnswerType::TXT == pRRAnswer->answerType()) || (enuAnswerType::SRV == pRRAnswer->answerType()))) { - - stcRRDomain serviceDomain; + clsRRDomain serviceDomain; if ((_buildDomainForService(*pService, true, serviceDomain)) && (pRRAnswer->m_Header.m_Domain == serviceDomain)) { - // TODO: Echo management needed? + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _processAnswers: Probing CONFLICT found with '%s'\n"), _DH(), _service2String(pService));); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processAnswers: Probing CONFLICT found with '%s'\n"), _DH(), _service2String(pService));); _cancelProbingForService(*pService); } @@ -867,10 +853,10 @@ bool MDNSResponder::clsHost::_processAnswers(const MDNSResponder::clsHost::stcRR } /* - MDNSResponder::clsHost::_processPTRAnswer (level 1) + clsLEAmDNS2_Host::_processPTRAnswer (level 1) */ -bool MDNSResponder::clsHost::_processPTRAnswer(const MDNSResponder::clsHost::stcRRAnswerPTR* p_pPTRAnswer, - bool& p_rbFoundNewKeyAnswer) +bool clsLEAMDNSHost::_processPTRAnswer(const clsLEAMDNSHost::clsRRAnswerPTR* p_pPTRAnswer, + bool& p_rbFoundNewKeyAnswer) { bool bResult = false; @@ -880,17 +866,16 @@ bool MDNSResponder::clsHost::_processPTRAnswer(const MDNSResponder::clsHost::stc // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local // Check pending service queries for eg. '_http._tcp' - stcQuery* pQuery = _findNextQueryByDomain(p_pPTRAnswer->m_Header.m_Domain, stcQuery::enuQueryType::Service, 0); + clsQuery* pQuery = _findNextQueryByDomain(p_pPTRAnswer->m_Header.m_Domain, clsQuery::enuQueryType::Service, 0); while (pQuery) { if (pQuery->m_bAwaitingAnswers) - { - // Find answer for service domain (eg. MyESP._http._tcp.local) - stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForServiceDomain(p_pPTRAnswer->m_PTRDomain); - if (pSQAnswer) // existing answer - { - if (p_pPTRAnswer->m_u32TTL) // Received update message - { + { // Find answer for service domain (eg. MyESP._http._tcp.local) + clsQuery::clsAnswer* pSQAnswer = pQuery->findAnswerForServiceDomain(p_pPTRAnswer->m_PTRDomain); + if (pSQAnswer) + { // existing answer + if (p_pPTRAnswer->m_u32TTL) + { // Received update message pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); // Update TTL tag DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processPTRAnswer: Updated TTL(%lu) for "), _DH(), p_pPTRAnswer->m_u32TTL); @@ -898,8 +883,8 @@ bool MDNSResponder::clsHost::_processPTRAnswer(const MDNSResponder::clsHost::stc DEBUG_OUTPUT.printf_P(PSTR("\n")); ); } - else // received goodbye-message - { + else + { // received goodbye-message pSQAnswer->m_TTLServiceDomain.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processPTRAnswer: 'Goodbye' received for "), _DH()); @@ -908,11 +893,11 @@ bool MDNSResponder::clsHost::_processPTRAnswer(const MDNSResponder::clsHost::stc ); } } - else if ((p_pPTRAnswer->m_u32TTL) && // Not just a goodbye-message - ((pSQAnswer = new stcQuery::stcAnswer))) // Not yet included -> add answer + else if ((p_pPTRAnswer->m_u32TTL) && // Not just a goodbye-message + ((pSQAnswer = new clsQuery::clsAnswer))) // Not yet included -> add answer { pSQAnswer->m_ServiceDomain = p_pPTRAnswer->m_PTRDomain; - pSQAnswer->m_QueryAnswerFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::ServiceDomain); + pSQAnswer->m_QueryAnswerFlags |= static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain); pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); //pSQAnswer->releaseServiceDomain(); @@ -925,10 +910,10 @@ bool MDNSResponder::clsHost::_processPTRAnswer(const MDNSResponder::clsHost::stc ); p_rbFoundNewKeyAnswer = true; - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::ServiceDomain), true); + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain), true); } } - pQuery = _findNextQueryByDomain(p_pPTRAnswer->m_Header.m_Domain, stcQuery::enuQueryType::Service, pQuery); + pQuery = _findNextQueryByDomain(p_pPTRAnswer->m_Header.m_Domain, clsQuery::enuQueryType::Service, pQuery); } } // else: No p_pPTRAnswer DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _processPTRAnswer: FAILED!\n"), _DH());); @@ -936,27 +921,28 @@ bool MDNSResponder::clsHost::_processPTRAnswer(const MDNSResponder::clsHost::stc } /* - MDNSResponder::clsHost::_processSRVAnswer (level 2) + clsLEAmDNS2_Host::_processSRVAnswer (level 2) */ -bool MDNSResponder::clsHost::_processSRVAnswer(const MDNSResponder::clsHost::stcRRAnswerSRV* p_pSRVAnswer, - bool& p_rbFoundNewKeyAnswer) +bool clsLEAMDNSHost::_processSRVAnswer(const clsLEAMDNSHost::clsRRAnswerSRV* p_pSRVAnswer, + bool& p_rbFoundNewKeyAnswer) { bool bResult = false; if ((bResult = (0 != p_pSRVAnswer))) { // eg. MyESP._http._tcp.local SRV xxxx xx yy zz 5000 esp8266.local - - stcQuery* pQuery = m_pQueries; - while (pQuery) + for (clsQuery::list::iterator it = m_Queries.begin(); ((bResult) && (it != m_Queries.end())); it++) { + clsQuery* pQuery = *it; + if (pQuery->m_bAwaitingAnswers) { - stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForServiceDomain(p_pSRVAnswer->m_Header.m_Domain); - if (pSQAnswer) // Answer for this service domain (eg. MyESP._http._tcp.local) available + clsQuery::clsAnswer* pSQAnswer = pQuery->findAnswerForServiceDomain(p_pSRVAnswer->m_Header.m_Domain); + if (pSQAnswer) { - if (p_pSRVAnswer->m_u32TTL) // First or update message (TTL != 0) - { + // Answer for this service domain (eg. MyESP._http._tcp.local) available + if (p_pSRVAnswer->m_u32TTL) + { // First or update message (TTL != 0) pSQAnswer->m_TTLHostDomainAndPort.set(p_pSRVAnswer->m_u32TTL); // Update TTL tag DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processSRVAnswer: Updated TTL(%lu) for "), _DH(), p_pSRVAnswer->m_u32TTL); @@ -971,7 +957,7 @@ bool MDNSResponder::clsHost::_processSRVAnswer(const MDNSResponder::clsHost::stc pSQAnswer->m_HostDomain = p_pSRVAnswer->m_SRVDomain; //pSQAnswer->releaseHostDomain(); pSQAnswer->m_u16Port = p_pSRVAnswer->m_u16Port; - pSQAnswer->m_QueryAnswerFlags |= (static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain) | static_cast<typeQueryAnswerType>(enuQueryAnswerType::Port)); + pSQAnswer->m_QueryAnswerFlags |= (static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain) | static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::Port)); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processSVRAnswer: Added host domain and port to "), _DH()); @@ -982,11 +968,11 @@ bool MDNSResponder::clsHost::_processSRVAnswer(const MDNSResponder::clsHost::stc ); p_rbFoundNewKeyAnswer = true; - _executeQueryCallback(*pQuery, *pSQAnswer, (static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain) | static_cast<typeQueryAnswerType>(enuQueryAnswerType::Port)), true); + _executeQueryCallback(*pQuery, *pSQAnswer, (static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain) | static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::Port)), true); } } - else // Goodby message - { + else + { // Goodby message pSQAnswer->m_TTLHostDomainAndPort.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processSRVAnswer: 'Goodbye' received for "), _DH()); @@ -996,34 +982,33 @@ bool MDNSResponder::clsHost::_processSRVAnswer(const MDNSResponder::clsHost::stc } } } // m_bAwaitingAnswers - pQuery = pQuery->m_pNext; - } // while(service query) + } // for(queries) } // else: No p_pSRVAnswer DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _processSRVAnswer: FAILED!\n"), _DH());); return bResult; } /* - MDNSResponder::clsHost::_processTXTAnswer (level 2) + clsLEAmDNS2_Host::_processTXTAnswer (level 2) */ -bool MDNSResponder::clsHost::_processTXTAnswer(const MDNSResponder::clsHost::stcRRAnswerTXT* p_pTXTAnswer) +bool clsLEAMDNSHost::_processTXTAnswer(const clsLEAMDNSHost::clsRRAnswerTXT* p_pTXTAnswer) { bool bResult = false; if ((bResult = (0 != p_pTXTAnswer))) { // eg. MyESP._http._tcp.local TXT xxxx xx c#=1 - - stcQuery* pQuery = m_pQueries; - while (pQuery) + for (clsQuery::list::iterator it = m_Queries.begin(); ((bResult) && (it != m_Queries.end())); it++) { + clsQuery* pQuery = *it; + if (pQuery->m_bAwaitingAnswers) { - stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForServiceDomain(p_pTXTAnswer->m_Header.m_Domain); - if (pSQAnswer) // Answer for this service domain (eg. MyESP._http._tcp.local) available - { - if (p_pTXTAnswer->m_u32TTL) // First or update message - { + clsQuery::clsAnswer* pSQAnswer = pQuery->findAnswerForServiceDomain(p_pTXTAnswer->m_Header.m_Domain); + if (pSQAnswer) + { // Answer for this service domain (eg. MyESP._http._tcp.local) available + if (p_pTXTAnswer->m_u32TTL) + { // First or update message pSQAnswer->m_TTLTxts.set(p_pTXTAnswer->m_u32TTL); // Update TTL tag DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processTXTAnswer: Updated TTL(%lu) for "), _DH(), p_pTXTAnswer->m_u32TTL); @@ -1033,7 +1018,7 @@ bool MDNSResponder::clsHost::_processTXTAnswer(const MDNSResponder::clsHost::stc if (!pSQAnswer->m_Txts.compare(p_pTXTAnswer->m_Txts)) { pSQAnswer->m_Txts = p_pTXTAnswer->m_Txts; - pSQAnswer->m_QueryAnswerFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts); + pSQAnswer->m_QueryAnswerFlags |= static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::Txts); //pSQAnswer->releaseTxts(); DEBUG_EX_INFO( @@ -1042,11 +1027,11 @@ bool MDNSResponder::clsHost::_processTXTAnswer(const MDNSResponder::clsHost::stc DEBUG_OUTPUT.println(); ); - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts), true); + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::Txts), true); } } - else // Goodby message - { + else + { // Goodby message pSQAnswer->m_TTLTxts.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processTXTAnswer: 'Goodbye' received for "), _DH()); @@ -1056,8 +1041,7 @@ bool MDNSResponder::clsHost::_processTXTAnswer(const MDNSResponder::clsHost::stc } } } // m_bAwaitingAnswers - pQuery = pQuery->m_pNext; - } // while(service query) + } // for(queries) } // else: No p_pTXTAnswer DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _processTXTAnswer: FAILED!\n"), _DH());); return bResult; @@ -1065,32 +1049,29 @@ bool MDNSResponder::clsHost::_processTXTAnswer(const MDNSResponder::clsHost::stc #ifdef MDNS_IPV4_SUPPORT /* - MDNSResponder::clsHost::_processAAnswer (level 3) + clsLEAmDNS2_Host::_processAAnswer (level 3) */ -bool MDNSResponder::clsHost::_processAAnswer(const MDNSResponder::clsHost::stcRRAnswerA* p_pAAnswer) +bool clsLEAMDNSHost::_processAAnswer(const clsLEAMDNSHost::clsRRAnswerA* p_pAAnswer) { bool bResult = false; if ((bResult = (0 != p_pAAnswer))) { // eg. esp8266.local A xxxx xx 192.168.2.120 - - stcQuery* pQuery = m_pQueries; - while (pQuery) + for (clsQuery::list::iterator it = m_Queries.begin(); ((bResult) && (it != m_Queries.end())); it++) { + clsQuery* pQuery = *it; + if (pQuery->m_bAwaitingAnswers) - { - // Look for answers to host queries - if ((p_pAAnswer->m_u32TTL) && // NOT just a goodbye message - (stcQuery::enuQueryType::Host == pQuery->m_QueryType) && // AND a host query - (pQuery->m_Domain == p_pAAnswer->m_Header.m_Domain)) // AND a matching host domain + { // Look for answers to host queries + if ((p_pAAnswer->m_u32TTL) && // NOT just a goodbye message + (clsQuery::enuQueryType::Host == pQuery->m_QueryType) && // AND a host query + (pQuery->m_Domain == p_pAAnswer->m_Header.m_Domain)) // AND a matching host domain { - - stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAnswer->m_Header.m_Domain); + clsQuery::clsAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAnswer->m_Header.m_Domain); if ((!pSQAnswer) && - ((pSQAnswer = new stcQuery::stcAnswer))) - { - // Add not yet included answer + ((pSQAnswer = new clsQuery::clsAnswer))) + { // Add not yet included answer pSQAnswer->m_HostDomain = p_pAAnswer->m_Header.m_Domain; //pSQAnswer->releaseHostDomain(); @@ -1101,21 +1082,20 @@ bool MDNSResponder::clsHost::_processAAnswer(const MDNSResponder::clsHost::stcRR DEBUG_OUTPUT.println(); ); - pSQAnswer->m_QueryAnswerFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain); - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain), true); + pSQAnswer->m_QueryAnswerFlags |= static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain); + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain), true); } } // Look for answers to service queries - stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAnswer->m_Header.m_Domain); - if (pSQAnswer) // Answer for this host domain (eg. esp8266.local) available - { - stcQuery::stcAnswer::stcIPAddress* pIPAddress = pSQAnswer->findIPv4Address(p_pAAnswer->m_IPAddress); + clsQuery::clsAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAnswer->m_Header.m_Domain); + if (pSQAnswer) + { // Answer for this host domain (eg. esp8266.local) available + clsQuery::clsAnswer::clsIPAddressWithTTL* pIPAddress = pSQAnswer->findIPv4Address(p_pAAnswer->m_IPAddress); if (pIPAddress) - { - // Already known IPv4 address - if (p_pAAnswer->m_u32TTL) // Valid TTL -> Update answers TTL - { + { // Already known IPv4 address + if (p_pAAnswer->m_u32TTL) + { // Valid TTL -> Update answers TTL pIPAddress->m_TTL.set(p_pAAnswer->m_u32TTL); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: Updated TTL(%lu) for "), _DH(), p_pAAnswer->m_u32TTL); @@ -1123,8 +1103,8 @@ bool MDNSResponder::clsHost::_processAAnswer(const MDNSResponder::clsHost::stcRR DEBUG_OUTPUT.printf_P(PSTR(" IPv4 address (%s)\n"), pIPAddress->m_IPAddress.toString().c_str()); ); } - else // 'Goodbye' message for known IPv4 address - { + else + { // 'Goodbye' message for known IPv4 address pIPAddress->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: 'Goodbye' received for "), _DH()); @@ -1134,23 +1114,21 @@ bool MDNSResponder::clsHost::_processAAnswer(const MDNSResponder::clsHost::stcRR } } else - { - // Until now unknown IPv4 address -> Add (if the message isn't just a 'Goodbye' note) - if (p_pAAnswer->m_u32TTL) // NOT just a 'Goodbye' message - { - pIPAddress = new stcQuery::stcAnswer::stcIPAddress(p_pAAnswer->m_IPAddress, p_pAAnswer->m_u32TTL); + { // Until now unknown IPv4 address -> Add (if the message isn't just a 'Goodbye' note) + if (p_pAAnswer->m_u32TTL) + { // NOT just a 'Goodbye' message + pIPAddress = new clsQuery::clsAnswer::clsIPAddressWithTTL(p_pAAnswer->m_IPAddress, p_pAAnswer->m_u32TTL); if ((pIPAddress) && (pSQAnswer->addIPv4Address(pIPAddress))) { - DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: Added IPv4 address to "), _DH()); _printRRDomain(pSQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(": %s\n"), pIPAddress->m_IPAddress.toString().c_str()); ); - pSQAnswer->m_QueryAnswerFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address); - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address), true); + pSQAnswer->m_QueryAnswerFlags |= static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address); + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address), true); } else { @@ -1160,8 +1138,7 @@ bool MDNSResponder::clsHost::_processAAnswer(const MDNSResponder::clsHost::stcRR } } } // m_bAwaitingAnswers - pQuery = pQuery->m_pNext; - } // while(service query) + } // for(queries) } // else: No p_pAAnswer DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: FAILED!\n"), _DH());); return bResult; @@ -1170,32 +1147,29 @@ bool MDNSResponder::clsHost::_processAAnswer(const MDNSResponder::clsHost::stcRR #ifdef MDNS_IPV6_SUPPORT /* - MDNSResponder::clsHost::_processAAAAAnswer (level 3) + clsLEAmDNS2_Host::_processAAAAAnswer (level 3) */ -bool MDNSResponder::clsHost::_processAAAAAnswer(const MDNSResponder::clsHost::stcRRAnswerAAAA* p_pAAAAAnswer) +bool clsLEAMDNSHost::_processAAAAAnswer(const clsLEAMDNSHost::clsRRAnswerAAAA* p_pAAAAAnswer) { bool bResult = false; if ((bResult = (0 != p_pAAAAAnswer))) { // eg. esp8266.local AAAA xxxx xx 0bf3::0c - - stcQuery* pQuery = m_pQueries; - while (pQuery) + for (clsQuery::list::iterator it = m_Queries.begin(); ((bResult) && (it != m_Queries.end())); it++) { + clsQuery* pQuery = *it; + if (pQuery->m_bAwaitingAnswers) - { - // Look for answers to host queries - if ((p_pAAAAAnswer->m_u32TTL) && // NOT just a goodbye message - (stcQuery::enuQueryType::Host == pQuery->m_QueryType) && // AND a host query - (pQuery->m_Domain == p_pAAAAAnswer->m_Header.m_Domain)) // AND a matching host domain + { // Look for answers to host queries + if ((p_pAAAAAnswer->m_u32TTL) && // NOT just a goodbye message + (clsQuery::enuQueryType::Host == pQuery->m_QueryType) && // AND a host query + (pQuery->m_Domain == p_pAAAAAnswer->m_Header.m_Domain)) // AND a matching host domain { - - stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAAAAnswer->m_Header.m_Domain); + clsQuery::clsAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAAAAnswer->m_Header.m_Domain); if ((!pSQAnswer) && - ((pSQAnswer = new stcQuery::stcAnswer))) - { - // Add not yet included answer + ((pSQAnswer = new clsQuery::clsAnswer))) + { // Add not yet included answer pSQAnswer->m_HostDomain = p_pAAAAAnswer->m_Header.m_Domain; //pSQAnswer->releaseHostDomain(); @@ -1206,21 +1180,20 @@ bool MDNSResponder::clsHost::_processAAAAAnswer(const MDNSResponder::clsHost::st DEBUG_OUTPUT.println(); ); - pSQAnswer->m_QueryAnswerFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain); - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain), true); + pSQAnswer->m_QueryAnswerFlags |= static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain); + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain), true); } } // Look for answers to service queries - stcQuery::stcAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAAAAnswer->m_Header.m_Domain); + clsQuery::clsAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAAAAnswer->m_Header.m_Domain); if (pSQAnswer) // Answer for this host domain (eg. esp8266.local) available { - stcQuery::stcAnswer::stcIPAddress* pIPAddress = pSQAnswer->findIPv6Address(p_pAAAAAnswer->m_IPAddress); + clsQuery::clsAnswer::clsIPAddressWithTTL* pIPAddress = pSQAnswer->findIPv6Address(p_pAAAAAnswer->m_IPAddress); if (pIPAddress) - { - // Already known IPv6 address - if (p_pAAAAAnswer->m_u32TTL) // Valid TTL -> Update answers TTL - { + { // Already known IPv6 address + if (p_pAAAAAnswer->m_u32TTL) + { // Valid TTL -> Update answers TTL pIPAddress->m_TTL.set(p_pAAAAAnswer->m_u32TTL); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processAAAAAnswer: Updated TTL(%lu) for "), _DH(), p_pAAAAAnswer->m_u32TTL); @@ -1228,8 +1201,8 @@ bool MDNSResponder::clsHost::_processAAAAAnswer(const MDNSResponder::clsHost::st DEBUG_OUTPUT.printf_P(PSTR(" IPv6 address (%s)\n"), pIPAddress->m_IPAddress.toString().c_str()); ); } - else // 'Goodbye' message for known IPv6 address - { + else + { // 'Goodbye' message for known IPv6 address pIPAddress->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processAAAAAnswer: 'Goodbye' received for "), _DH()); @@ -1239,23 +1212,22 @@ bool MDNSResponder::clsHost::_processAAAAAnswer(const MDNSResponder::clsHost::st } } else - { - // Until now unknown IPv6 address -> Add (if the message isn't just a 'Goodbye' note) - if (p_pAAAAAnswer->m_u32TTL) // NOT just a 'Goodbye' message + { // Until now unknown IPv6 address -> Add (if the message isn't just a 'Goodbye' note) + if (p_pAAAAAnswer->m_u32TTL) { - pIPAddress = new stcQuery::stcAnswer::stcIPAddress(p_pAAAAAnswer->m_IPAddress, p_pAAAAAnswer->m_u32TTL); + // NOT just a 'Goodbye' message + pIPAddress = new clsQuery::clsAnswer::clsIPAddressWithTTL(p_pAAAAAnswer->m_IPAddress, p_pAAAAAnswer->m_u32TTL); if ((pIPAddress) && (pSQAnswer->addIPv6Address(pIPAddress))) { - DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processAAAAAnswer: Added IPv6 address to "), _DH()); _printRRDomain(pSQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(": %s\n"), pIPAddress->m_IPAddress.toString().c_str()); ); - pSQAnswer->m_QueryAnswerFlags |= static_cast<uint32_t>(enuQueryAnswerType::IPv6Address); - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address), true); + pSQAnswer->m_QueryAnswerFlags |= static_cast<uint32_t>(clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address); + _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address), true); } else { @@ -1265,8 +1237,7 @@ bool MDNSResponder::clsHost::_processAAAAAnswer(const MDNSResponder::clsHost::st } } } // m_bAwaitingAnswers - pQuery = pQuery->m_pNext; - } // while(service query) + } // for(queries) } // else: No p_pAAAAAnswer return bResult; @@ -1275,11 +1246,13 @@ bool MDNSResponder::clsHost::_processAAAAAnswer(const MDNSResponder::clsHost::st /* + PROBING + */ /* - MDNSResponder::clsHost::_updateProbeStatus + clsLEAmDNS2_Host::_updateProbeStatus Manages the (outgoing) probing process. - If probing has not been started yet (ProbingStatus_NotStarted), the initial delay (see RFC 6762) is determined and @@ -1290,13 +1263,13 @@ bool MDNSResponder::clsHost::_processAAAAAnswer(const MDNSResponder::clsHost::st Conflict management is handled in '_parseResponse ff.' Tiebraking is handled in 'parseQuery ff.' */ -bool MDNSResponder::clsHost::_updateProbeStatus(void) +bool clsLEAMDNSHost::_updateProbeStatus(void) { bool bResult = true; // // Probe host domain - if ((enuProbingStatus::ReadyToStart == m_HostProbeInformation.m_ProbingStatus) && // Ready to get started AND + if ((clsProbeInformation_Base::enuProbingStatus::ReadyToStart == m_ProbeInformation.m_ProbingStatus) && // Ready to get started AND (( #ifdef MDNS_IPV4_SUPPORT _getResponderIPAddress(enuIPProtocolType::V4).isSet() // AND has IPv4 address @@ -1314,111 +1287,122 @@ bool MDNSResponder::clsHost::_updateProbeStatus(void) DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Starting host probing...\n"), _DH());); // First probe delay SHOULD be random 0-250 ms - m_HostProbeInformation.m_Timeout.reset(rand() % MDNS_PROBE_DELAY); - m_HostProbeInformation.m_ProbingStatus = enuProbingStatus::InProgress; + m_ProbeInformation.m_Timeout.reset(rand() % clsConsts::u32ProbeDelay); + m_ProbeInformation.m_ProbingStatus = clsProbeInformation_Base::enuProbingStatus::InProgress; } - else if ((enuProbingStatus::InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing AND - (m_HostProbeInformation.m_Timeout.expired())) // Time for next probe + else if ((clsProbeInformation_Base::enuProbingStatus::InProgress == m_ProbeInformation.m_ProbingStatus) && // Probing AND + (m_ProbeInformation.m_Timeout.expired())) // Time for next probe { - - if (MDNS_PROBE_COUNT > m_HostProbeInformation.m_u8SentCount) // Send next probe + if (clsConsts::u32ProbeCount > m_ProbeInformation.m_u8SentCount) { + // Send next probe if ((bResult = _sendHostProbe())) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Did sent host probe for '%s.local'\n\n"), _DH(), (m_pcHostName ? : ""));); - m_HostProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); - ++m_HostProbeInformation.m_u8SentCount; + m_ProbeInformation.m_Timeout.reset(clsConsts::u32ProbeDelay); + ++m_ProbeInformation.m_u8SentCount; } } - else // Probing finished + else { + // Probing finished DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("\n%s _updateProbeStatus: Done host probing for '%s.local'.\n\n\n"), _DH(), (m_pcHostName ? : ""));); - m_HostProbeInformation.m_ProbingStatus = enuProbingStatus::Done; - m_HostProbeInformation.m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + m_ProbeInformation.m_ProbingStatus = clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce; + m_ProbeInformation.m_Timeout.reset(esp8266::polledTimeout::oneShot::neverExpires); _callHostProbeResultCallback(true); // Prepare to announce host - m_HostProbeInformation.m_u8SentCount = 0; - m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + m_ProbeInformation.m_u8SentCount = 0; + m_ProbeInformation.m_Timeout.reset(clsConsts::u32AnnounceDelay); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Prepared host announcing.\n\n"), _DH());); } } // else: Probing already finished OR waiting for next time slot - else if ((enuProbingStatus::Done == m_HostProbeInformation.m_ProbingStatus) && - (m_HostProbeInformation.m_Timeout.expired())) + else if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == m_ProbeInformation.m_ProbingStatus) && + (m_ProbeInformation.m_Timeout.expired())) { - - if ((bResult = _announce(true, false))) // Don't announce services here + if ((bResult = _announce(true, false))) { - ++m_HostProbeInformation.m_u8SentCount; // 1.. + // Don't announce services here + ++m_ProbeInformation.m_u8SentCount; // 1.. - if (MDNS_ANNOUNCE_COUNT > m_HostProbeInformation.m_u8SentCount) + if (clsConsts::u32AnnounceCount > m_ProbeInformation.m_u8SentCount) { - m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY * pow(2, (m_HostProbeInformation.m_u8SentCount - 1))); // 2^(0..) -> 1, 2, 4, ... - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Announcing host '%s.local' (%lu).\n\n"), _DH(), (m_pcHostName ? : ""), m_HostProbeInformation.m_u8SentCount);); + m_ProbeInformation.m_Timeout.reset(clsConsts::u32AnnounceDelay * pow(2, (m_ProbeInformation.m_u8SentCount - 1))); // 2^(0..) -> 1, 2, 4, ... + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Announcing host '%s.local' (%lu).\n\n"), _DH(), (m_pcHostName ? : ""), m_ProbeInformation.m_u8SentCount);); } else { - m_HostProbeInformation.m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + m_ProbeInformation.m_ProbingStatus = clsProbeInformation_Base::enuProbingStatus::DoneFinally; + m_ProbeInformation.m_Timeout.reset(esp8266::polledTimeout::oneShot::neverExpires); + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Done host announcing for '%s.local'.\n"), _DH(), (m_pcHostName ? : ""));); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Done host announcing for '%s.local'.\n\n"), _DH(), (m_pcHostName ? : ""));); + //DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Done host announcing for '%s.local'.\n"), _DH(), (m_pcHostName ? : "")); } } } // // Probe services - for (stcService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) { - if (enuProbingStatus::ReadyToStart == pService->m_ProbeInformation.m_ProbingStatus) // Ready to get started - { + clsService* pService = *it; - pService->m_ProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); // More or equal than first probe for host domain - pService->m_ProbeInformation.m_ProbingStatus = enuProbingStatus::InProgress; + if (clsProbeInformation_Base::enuProbingStatus::ReadyToStart == pService->m_ProbeInformation.m_ProbingStatus) + { + // Ready to get started + pService->m_ProbeInformation.m_Timeout.reset(clsConsts::u32ProbeDelay); // More or equal than first probe for host domain + pService->m_ProbeInformation.m_ProbingStatus = clsProbeInformation_Base::enuProbingStatus::InProgress; } - else if ((enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing AND - (pService->m_ProbeInformation.m_Timeout.expired())) // Time for next probe + else if ((clsProbeInformation_Base::enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing AND + (pService->m_ProbeInformation.m_Timeout.expired())) // Time for next probe { - - if (MDNS_PROBE_COUNT > pService->m_ProbeInformation.m_u8SentCount) // Send next probe + if (clsConsts::u32ProbeCount > pService->m_ProbeInformation.m_u8SentCount) { + // Send next probe if ((bResult = _sendServiceProbe(*pService))) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Did sent service probe for '%s' (%u)\n\n"), _DH(), _service2String(pService), (pService->m_ProbeInformation.m_u8SentCount + 1));); - pService->m_ProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); + pService->m_ProbeInformation.m_Timeout.reset(clsConsts::u32ProbeDelay); ++pService->m_ProbeInformation.m_u8SentCount; } } - else // Probing finished + else { + // Probing finished DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("\n%s _updateProbeStatus: Done service probing '%s'\n\n\n"), _DH(), _service2String(pService));); - pService->m_ProbeInformation.m_ProbingStatus = enuProbingStatus::Done; - pService->m_ProbeInformation.m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + pService->m_ProbeInformation.m_ProbingStatus = clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce; + pService->m_ProbeInformation.m_Timeout.reset(esp8266::polledTimeout::oneShot::neverExpires); _callServiceProbeResultCallback(*pService, true); // Prepare to announce service pService->m_ProbeInformation.m_u8SentCount = 0; - pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + pService->m_ProbeInformation.m_Timeout.reset(clsConsts::u32AnnounceDelay); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Prepared service announcing.\n\n"), _DH());); } - } // else: Probing already finished OR waiting for next time slot - else if ((enuProbingStatus::Done == pService->m_ProbeInformation.m_ProbingStatus) && + } + else if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == pService->m_ProbeInformation.m_ProbingStatus) && (pService->m_ProbeInformation.m_Timeout.expired())) { - - if ((bResult = _announceService(*pService))) // Announce service + // Probing already finished OR waiting for next time slot + if ((bResult = _announceService(*pService))) { + // Announce service ++pService->m_ProbeInformation.m_u8SentCount; // 1.. - if (MDNS_ANNOUNCE_COUNT > pService->m_ProbeInformation.m_u8SentCount) + if (clsConsts::u32AnnounceCount > pService->m_ProbeInformation.m_u8SentCount) { - pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY * pow(2, (pService->m_ProbeInformation.m_u8SentCount - 1))); // 2^(0..) -> 1, 2, 4, ... + pService->m_ProbeInformation.m_Timeout.reset(clsConsts::u32AnnounceDelay * pow(2, (pService->m_ProbeInformation.m_u8SentCount - 1))); // 2^(0..) -> 1, 2, 4, ... DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Announcing service '%s' (%lu)\n\n"), _DH(), _service2String(pService), pService->m_ProbeInformation.m_u8SentCount);); } else { - pService->m_ProbeInformation.m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + pService->m_ProbeInformation.m_ProbingStatus = clsProbeInformation_Base::enuProbingStatus::DoneFinally; + pService->m_ProbeInformation.m_Timeout.reset(esp8266::polledTimeout::oneShot::neverExpires); + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Done service announcing for '%s'\n"), _DH(), _service2String(pService));); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Done service announcing for '%s'\n\n"), _DH(), _service2String(pService));); + //DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Done service announcing for '%s'\n"), _DH(), _service2String(pService)); } } } @@ -1428,44 +1412,48 @@ bool MDNSResponder::clsHost::_updateProbeStatus(void) } /* - MDNSResponder::clsHost::_resetProbeStatus + clsLEAmDNS2_Host::_resetProbeStatus Resets the probe status. If 'p_bRestart' is set, the status is set to ProbingStatus_NotStarted. Consequently, when running 'updateProbeStatus' (which is done in every '_update' loop), the probing process is restarted. + */ -bool MDNSResponder::clsHost::_resetProbeStatus(bool p_bRestart /*= true*/) +bool clsLEAMDNSHost::_resetProbeStatus(bool p_bRestart /*= true*/) { - m_HostProbeInformation.clear(false); - m_HostProbeInformation.m_ProbingStatus = (p_bRestart ? enuProbingStatus::ReadyToStart : enuProbingStatus::Done); + m_ProbeInformation.clear(false); + m_ProbeInformation.m_ProbingStatus = (p_bRestart ? clsProbeInformation_Base::enuProbingStatus::ReadyToStart : clsProbeInformation_Base::enuProbingStatus::DoneFinally); - for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) + for (clsService* pService : m_Services) { pService->m_ProbeInformation.clear(false); - pService->m_ProbeInformation.m_ProbingStatus = (p_bRestart ? enuProbingStatus::ReadyToStart : enuProbingStatus::Done); + pService->m_ProbeInformation.m_ProbingStatus = (p_bRestart ? clsProbeInformation_Base::enuProbingStatus::ReadyToStart : clsProbeInformation_Base::enuProbingStatus::DoneFinally); } return true; } /* - MDNSResponder::clsHost::_hasProbesWaitingForAnswers + clsLEAmDNS2_Host::_hasProbesWaitingForAnswers + */ -bool MDNSResponder::clsHost::_hasProbesWaitingForAnswers(void) const +bool clsLEAMDNSHost::_hasProbesWaitingForAnswers(void) const { - bool bResult = ((enuProbingStatus::InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing - (0 < m_HostProbeInformation.m_u8SentCount)); // And really probing + bool bResult = ((clsProbeInformation_Base::enuProbingStatus::InProgress == m_ProbeInformation.m_ProbingStatus) && // Probing + (0 < m_ProbeInformation.m_u8SentCount)); // And really probing - for (stcService* pService = m_pServices; ((!bResult) && (pService)); pService = pService->m_pNext) + for (clsService::list::const_iterator it = m_Services.cbegin(); ((!bResult) && (it != m_Services.cend())); it++) { - bResult = ((enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing - (0 < pService->m_ProbeInformation.m_u8SentCount)); // And really probing + clsService* pService = *it; + + bResult = ((clsProbeInformation_Base::enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing + (0 < pService->m_ProbeInformation.m_u8SentCount)); // And really probing } return bResult; } /* - MDNSResponder::clsHost::_sendHostProbe + clsLEAmDNS2_Host::_sendHostProbe Asks (probes) in the local network for the planned host domain - (eg. esp8266.local) @@ -1474,50 +1462,52 @@ bool MDNSResponder::clsHost::_hasProbesWaitingForAnswers(void) const the 'knwon answers' section of the query. Host domain: - A/AAAA (eg. esp8266.esp -> 192.168.2.120) + */ -bool MDNSResponder::clsHost::_sendHostProbe(void) +bool clsLEAMDNSHost::_sendHostProbe(void) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendHostProbe (%s.local, %lu)\n"), _DH(), m_pcHostName, millis());); bool bResult = true; // Requests for host domain - stcSendParameter sendParameter; + clsSendParameter sendParameter; sendParameter.m_bCacheFlush = false; // RFC 6762 10.2 - sendParameter.m_pQuestions = new stcRRQuestion; - if (((bResult = (0 != sendParameter.m_pQuestions))) && - ((bResult = _buildDomainForHost(m_pcHostName, sendParameter.m_pQuestions->m_Header.m_Domain)))) + clsRRQuestion* pNewRRQuestion = new clsRRQuestion; + if (((bResult = (0 != pNewRRQuestion))) && + ((bResult = _buildDomainForHost(m_pcHostName, pNewRRQuestion->m_Header.m_Domain)))) { - //sendParameter.m_pQuestions->m_bUnicast = true; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet + pNewRRQuestion->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; + pNewRRQuestion->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet + + sendParameter.m_RRQuestions.push_back(pNewRRQuestion); // Add known answers #ifdef MDNS_IPV4_SUPPORT - sendParameter.m_u32HostReplyMask |= static_cast<uint32_t>(enuContentFlag::A); // Add A answer + sendParameter.m_u32HostReplyMask |= static_cast<uint32_t>(enuContentFlag::A); // Add A answer #endif #ifdef MDNS_IPV6_SUPPORT - sendParameter.m_u32HostReplyMask |= static_cast<uint32_t>(enuContentFlag::AAAA); // Add AAAA answer + sendParameter.m_u32HostReplyMask |= static_cast<uint32_t>(enuContentFlag::AAAA); // Add AAAA answer #endif } else { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _sendHostProbe: FAILED to create host question!\n"), _DH());); - if (sendParameter.m_pQuestions) + if (pNewRRQuestion) { - delete sendParameter.m_pQuestions; - sendParameter.m_pQuestions = 0; + delete pNewRRQuestion; + pNewRRQuestion = 0; } } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendHostProbe: FAILED!\n"), _DH());); return ((bResult) && - (_sendMDNSMessage(sendParameter))); + (_sendMessage(sendParameter))); } /* - MDNSResponder::clsHost::_sendServiceProbe + clsLEAmDNS2_Host::_sendServiceProbe Asks (probes) in the local network for the planned service instance domain - (eg. MyESP._http._tcp.local). @@ -1527,25 +1517,27 @@ bool MDNSResponder::clsHost::_sendHostProbe(void) Service domain: - SRV (eg. MyESP._http._tcp.local -> 5000 esp8266.local) - PTR NAME (eg. _http._tcp.local -> MyESP._http._tcp.local) (TODO: Check if needed, maybe TXT is better) + */ -bool MDNSResponder::clsHost::_sendServiceProbe(stcService& p_rService) +bool clsLEAMDNSHost::_sendServiceProbe(clsService& p_rService) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendServiceProbe (%s, %lu)\n"), _DH(), _service2String(&p_rService), millis());); bool bResult = true; // Requests for service instance domain - stcSendParameter sendParameter; + clsSendParameter sendParameter; sendParameter.m_bCacheFlush = false; // RFC 6762 10.2 - sendParameter.m_pQuestions = new stcRRQuestion; - if (((bResult = (0 != sendParameter.m_pQuestions))) && - ((bResult = _buildDomainForService(p_rService, true, sendParameter.m_pQuestions->m_Header.m_Domain)))) + clsRRQuestion* pNewRRQuestion = new clsRRQuestion; + if (((bResult = (0 != pNewRRQuestion))) && + ((bResult = _buildDomainForService(p_rService, true, pNewRRQuestion->m_Header.m_Domain)))) { + pNewRRQuestion->m_bUnicast = true; + pNewRRQuestion->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; + pNewRRQuestion->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet - sendParameter.m_pQuestions->m_bUnicast = true; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet + sendParameter.m_RRQuestions.push_back(pNewRRQuestion); // Add known answers p_rService.m_u32ReplyMask = (static_cast<uint32_t>(enuContentFlag::SRV) | static_cast<uint32_t>(enuContentFlag::PTR_NAME)); // Add SRV and PTR NAME answers @@ -1553,30 +1545,31 @@ bool MDNSResponder::clsHost::_sendServiceProbe(stcService& p_rService) else { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _sendServiceProbe: FAILED to create service question!\n"), _DH());); - if (sendParameter.m_pQuestions) + if (pNewRRQuestion) { - delete sendParameter.m_pQuestions; - sendParameter.m_pQuestions = 0; + delete pNewRRQuestion; + pNewRRQuestion = 0; } } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendServiceProbe: FAILED!\n"), _DH());); return ((bResult) && - (_sendMDNSMessage(sendParameter))); + (_sendMessage(sendParameter))); } /* - MDNSResponder::clsHost::_cancelProbingForHost + clsLEAmDNS2_Host::_cancelProbingForHost + */ -bool MDNSResponder::clsHost::_cancelProbingForHost(void) +bool clsLEAMDNSHost::_cancelProbingForHost(void) { bool bResult = false; - m_HostProbeInformation.clear(false); + m_ProbeInformation.clear(false); // Send host notification bResult = _callHostProbeResultCallback(false); - for (stcService* pService = m_pServices; ((!bResult) && (pService)); pService = pService->m_pNext) + for (clsService* pService : m_Services) { bResult = _cancelProbingForService(*pService); } @@ -1584,9 +1577,10 @@ bool MDNSResponder::clsHost::_cancelProbingForHost(void) } /* - MDNSResponder::clsHost::_cancelProbingForService + clsLEAmDNS2_Host::_cancelProbingForService + */ -bool MDNSResponder::clsHost::_cancelProbingForService(stcService& p_rService) +bool clsLEAMDNSHost::_cancelProbingForService(clsService& p_rService) { p_rService.m_ProbeInformation.clear(false); @@ -1595,81 +1589,53 @@ bool MDNSResponder::clsHost::_cancelProbingForService(stcService& p_rService) } /* - MDNSResponder::clsHost::_callHostProbeResultCallback + clsLEAmDNS2_Host::_callHostProbeResultCallback */ -bool MDNSResponder::clsHost::_callHostProbeResultCallback(bool p_bResult) +bool clsLEAMDNSHost::_callHostProbeResultCallback(bool p_bResult) { - if (m_HostProbeInformation.m_fnProbeResultCallback) + if (m_ProbeInformation.m_fnProbeResultCallback) { - m_HostProbeInformation.m_fnProbeResultCallback(*this, m_pcHostName, p_bResult); + m_ProbeInformation.m_fnProbeResultCallback(*this, m_pcHostName, p_bResult); } else if (!p_bResult) { // Auto-Handle failure by changing the host name, use '-' as divider between base name and index - char* pcHostDomainTemp = strdup(m_pcHostName); - if (pcHostDomainTemp) - { - if (MDNSResponder::indexDomain(pcHostDomainTemp, "-", 0)) - { - setHostName(pcHostDomainTemp); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _callHostProbeResultCallback: FAILED to update host domain '%s'!\n"), _DH(), (m_pcHostName ? : ""));); - } - free(pcHostDomainTemp); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _callHostProbeResultCallback: FAILED to copy host domain '%s'!\n"), _DH(), (m_pcHostName ? : ""));); - } + indexHostName(); + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _callHostProbeResultCallback: Changed Host Name: %s\n"), _DH(), (m_pcHostName ? : ""))); } return true; } /* - MDNSResponder::clsHost::_callServiceProbeResultCallback + clsLEAmDNS2_Host::_callServiceProbeResultCallback */ -bool MDNSResponder::clsHost::_callServiceProbeResultCallback(MDNSResponder::clsHost::stcService& p_rService, - bool p_bResult) +bool clsLEAMDNSHost::_callServiceProbeResultCallback(clsLEAMDNSHost::clsService& p_rService, + bool p_bResult) { if (p_rService.m_ProbeInformation.m_fnProbeResultCallback) { - p_rService.m_ProbeInformation.m_fnProbeResultCallback(*this, p_rService, p_rService.m_pcName, p_bResult); + p_rService.m_ProbeInformation.m_fnProbeResultCallback(p_rService, p_rService.instanceName(), p_bResult); } else if (!p_bResult) { // Auto-Handle failure by changing the service name, use ' #' as divider between base name and index - char* pcServiceNameTemp = strdup(p_rService.m_pcName); - if (pcServiceNameTemp) - { - if (MDNSResponder::indexDomain(pcServiceNameTemp, " #", 0)) - { - setServiceName(&p_rService, pcServiceNameTemp); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _callServiceProbeResultCallback: FAILED to update service name for '%s'!\n"), _DH(), _service2String(&p_rService));); - } - free(pcServiceNameTemp); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _callServiceProbeResultCallback: FAILED to copy service name for '%s'!\n"), _DH(), _service2String(&p_rService));); - } + p_rService.indexInstanceName(); + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _callServiceProbeResultCallback: Changed Service Domain: %s\n"), _DH(), _service2String(&p_rService))); } return true; } -/** +/* + ANNOUNCING + */ /* - MDNSResponder::clsHost::_announce + clsLEAmDNS2_Host::_announce Announces the host domain: - A/AAAA (eg. esp8266.local -> 192.168.2.120) @@ -1684,18 +1650,19 @@ bool MDNSResponder::clsHost::_callServiceProbeResultCallback(MDNSResponder::clsH Goodbye (Un-Announcing) for the host domain and all services is also handled here. Goodbye messages are created by setting the TTL for the answer to 0, this happens inside the '_writeXXXAnswer' procs via 'sendParameter.m_bUnannounce = true' + */ -bool MDNSResponder::clsHost::_announce(bool p_bAnnounce, - bool p_bIncludeServices) +bool clsLEAMDNSHost::_announce(bool p_bAnnounce, + bool p_bIncludeServices) { bool bResult = false; - stcSendParameter sendParameter; - if (enuProbingStatus::Done == m_HostProbeInformation.m_ProbingStatus) + clsSendParameter sendParameter; + if (clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == m_ProbeInformation.m_ProbingStatus) { bResult = true; - sendParameter.m_Response = stcSendParameter::enuResponseType::Unsolicited; // Announces are 'Unsolicited authorative responses' + sendParameter.m_Response = clsSendParameter::enuResponseType::Unsolicited; // Announces are 'Unsolicited authorative responses' sendParameter.m_bAuthorative = true; sendParameter.m_bCacheFlush = true; // RFC 6762 8.3 sendParameter.m_bUnannounce = !p_bAnnounce; // When unannouncing, the TTL is set to '0' while creating the answers @@ -1716,12 +1683,14 @@ bool MDNSResponder::clsHost::_announce(bool p_bAnnounce, if (p_bIncludeServices) { // Announce services (service type, name, SRV (location) and TXTs) - for (stcService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + for (clsService* pService : m_Services) { - if (enuProbingStatus::Done == pService->m_ProbeInformation.m_ProbingStatus) + if (clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == pService->m_ProbeInformation.m_ProbingStatus) { - pService->m_u32ReplyMask = (static_cast<uint32_t>(enuContentFlag::PTR_TYPE) | static_cast<uint32_t>(enuContentFlag::PTR_NAME) | static_cast<uint32_t>(enuContentFlag::SRV) | static_cast<uint32_t>(enuContentFlag::TXT)); - + pService->m_u32ReplyMask = (static_cast<uint32_t>(enuContentFlag::PTR_TYPE) | + static_cast<uint32_t>(enuContentFlag::PTR_NAME) | + static_cast<uint32_t>(enuContentFlag::SRV) | + static_cast<uint32_t>(enuContentFlag::TXT)); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _announce: Announcing service '%s' (content %s)\n"), _DH(), _service2String(pService), _replyFlags2String(pService->m_u32ReplyMask));); } } @@ -1729,22 +1698,22 @@ bool MDNSResponder::clsHost::_announce(bool p_bAnnounce, } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _announce: FAILED!\n"), _DH());); return ((bResult) && - (_sendMDNSMessage(sendParameter))); + (_sendMessage(sendParameter))); } /* - MDNSResponder::clsHost::_announceService + clsLEAmDNS2_Host::_announceService + */ -bool MDNSResponder::clsHost::_announceService(MDNSResponder::clsHost::stcService& p_rService, - bool p_bAnnounce /*= true*/) +bool clsLEAMDNSHost::_announceService(clsLEAMDNSHost::clsService& p_rService, + bool p_bAnnounce /*= true*/) { bool bResult = false; - stcSendParameter sendParameter; - if (enuProbingStatus::Done == p_rService.m_ProbeInformation.m_ProbingStatus) + clsSendParameter sendParameter; + if (clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == p_rService.m_ProbeInformation.m_ProbingStatus) { - - sendParameter.m_Response = stcSendParameter::enuResponseType::Unsolicited; // Announces are 'Unsolicited authorative responses' + sendParameter.m_Response = clsSendParameter::enuResponseType::Unsolicited; // Announces are 'Unsolicited authorative responses' sendParameter.m_bAuthorative = true; sendParameter.m_bUnannounce = !p_bAnnounce; // When unannouncing, the TTL is set to '0' while creating the answers @@ -1752,23 +1721,28 @@ bool MDNSResponder::clsHost::_announceService(MDNSResponder::clsHost::stcService sendParameter.m_u32HostReplyMask = 0; // Announce services (service type, name, SRV (location) and TXTs) - p_rService.m_u32ReplyMask = (static_cast<uint32_t>(enuContentFlag::PTR_TYPE) | static_cast<uint32_t>(enuContentFlag::PTR_NAME) | static_cast<uint32_t>(enuContentFlag::SRV) | static_cast<uint32_t>(enuContentFlag::TXT)); + p_rService.m_u32ReplyMask = (static_cast<uint32_t>(enuContentFlag::PTR_TYPE) | + static_cast<uint32_t>(enuContentFlag::PTR_NAME) | + static_cast<uint32_t>(enuContentFlag::SRV) | + static_cast<uint32_t>(enuContentFlag::TXT)); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _announceService: Announcing service '%s' (content: %s)\n"), _DH(), _service2String(&p_rService), _replyFlags2String(p_rService.m_u32ReplyMask));); bResult = true; } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _announceService: FAILED!\n"), _DH());); return ((bResult) && - (_sendMDNSMessage(sendParameter))); + (_sendMessage(sendParameter))); } -/** +/* + QUERY CACHE + */ /* - MDNSResponder::clsHost::_checkQueryCache + clsLEAmDNS2_Host::_checkQueryCache For any 'living' query (m_bAwaitingAnswers == true) all available answers (their components) are checked for topicality based on the stored reception time and the answers TTL. @@ -1776,29 +1750,33 @@ bool MDNSResponder::clsHost::_announceService(MDNSResponder::clsHost::stcService When no update arrived (in time), the component is removed from the answer (cache). */ -bool MDNSResponder::clsHost::_checkQueryCache(void) +bool clsLEAMDNSHost::_checkQueryCache(void) { bool bResult = true; DEBUG_EX_INFO( bool printedInfo = false; ); - for (stcQuery* pQuery = m_pQueries; ((bResult) && (pQuery)); pQuery = pQuery->m_pNext) + for (clsQuery::list::iterator itQ = m_Queries.begin(); ((bResult) && (itQ != m_Queries.end())); itQ++) { + clsQuery* pQuery = *itQ; // // Resend dynamic queries, if not already done often enough - if ((!pQuery->m_bLegacyQuery) && + if ((!pQuery->m_bStaticQuery) && (pQuery->m_ResendTimeout.expired())) { - - if ((bResult = _sendMDNSQuery(*pQuery))) + if ((bResult = _sendQuery(*pQuery))) { // The re-query rate is increased to more than one hour (RFC 6762 5.2) ++pQuery->m_u8SentCount; - uint32_t u32NewDelay = (MDNS_DYNAMIC_QUERY_RESEND_DELAY * pow(2, std::min((pQuery->m_u8SentCount - 1), 12))); + uint32_t u32NewDelay = (clsConsts::u32DynamicQueryResendDelay * pow(2, std::min((pQuery->m_u8SentCount - 1), 12))); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Next query in %u seconds!\n"), _DH(), (u32NewDelay));); pQuery->m_ResendTimeout.reset(u32NewDelay); } + else + { + break; + } DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: %s to resend query!\n"), _DH(), (bResult ? "Succeeded" : "FAILED")); printedInfo = true; @@ -1809,25 +1787,22 @@ bool MDNSResponder::clsHost::_checkQueryCache(void) // Schedule updates for cached answers if (pQuery->m_bAwaitingAnswers) { - stcQuery::stcAnswer* pSQAnswer = pQuery->m_pAnswers; - while ((bResult) && - (pSQAnswer)) + clsQuery::clsAnswer::list expiredAnswers; + for (clsQuery::clsAnswer::list::iterator itQA = pQuery->m_Answers.begin(); ((bResult) && (itQA != pQuery->m_Answers.end())); itQA++) { - stcQuery::stcAnswer* pNextSQAnswer = pSQAnswer->m_pNext; + clsQuery::clsAnswer* pQAnswer = *itQA; // 1. level answer if ((bResult) && - (pSQAnswer->m_TTLServiceDomain.flagged())) + (pQAnswer->m_TTLServiceDomain.flagged())) { - - if (!pSQAnswer->m_TTLServiceDomain.finalTimeoutLevel()) + if (!pQAnswer->m_TTLServiceDomain.finalTimeoutLevel()) { - - bResult = ((_sendMDNSQuery(*pQuery)) && - (pSQAnswer->m_TTLServiceDomain.restart())); + bResult = ((_sendQuery(*pQuery)) && + (pQAnswer->m_TTLServiceDomain.restart())); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: PTR update scheduled for "), _DH()); - _printRRDomain(pSQAnswer->m_ServiceDomain); + _printRRDomain(pQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(" %s\n"), (bResult ? "OK" : "FAILURE")); printedInfo = true; ); @@ -1835,16 +1810,15 @@ bool MDNSResponder::clsHost::_checkQueryCache(void) else { // Timed out! -> Delete - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::ServiceDomain), false); + _executeQueryCallback(*pQuery, *pQAnswer, static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain), false); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Will remove PTR answer for "), _DH()); - _printRRDomain(pSQAnswer->m_ServiceDomain); + _printRRDomain(pQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR("\n")); printedInfo = true; ); - bResult = pQuery->removeAnswer(pSQAnswer); - pSQAnswer = 0; + expiredAnswers.push_back(pQAnswer); continue; // Don't use this answer anymore } } // ServiceDomain flagged @@ -1852,17 +1826,15 @@ bool MDNSResponder::clsHost::_checkQueryCache(void) // 2. level answers // HostDomain & Port (from SRV) if ((bResult) && - (pSQAnswer->m_TTLHostDomainAndPort.flagged())) + (pQAnswer->m_TTLHostDomainAndPort.flagged())) { - - if (!pSQAnswer->m_TTLHostDomainAndPort.finalTimeoutLevel()) + if (!pQAnswer->m_TTLHostDomainAndPort.finalTimeoutLevel()) { - - bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_SRV)) && - (pSQAnswer->m_TTLHostDomainAndPort.restart())); + bResult = ((_sendQuery(pQAnswer->m_ServiceDomain, DNS_RRTYPE_SRV)) && + (pQAnswer->m_TTLHostDomainAndPort.restart())); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: SRV update scheduled for "), _DH()); - _printRRDomain(pSQAnswer->m_ServiceDomain); + _printRRDomain(pQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(" host domain and port %s\n"), (bResult ? "OK" : "FAILURE")); printedInfo = true; ); @@ -1872,45 +1844,43 @@ bool MDNSResponder::clsHost::_checkQueryCache(void) // Timed out! -> Delete DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Will remove SRV answer for "), _DH()); - _printRRDomain(pSQAnswer->m_ServiceDomain); + _printRRDomain(pQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); printedInfo = true; ); // Delete - pSQAnswer->m_HostDomain.clear(); + pQAnswer->m_HostDomain.clear(); //pSQAnswer->releaseHostDomain(); - pSQAnswer->m_u16Port = 0; - pSQAnswer->m_TTLHostDomainAndPort.set(0); - typeQueryAnswerType queryAnswerContentFlags = (static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain) | static_cast<typeQueryAnswerType>(enuQueryAnswerType::Port)); + pQAnswer->m_u16Port = 0; + pQAnswer->m_TTLHostDomainAndPort.set(0); + clsQuery::clsAnswer::typeQueryAnswerType queryAnswerContentFlags = (static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain) | static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::Port)); // As the host domain is the base for the IPv4- and IPv6Address, remove these too #ifdef MDNS_IPV4_SUPPORT - pSQAnswer->releaseIPv4Addresses(); - queryAnswerContentFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address); + pQAnswer->releaseIPv4Addresses(); + queryAnswerContentFlags |= static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address); #endif #ifdef MDNS_IPV6_SUPPORT - pSQAnswer->releaseIPv6Addresses(); - queryAnswerContentFlags |= static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address); + pQAnswer->releaseIPv6Addresses(); + queryAnswerContentFlags |= static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address); #endif // Remove content flags for deleted answer parts - pSQAnswer->m_QueryAnswerFlags &= ~queryAnswerContentFlags; - _executeQueryCallback(*pQuery, *pSQAnswer, queryAnswerContentFlags, false); + pQAnswer->m_QueryAnswerFlags &= ~queryAnswerContentFlags; + _executeQueryCallback(*pQuery, *pQAnswer, queryAnswerContentFlags, false); } } // HostDomainAndPort flagged // Txts (from TXT) if ((bResult) && - (pSQAnswer->m_TTLTxts.flagged())) + (pQAnswer->m_TTLTxts.flagged())) { - - if (!pSQAnswer->m_TTLTxts.finalTimeoutLevel()) + if (!pQAnswer->m_TTLTxts.finalTimeoutLevel()) { - - bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_TXT)) && - (pSQAnswer->m_TTLTxts.restart())); + bResult = ((_sendQuery(pQAnswer->m_ServiceDomain, DNS_RRTYPE_TXT)) && + (pQAnswer->m_TTLTxts.restart())); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: TXT update scheduled for "), _DH()); - _printRRDomain(pSQAnswer->m_ServiceDomain); + _printRRDomain(pQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(" TXTs %s\n"), (bResult ? "OK" : "FAILURE")); printedInfo = true; ); @@ -1920,47 +1890,43 @@ bool MDNSResponder::clsHost::_checkQueryCache(void) // Timed out! -> Delete DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Will remove TXT answer for "), _DH()); - _printRRDomain(pSQAnswer->m_ServiceDomain); + _printRRDomain(pQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); printedInfo = true; ); // Delete - pSQAnswer->m_Txts.clear(); - pSQAnswer->m_TTLTxts.set(0); + pQAnswer->m_Txts.clear(); + pQAnswer->m_TTLTxts.set(0); // Remove content flags for deleted answer parts - pSQAnswer->m_QueryAnswerFlags &= ~static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts); - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts), false); + pQAnswer->m_QueryAnswerFlags &= ~static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::Txts); + _executeQueryCallback(*pQuery, *pQAnswer, static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::Txts), false); } } // TXTs flagged // 3. level answers #ifdef MDNS_IPV4_SUPPORT // IPv4Address (from A) - stcQuery::stcAnswer::stcIPAddress* pIPv4Address = pSQAnswer->m_pIPv4Addresses; + clsQuery::clsAnswer::clsIPAddressWithTTL::list expiredIPv4Addresses; bool bAUpdateQuerySent = false; - while ((pIPv4Address) && - (bResult)) + for (clsQuery::clsAnswer::clsIPAddressWithTTL::list::iterator itQAIPv4 = pQAnswer->m_IPv4Addresses.begin(); ((bResult) && (itQAIPv4 != pQAnswer->m_IPv4Addresses.end())); itQAIPv4++) { - - stcQuery::stcAnswer::stcIPAddress* pNextIPv4Address = pIPv4Address->m_pNext; // Get 'next' early, as 'current' may be deleted at the end... + clsQuery::clsAnswer::clsIPAddressWithTTL* pIPv4Address = *itQAIPv4; if (pIPv4Address->m_TTL.flagged()) { - - if (!pIPv4Address->m_TTL.finalTimeoutLevel()) // Needs update + if (!pIPv4Address->m_TTL.finalTimeoutLevel()) { - + // Needs update if ((bAUpdateQuerySent) || - ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_A)))) + ((bResult = _sendQuery(pQAnswer->m_HostDomain, DNS_RRTYPE_A)))) { - pIPv4Address->m_TTL.restart(); bAUpdateQuerySent = true; DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: IPv4 update scheduled for "), _DH()); - _printRRDomain(pSQAnswer->m_ServiceDomain); + _printRRDomain(pQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(" IPv4 address (%s)\n"), (pIPv4Address->m_IPAddress.toString().c_str())); printedInfo = true; ); @@ -1971,49 +1937,49 @@ bool MDNSResponder::clsHost::_checkQueryCache(void) // Timed out! -> Delete DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Will remove IPv4 answer for "), _DH()); - _printRRDomain(pSQAnswer->m_ServiceDomain); + _printRRDomain(pQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(" IPv4 address\n")); printedInfo = true; ); - pSQAnswer->removeIPv4Address(pIPv4Address); - if (!pSQAnswer->m_pIPv4Addresses) // NO IPv4 address left -> remove content flag + if (1 == pQAnswer->m_IPv4Addresses.size()) { - pSQAnswer->m_QueryAnswerFlags &= ~static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address); + // NO IPv4 address left after this -> remove content flag + pQAnswer->m_QueryAnswerFlags &= ~static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address); } // Notify client - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address), false); + _executeQueryCallback(*pQuery, *pQAnswer, static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address), false); + expiredIPv4Addresses.push_back(pIPv4Address); } } // IPv4 flagged - - pIPv4Address = pNextIPv4Address; // Next - } // while + } // for + // Finally remove expired IPv4 addresses + for (clsQuery::clsAnswer::clsIPAddressWithTTL* pIPv4Address : expiredIPv4Addresses) + { + pQAnswer->removeIPv4Address(pIPv4Address); + } #endif #ifdef MDNS_IPV6_SUPPORT // IPv6Address (from AAAA) - stcQuery::stcAnswer::stcIPAddress* pIPv6Address = pSQAnswer->m_pIPv6Addresses; + clsQuery::clsAnswer::clsIPAddressWithTTL::list expiredIPv6Addresses; bool bAAAAUpdateQuerySent = false; - while ((pIPv6Address) && - (bResult)) + for (clsQuery::clsAnswer::clsIPAddressWithTTL::list::iterator itQAIPv6 = pQAnswer->m_IPv6Addresses.begin(); ((bResult) && (itQAIPv6 != pQAnswer->m_IPv6Addresses.end())); itQAIPv6++) { - - stcQuery::stcAnswer::stcIPAddress* pNextIPv6Address = pIPv6Address->m_pNext; // Get 'next' early, as 'current' may be deleted at the end... + clsQuery::clsAnswer::clsIPAddressWithTTL* pIPv6Address = *itQAIPv6; if (pIPv6Address->m_TTL.flagged()) { - - if (!pIPv6Address->m_TTL.finalTimeoutLevel()) // Needs update + if (!pIPv6Address->m_TTL.finalTimeoutLevel()) { - + // Needs update if ((bAAAAUpdateQuerySent) || - ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) + ((bResult = _sendQuery(pQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) { - pIPv6Address->m_TTL.restart(); bAAAAUpdateQuerySent = true; DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: IPv6 update scheduled for "), _DH()); - _printRRDomain(pSQAnswer->m_ServiceDomain); + _printRRDomain(pQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(" IPv6 address (%s)\n"), (pIPv6Address->m_IPAddress.toString().c_str())); printedInfo = true; ); @@ -2024,24 +1990,33 @@ bool MDNSResponder::clsHost::_checkQueryCache(void) // Timed out! -> Delete DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Will remove answer for "), _DH()); - _printRRDomain(pSQAnswer->m_ServiceDomain); + _printRRDomain(pQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(" IPv6 address\n")); printedInfo = true; ); - pSQAnswer->removeIPv6Address(pIPv6Address); - if (!pSQAnswer->m_pIPv6Addresses) // NO IPv6 address left -> remove content flag + if (1 == pQAnswer->m_IPv6Addresses.size()) { - pSQAnswer->m_QueryAnswerFlags &= ~static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address); + // NO IPv6 address left after this -> remove content flag + pQAnswer->m_QueryAnswerFlags &= ~static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address); } // Notify client - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address), false); + _executeQueryCallback(*pQuery, *pQAnswer, static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address), false); + expiredIPv6Addresses.push_back(pIPv6Address); } } // IPv6 flagged - - pIPv6Address = pNextIPv6Address; // Next + // Finally remove expired IPv6 addresses + for (clsQuery::clsAnswer::clsIPAddressWithTTL* pIPv6Address : expiredIPv6Addresses) + { + pQAnswer->removeIPv6Address(pIPv6Address); + } } // while #endif - pSQAnswer = pNextSQAnswer; + } + + // Finally remove expired answers + for (clsQuery::clsAnswer* pAnswer : expiredAnswers) + { + pQuery->removeAnswer(pAnswer); } } } @@ -2052,7 +2027,7 @@ bool MDNSResponder::clsHost::_checkQueryCache(void) /* - MDNSResponder::clsHost::_replyMaskForHost + clsLEAmDNS2_Host::_replyMaskForHost Determines the relavant host answers for the given question. - A question for the hostname (eg. esp8266.local) will result in an A/AAAA (eg. 192.168.2.129) reply. @@ -2060,8 +2035,8 @@ bool MDNSResponder::clsHost::_checkQueryCache(void) In addition, a full name match (question domain == host domain) is marked. */ -uint32_t MDNSResponder::clsHost::_replyMaskForHost(const MDNSResponder::clsHost::stcRRHeader& p_RRHeader, - bool* p_pbFullNameMatch /*= 0*/) const +uint32_t clsLEAMDNSHost::_replyMaskForHost(const clsLEAMDNSHost::clsRRHeader& p_RRHeader, + bool* p_pbFullNameMatch /*= 0*/) const { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _replyMaskForHost\n"));); @@ -2077,7 +2052,7 @@ uint32_t MDNSResponder::clsHost::_replyMaskForHost(const MDNSResponder::clsHost: { // PTR request #ifdef MDNS_IPV4_SUPPORT - stcRRDomain reverseIPv4Domain; + clsRRDomain reverseIPv4Domain; if ((_getResponderIPAddress(enuIPProtocolType::V4).isSet()) && (_buildDomainForReverseIPv4(_getResponderIPAddress(enuIPProtocolType::V4), reverseIPv4Domain)) && (p_RRHeader.m_Domain == reverseIPv4Domain)) @@ -2087,7 +2062,7 @@ uint32_t MDNSResponder::clsHost::_replyMaskForHost(const MDNSResponder::clsHost: } #endif #ifdef MDNS_IPV6_SUPPORT - stcRRDomain reverseIPv6Domain; + clsRRDomain reverseIPv6Domain; if ((_getResponderIPAddress(enuIPProtocolType::V6).isSet()) && (_buildDomainForReverseIPv6(_getResponderIPAddress(enuIPProtocolType::V6), reverseIPv6Domain)) && (p_RRHeader.m_Domain == reverseIPv6Domain)) @@ -2098,11 +2073,10 @@ uint32_t MDNSResponder::clsHost::_replyMaskForHost(const MDNSResponder::clsHost: #endif } // Address qeuest - stcRRDomain hostDomain; + clsRRDomain hostDomain; if ((_buildDomainForHost(m_pcHostName, hostDomain)) && (p_RRHeader.m_Domain == hostDomain)) // Host domain match { - (p_pbFullNameMatch ? (*p_pbFullNameMatch = true) : (0)); #ifdef MDNS_IPV4_SUPPORT @@ -2132,7 +2106,7 @@ uint32_t MDNSResponder::clsHost::_replyMaskForHost(const MDNSResponder::clsHost: } /* - MDNSResponder::clsHost::_replyMaskForService + clsLEAmDNS2_Host::_replyMaskForService Determines the relevant service answers for the given question - A PTR dns-sd service enum question (_services.dns-sd._udp.local) will result into an PTR_TYPE (eg. _http._tcp.local) answer @@ -2142,10 +2116,11 @@ uint32_t MDNSResponder::clsHost::_replyMaskForHost(const MDNSResponder::clsHost: - A TXT service name question (eg. MyESP._http._tcp.local) will result into an TXT (eg. c#=1) answer In addition, a full name match (question domain == service instance domain) is marked. + */ -uint32_t MDNSResponder::clsHost::_replyMaskForService(const MDNSResponder::clsHost::stcRRHeader& p_RRHeader, - const MDNSResponder::clsHost::stcService& p_Service, - bool* p_pbFullNameMatch /*= 0*/) const +uint32_t clsLEAMDNSHost::_replyMaskForService(const clsLEAMDNSHost::clsRRHeader& p_RRHeader, + clsLEAMDNSHost::clsService& p_rService, + bool* p_pbFullNameMatch /*= 0*/) { uint32_t u32ReplyMask = 0; (p_pbFullNameMatch ? *p_pbFullNameMatch = false : 0); @@ -2153,8 +2128,7 @@ uint32_t MDNSResponder::clsHost::_replyMaskForService(const MDNSResponder::clsHo if ((DNS_RRCLASS_IN == (p_RRHeader.m_Attributes.m_u16Class & (~0x8000))) || (DNS_RRCLASS_ANY == (p_RRHeader.m_Attributes.m_u16Class & (~0x8000)))) { - - stcRRDomain DNSSDDomain; + clsRRDomain DNSSDDomain; if ((_buildDomainForDNSSD(DNSSDDomain)) && // _services._dns-sd._udp.local (p_RRHeader.m_Domain == DNSSDDomain) && ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || @@ -2164,8 +2138,8 @@ uint32_t MDNSResponder::clsHost::_replyMaskForService(const MDNSResponder::clsHo u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::PTR_TYPE); } - stcRRDomain serviceDomain; - if ((_buildDomainForService(p_Service, false, serviceDomain)) && // eg. _http._tcp.local + clsRRDomain serviceDomain; + if ((_buildDomainForService(p_rService, false, serviceDomain)) && // eg. _http._tcp.local (p_RRHeader.m_Domain == serviceDomain) && ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type))) @@ -2174,10 +2148,9 @@ uint32_t MDNSResponder::clsHost::_replyMaskForService(const MDNSResponder::clsHo u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::PTR_NAME); } - if ((_buildDomainForService(p_Service, true, serviceDomain)) && // eg. MyESP._http._tcp.local + if ((_buildDomainForService(p_rService, true, serviceDomain)) && // eg. MyESP._http._tcp.local (p_RRHeader.m_Domain == serviceDomain)) { - (p_pbFullNameMatch ? (*p_pbFullNameMatch = true) : (0)); if ((DNS_RRTYPE_SRV == p_RRHeader.m_Attributes.m_u16Type) || @@ -2198,10 +2171,15 @@ uint32_t MDNSResponder::clsHost::_replyMaskForService(const MDNSResponder::clsHo { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _replyMaskForService: INVALID RR-class (0x%04X)!\n"), p_RRHeader.m_Attributes.m_u16Class);); } - DEBUG_EX_INFO(if (u32ReplyMask) DEBUG_OUTPUT.printf_P(PSTR("%s _replyMaskForService(%s.%s.%s): %s\n"), _DH(), p_Service.m_pcName, p_Service.m_pcServiceType, p_Service.m_pcProtocol, _replyFlags2String(u32ReplyMask));); + DEBUG_EX_INFO(if (u32ReplyMask) DEBUG_OUTPUT.printf_P(PSTR("%s _replyMaskForService(%s.%s.%s): %s\n"), _DH(), p_rService.m_pcInstanceName, p_rService.m_pcType, p_rService.m_pcProtocol, _replyFlags2String(u32ReplyMask));); return u32ReplyMask; } + } // namespace MDNSImplementation + } // namespace esp8266 + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Debug.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp old mode 100755 new mode 100644 similarity index 65% rename from libraries/ESP8266mDNS/src/LEAmDNS2_Host_Debug.cpp rename to libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp index 3f43a54089..434f61a0ea --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Debug.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp @@ -1,5 +1,5 @@ /* - LEAmDNS2_Host_Debug.h + LEAmDNS2Host_Debug.h License (MIT license): Permission is hereby granted, free of charge, to any person obtaining a copy @@ -22,88 +22,70 @@ */ -//#include <arch/cc.h> -//#include <sys/time.h> -//#include <HardwareSerial.h> -//#include <IPAddress.h> -//#include <lwip/ip_addr.h> -//#include <lwip/netif.h> -//#include <WString.h> -//#include <cstdint> - -/* - ESP8266mDNS Control.cpp -*/ - -extern "C" { - //#include "user_interface.h" -} - -#include "LEAmDNS2_lwIPdefs.h" -#include "LEAmDNS2_Priv.h" - -#ifdef MDNS_IPV4_SUPPORT -//#include <lwip/igmp.h> -#endif -#ifdef MDNS_IPV6_SUPPORT -//#include <lwip/mld6.h> -#endif +#include "LEAmDNS2Host.h" namespace esp8266 { -/* - LEAmDNS -*/ + namespace experimental { + #ifdef DEBUG_ESP_MDNS_RESPONDER /* - MDNSResponder::clsHost::_DH + clsLEAmDNS2_Host::_DH + */ -const char* MDNSResponder::clsHost::_DH(const MDNSResponder::clsHost::stcService* p_pMDNSService /*= 0*/) const +const char* clsLEAMDNSHost::_DH(const clsLEAMDNSHost::clsService* p_pService /*= 0*/) const { static char acBuffer[16 + 64]; *acBuffer = 0; - if (p_pMDNSService) + if (m_pNetIf) { - sprintf_P(acBuffer, PSTR("[MDNSResponder (%c%c%u)->%s]"), m_rNetIf.name[0], m_rNetIf.name[1], m_rNetIf.num, _service2String(p_pMDNSService)); + sprintf_P(acBuffer, PSTR("[mDNS %c%c%u]"), m_pNetIf->name[0], m_pNetIf->name[1], m_pNetIf->num); + if (p_pService) + { + strcat_P(acBuffer, PSTR(">")); + strcat(acBuffer, _service2String(p_pService)); + } } else { - sprintf_P(acBuffer, PSTR("[MDNSResponder (%c%c%u)]"), m_rNetIf.name[0], m_rNetIf.name[1], m_rNetIf.num); + strcpy_P(acBuffer, PSTR("[mDNS]")); } return acBuffer; } /* - MDNSResponder::clsHost::_service2String + clsLEAmDNS2_Host::_service2String + */ -const char* MDNSResponder::clsHost::_service2String(const MDNSResponder::clsHost::stcService* p_pMDNSService) const +const char* clsLEAMDNSHost::_service2String(const clsLEAMDNSHost::clsService* p_pService) const { static char acBuffer[64]; *acBuffer = 0; - if (p_pMDNSService) + if (p_pService) { sprintf_P(acBuffer, PSTR("%s.%s%s.%s%s.local"), - (p_pMDNSService->m_pcName ? : "-"), - (p_pMDNSService->m_pcServiceType ? ('_' == *(p_pMDNSService->m_pcServiceType) ? "" : "_") : "-"), - (p_pMDNSService->m_pcServiceType ? : "-"), - (p_pMDNSService->m_pcProtocol ? ('_' == *(p_pMDNSService->m_pcProtocol) ? "" : "_") : "-"), - (p_pMDNSService->m_pcProtocol ? : "-")); + (p_pService->m_pcInstanceName ? : "-"), + (p_pService->m_pcType ? ('_' == *(p_pService->m_pcType) ? "" : "_") : "-"), + (p_pService->m_pcType ? : "-"), + (p_pService->m_pcProtocol ? ('_' == *(p_pService->m_pcProtocol) ? "" : "_") : "-"), + (p_pService->m_pcProtocol ? : "-")); } return acBuffer; } /* - MDNSResponder::clsHost::_printRRDomain + clsLEAmDNS2_Host::_printRRDomain + */ -bool MDNSResponder::clsHost::_printRRDomain(const MDNSResponder::clsHost::stcRRDomain& p_RRDomain) const +bool clsLEAMDNSHost::_printRRDomain(const clsLEAMDNSHost::clsRRDomain& p_RRDomain) const { //DEBUG_OUTPUT.printf_P(PSTR("Domain: ")); @@ -134,9 +116,10 @@ bool MDNSResponder::clsHost::_printRRDomain(const MDNSResponder::clsHost::stcRRD } /* - MDNSResponder::clsHost::_printRRAnswer + clsLEAmDNS2_Host::_printRRAnswer + */ -bool MDNSResponder::clsHost::_printRRAnswer(const MDNSResponder::clsHost::stcRRAnswer& p_RRAnswer) const +bool clsLEAMDNSHost::_printRRAnswer(const clsLEAMDNSHost::clsRRAnswer& p_RRAnswer) const { DEBUG_OUTPUT.printf_P(PSTR("%s RRAnswer: "), _DH()); _printRRDomain(p_RRAnswer.m_Header.m_Domain); @@ -145,20 +128,20 @@ bool MDNSResponder::clsHost::_printRRAnswer(const MDNSResponder::clsHost::stcRRA { #ifdef MDNS_IPV4_SUPPORT case DNS_RRTYPE_A: - DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((const stcRRAnswerA*)&p_RRAnswer)->m_IPAddress.toString().c_str()); + DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((const clsRRAnswerA*)&p_RRAnswer)->m_IPAddress.toString().c_str()); break; #endif case DNS_RRTYPE_PTR: DEBUG_OUTPUT.printf_P(PSTR("PTR ")); - _printRRDomain(((const stcRRAnswerPTR*)&p_RRAnswer)->m_PTRDomain); + _printRRDomain(((const clsRRAnswerPTR*)&p_RRAnswer)->m_PTRDomain); break; case DNS_RRTYPE_TXT: { - size_t stTxtLength = ((const stcRRAnswerTXT*)&p_RRAnswer)->m_Txts.c_strLength(); + size_t stTxtLength = ((const clsRRAnswerTXT*)&p_RRAnswer)->m_Txts.c_strLength(); char* pTxts = new char[stTxtLength]; if (pTxts) { - ((/*const c_str()!!*/stcRRAnswerTXT*)&p_RRAnswer)->m_Txts.c_str(pTxts); + ((/*const c_str()!!*/clsRRAnswerTXT*)&p_RRAnswer)->m_Txts.c_str(pTxts); DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts); delete[] pTxts; } @@ -166,12 +149,12 @@ bool MDNSResponder::clsHost::_printRRAnswer(const MDNSResponder::clsHost::stcRRA } #ifdef MDNS_IPV6_SUPPORT case DNS_RRTYPE_AAAA: - DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((stcRRAnswerAAAA*&)p_RRAnswer)->m_IPAddress.toString().c_str()); + DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((clsRRAnswerAAAA*&)p_RRAnswer)->m_IPAddress.toString().c_str()); break; #endif case DNS_RRTYPE_SRV: - DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((const stcRRAnswerSRV*)&p_RRAnswer)->m_u16Port); - _printRRDomain(((const stcRRAnswerSRV*)&p_RRAnswer)->m_SRVDomain); + DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((const clsRRAnswerSRV*)&p_RRAnswer)->m_u16Port); + _printRRDomain(((const clsRRAnswerSRV*)&p_RRAnswer)->m_SRVDomain); break; default: DEBUG_OUTPUT.printf_P(PSTR("generic ")); @@ -183,33 +166,38 @@ bool MDNSResponder::clsHost::_printRRAnswer(const MDNSResponder::clsHost::stcRRA } /* - MDNSResponder::clsHost::_RRType2Name + clsLEAmDNS2_Host::_RRType2Name + */ -const char* MDNSResponder::clsHost::_RRType2Name(uint16_t p_u16RRType) const +const char* clsLEAMDNSHost::_RRType2Name(uint16_t p_u16RRType) const { static char acRRName[16]; *acRRName = 0; switch (p_u16RRType & (~0x8000)) // Topmost bit might carry 'cache flush' flag { - case DNS_RRTYPE_A: strcpy(acRRName, "A"); break; - case DNS_RRTYPE_PTR: strcpy(acRRName, "PTR"); break; - case DNS_RRTYPE_TXT: strcpy(acRRName, "TXT"); break; - case DNS_RRTYPE_AAAA: strcpy(acRRName, "AAAA"); break; - case DNS_RRTYPE_SRV: strcpy(acRRName, "SRV"); break; - case DNS_RRTYPE_NSEC: strcpy(acRRName, "NSEC"); break; - case DNS_RRTYPE_ANY: strcpy(acRRName, "ANY"); break; - default: - sprintf(acRRName, "Unknown(0x%04X)", p_u16RRType); // MAX 15! +#ifdef MDNS_IPV4_SUPPORT + case DNS_RRTYPE_A: strcpy(acRRName, "A"); break; +#endif + case DNS_RRTYPE_PTR: strcpy(acRRName, "PTR"); break; + case DNS_RRTYPE_TXT: strcpy(acRRName, "TXT"); break; +#ifdef MDNS_IPV6_SUPPORT + case DNS_RRTYPE_AAAA: strcpy(acRRName, "AAAA"); break; +#endif + case DNS_RRTYPE_SRV: strcpy(acRRName, "SRV"); break; + case clsConsts::u8DNS_RRTYPE_NSEC: strcpy(acRRName, "NSEC"); break; + case DNS_RRTYPE_ANY: strcpy(acRRName, "ANY"); break; + default: sprintf(acRRName, "Unknown(0x%04X)", p_u16RRType); // MAX 15! } return acRRName; } /* - MDNSResponder::clsHost::_RRClass2String + clsLEAmDNS2_Host::_RRClass2String + */ -const char* MDNSResponder::clsHost::_RRClass2String(uint16_t p_u16RRClass, - bool p_bIsQuery) const +const char* clsLEAMDNSHost::_RRClass2String(uint16_t p_u16RRClass, + bool p_bIsQuery) const { static char acClassString[16]; *acClassString = 0; @@ -227,9 +215,10 @@ const char* MDNSResponder::clsHost::_RRClass2String(uint16_t p_u16RRClass, } /* - MDNSResponder::clsHost::_replyFlags2String + clsLEAmDNS2_Host::_replyFlags2String + */ -const char* MDNSResponder::clsHost::_replyFlags2String(uint32_t p_u32ReplyFlags) const +const char* clsLEAMDNSHost::_replyFlags2String(uint32_t p_u32ReplyFlags) const { static char acFlagsString[64]; @@ -276,29 +265,41 @@ const char* MDNSResponder::clsHost::_replyFlags2String(uint32_t p_u32ReplyFlags) strcpy(acFlagsString, "none"); } + // Remove trailing spaces + while ((*acFlagsString) && + (' ' == acFlagsString[strlen(acFlagsString) - 1])) + { + acFlagsString[strlen(acFlagsString) - 1] = 0; + } + return acFlagsString; // 63 } /* - MDNSResponder::clsHost::_NSECBitmap2String + clsLEAmDNS2_Host::_NSECBitmap2String + */ -const char* MDNSResponder::clsHost::_NSECBitmap2String(const stcNSECBitmap* p_pNSECBitmap) const +const char* clsLEAMDNSHost::_NSECBitmap2String(const clsNSECBitmap* p_pNSECBitmap) const { static char acFlagsString[32]; *acFlagsString = 0; +#ifdef MDNS_IPV4_SUPPORT if (p_pNSECBitmap->getBit(DNS_RRTYPE_A)) { strcat(acFlagsString, "A "); // 2 } +#endif if (p_pNSECBitmap->getBit(DNS_RRTYPE_PTR)) { strcat(acFlagsString, "PTR "); // 4 } +#ifdef MDNS_IPV6_SUPPORT if (p_pNSECBitmap->getBit(DNS_RRTYPE_AAAA)) { strcat(acFlagsString, "AAAA "); // 5 } +#endif if (p_pNSECBitmap->getBit(DNS_RRTYPE_TXT)) { strcat(acFlagsString, "TXT "); // 4 @@ -307,7 +308,7 @@ const char* MDNSResponder::clsHost::_NSECBitmap2String(const stcNSECBitmap* p_pN { strcat(acFlagsString, "SRV "); // 4 } - if (p_pNSECBitmap->getBit(DNS_RRTYPE_NSEC)) + if (p_pNSECBitmap->getBit(clsConsts::u8DNS_RRTYPE_NSEC)) { strcat(acFlagsString, "NSEC "); // 5 } @@ -322,6 +323,12 @@ const char* MDNSResponder::clsHost::_NSECBitmap2String(const stcNSECBitmap* p_pN #endif // DEBUG_ESP_MDNS_RESPONDER + } // namespace MDNSImplementation + } // namespace esp8266 + + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp new file mode 100644 index 0000000000..b4db3c0531 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -0,0 +1,3253 @@ +/* + LEAmDNS2Host_Structs.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#include "LEAmDNS2Host.h" + + +namespace esp8266 +{ + + +namespace experimental +{ + + +/** + Internal CLASSES & STRUCTS +*/ + +/** + clsLEAMDNSHost::clsServiceTxt + + One MDNS TXT item. + m_pcValue may be '\0'. + Objects can be chained together (list). + A 'm_bTemp' flag differentiates between static and dynamic items. + Output as byte array 'c#=1' is supported. +*/ + +/* + clsLEAMDNSHost::clsServiceTxt::clsServiceTxt constructor + +*/ +clsLEAMDNSHost::clsServiceTxt::clsServiceTxt(const char* p_pcKey /*= 0*/, + const char* p_pcValue /*= 0*/, + bool p_bTemp /*= false*/) + : m_pcKey(0), + m_pcValue(0), + m_bTemp(p_bTemp) +{ + setKey(p_pcKey); + setValue(p_pcValue); +} + +/* + clsLEAMDNSHost::clsServiceTxt::clsServiceTxt copy-constructor + +*/ +clsLEAMDNSHost::clsServiceTxt::clsServiceTxt(const clsLEAMDNSHost::clsServiceTxt& p_Other) + : m_pcKey(0), + m_pcValue(0), + m_bTemp(false) +{ + operator=(p_Other); +} + +/* + clsLEAMDNSHost::clsServiceTxt::~stcServiceTxt destructor + +*/ +clsLEAMDNSHost::clsServiceTxt::~clsServiceTxt(void) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsServiceTxt::operator= + +*/ +clsLEAMDNSHost::clsServiceTxt& clsLEAMDNSHost::clsServiceTxt::operator=(const clsLEAMDNSHost::clsServiceTxt& p_Other) +{ + if (&p_Other != this) + { + clear(); + set(p_Other.m_pcKey, p_Other.m_pcValue, p_Other.m_bTemp); + } + return *this; +} + +/* + clsLEAMDNSHost::clsServiceTxt::clear + +*/ +bool clsLEAMDNSHost::clsServiceTxt::clear(void) +{ + releaseKey(); + releaseValue(); + return true; +} + +/* + clsLEAMDNSHost::clsServiceTxt::allocKey + +*/ +char* clsLEAMDNSHost::clsServiceTxt::allocKey(size_t p_stLength) +{ + releaseKey(); + if (p_stLength) + { + m_pcKey = new char[p_stLength + 1]; + } + return m_pcKey; +} + +/* + clsLEAMDNSHost::clsServiceTxt::setKey + +*/ +bool clsLEAMDNSHost::clsServiceTxt::setKey(const char* p_pcKey, + size_t p_stLength) +{ + bool bResult = false; + + releaseKey(); + if (p_stLength) + { + if (allocKey(p_stLength)) + { + strncpy(m_pcKey, p_pcKey, p_stLength); + m_pcKey[p_stLength] = 0; + bResult = true; + } + } + return bResult; +} + +/* + clsLEAMDNSHost::clsServiceTxt::setKey + +*/ +bool clsLEAMDNSHost::clsServiceTxt::setKey(const char* p_pcKey) +{ + return setKey(p_pcKey, (p_pcKey ? strlen(p_pcKey) : 0)); +} + +/* + clsLEAMDNSHost::clsServiceTxt::releaseKey + +*/ +bool clsLEAMDNSHost::clsServiceTxt::releaseKey(void) +{ + if (m_pcKey) + { + delete[] m_pcKey; + m_pcKey = 0; + } + return true; +} + +/* + clsLEAMDNSHost::clsServiceTxt::allocValue + +*/ +char* clsLEAMDNSHost::clsServiceTxt::allocValue(size_t p_stLength) +{ + releaseValue(); + if (p_stLength) + { + m_pcValue = new char[p_stLength + 1]; + } + return m_pcValue; +} + +/* + clsLEAMDNSHost::clsServiceTxt::setValue + +*/ +bool clsLEAMDNSHost::clsServiceTxt::setValue(const char* p_pcValue, + size_t p_stLength) +{ + bool bResult = false; + + releaseValue(); + if (p_stLength) + { + if (allocValue(p_stLength)) + { + strncpy(m_pcValue, p_pcValue, p_stLength); + m_pcValue[p_stLength] = 0; + bResult = true; + } + } + else + { + // No value -> also OK + bResult = true; + } + return bResult; +} + +/* + clsLEAMDNSHost::clsServiceTxt::setValue + +*/ +bool clsLEAMDNSHost::clsServiceTxt::setValue(const char* p_pcValue) +{ + return setValue(p_pcValue, (p_pcValue ? strlen(p_pcValue) : 0)); +} + +/* + clsLEAMDNSHost::clsServiceTxt::releaseValue + +*/ +bool clsLEAMDNSHost::clsServiceTxt::releaseValue(void) +{ + if (m_pcValue) + { + delete[] m_pcValue; + m_pcValue = 0; + } + return true; +} + +/* + clsLEAMDNSHost::clsServiceTxt::set + +*/ +bool clsLEAMDNSHost::clsServiceTxt::set(const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp /*= false*/) +{ + m_bTemp = p_bTemp; + return ((setKey(p_pcKey)) && + (setValue(p_pcValue))); +} + +/* + clsLEAMDNSHost::clsServiceTxt::update + +*/ +bool clsLEAMDNSHost::clsServiceTxt::update(const char* p_pcValue) +{ + return setValue(p_pcValue); +} + +/* + clsLEAMDNSHost::clsServiceTxt::length + + length of eg. 'c#=1' without any closing '\0' + +*/ +size_t clsLEAMDNSHost::clsServiceTxt::length(void) const +{ + size_t stLength = 0; + if (m_pcKey) + { + stLength += strlen(m_pcKey); // Key + stLength += 1; // '=' + stLength += (m_pcValue ? strlen(m_pcValue) : 0); // Value + } + return stLength; +} + + +/** + clsLEAMDNSHost::clsServiceTxts + + A list of zero or more MDNS TXT (stcServiceTxt) items. + Dynamic TXT items can be removed by 'removeTempTxts'. + A TXT item can be looked up by its 'key' member. + Export as ';'-separated byte array is supported. + Export as 'length byte coded' byte array is supported. + Comparison ((all A TXT items in B and equal) AND (all B TXT items in A and equal)) is supported. + +*/ + +/* + clsLEAMDNSHost::clsServiceTxts::clsServiceTxts contructor + +*/ +clsLEAMDNSHost::clsServiceTxts::clsServiceTxts(void) + : m_pcCache(0) +{ +} + +/* + clsLEAMDNSHost::clsServiceTxts::clsServiceTxts copy-constructor + +*/ +clsLEAMDNSHost::clsServiceTxts::clsServiceTxts(const clsServiceTxts& p_Other) + : m_pcCache(0) +{ + operator=(p_Other); +} + +/* + clsLEAMDNSHost::clsServiceTxts::~stcServiceTxts destructor + +*/ +clsLEAMDNSHost::clsServiceTxts::~clsServiceTxts(void) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsServiceTxts::operator= + +*/ +clsLEAMDNSHost::clsServiceTxts& clsLEAMDNSHost::clsServiceTxts::operator=(const clsServiceTxts& p_Other) +{ + if (this != &p_Other) + { + clear(); + + for (const clsServiceTxt* pOtherTxt : p_Other.m_Txts) + { + add(new clsServiceTxt(*pOtherTxt)); + } + } + return *this; +} + +/* + clsLEAMDNSHost::clsServiceTxts::clear + +*/ +bool clsLEAMDNSHost::clsServiceTxts::clear(void) +{ + for (clsServiceTxt* pTxt : m_Txts) + { + delete pTxt; + } + m_Txts.clear(); + + return clearCache(); +} + +/* + clsLEAMDNSHost::clsServiceTxts::clearCache + +*/ +bool clsLEAMDNSHost::clsServiceTxts::clearCache(void) +{ + if (m_pcCache) + { + delete[] m_pcCache; + m_pcCache = 0; + } + return true; +} + +/* + clsLEAMDNSHost::clsServiceTxts::add + +*/ +bool clsLEAMDNSHost::clsServiceTxts::add(clsLEAMDNSHost::clsServiceTxt* p_pTxt) +{ + bool bResult = false; + + if (p_pTxt) + { + m_Txts.push_back(p_pTxt); + bResult = true; + } + return ((clearCache()) && + (bResult)); +} + +/* + clsLEAMDNSHost::clsServiceTxts::remove + +*/ +bool clsLEAMDNSHost::clsServiceTxts::remove(clsServiceTxt* p_pTxt) +{ + bool bResult = false; + + clsServiceTxt::list::iterator it(p_pTxt + ? std::find(m_Txts.begin(), m_Txts.end(), p_pTxt) + : m_Txts.end()); + if (m_Txts.end() != it) + { + m_Txts.erase(it); + delete p_pTxt; + + bResult = true; + } + return ((clearCache()) && + (bResult)); +} + +/* + clsLEAMDNSHost::clsServiceTxts::count + +*/ +size_t clsLEAMDNSHost::clsServiceTxts::count(void) const +{ + size_t stResult = m_Txts.size(); + return stResult; +} + +/* + clsLEAMDNSHost::clsServiceTxts::removeTempTxts + +*/ +bool clsLEAMDNSHost::clsServiceTxts::removeTempTxts(void) +{ + bool bResult = true; + + // Delete content + clsServiceTxt::list tempTxts; + for (clsServiceTxt* pTxt : m_Txts) + { + if (pTxt->m_bTemp) + { + tempTxts.push_back(pTxt); + delete pTxt; + } + } + // Remove objects from list + for (clsServiceTxt* pTempTxt : tempTxts) + { + m_Txts.remove(pTempTxt); + } + return ((clearCache()) && + (bResult)); +} + +/* + clsLEAMDNSHost::clsServiceTxts::find + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsServiceTxts::find(const char* p_pcKey) +{ + clsServiceTxt* pResult = 0; + + for (clsServiceTxt* pTxt : m_Txts) + { + if ((p_pcKey) && + (0 == strcmp(pTxt->m_pcKey, p_pcKey))) + { + pResult = pTxt; + break; + } + } + return pResult; +} + +/* + clsLEAMDNSHost::clsServiceTxts::find (const) + +*/ +const clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsServiceTxts::find(const char* p_pcKey) const +{ + const clsServiceTxt* pResult = 0; + + for (const clsServiceTxt* pTxt : m_Txts) + { + if ((p_pcKey) && + (0 == strcmp(pTxt->m_pcKey, p_pcKey))) + { + pResult = pTxt; + break; + } + } + return pResult; +} + +/* + clsLEAMDNSHost::clsServiceTxts::find + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsServiceTxts::find(const clsServiceTxt* p_pTxt) +{ + clsServiceTxt* pResult = 0; + + for (clsServiceTxt* pTxt : m_Txts) + { + if (p_pTxt == pTxt) + { + pResult = pTxt; + break; + } + } + return pResult; +} + +/* + clsLEAMDNSHost::clsServiceTxts::length + +*/ +size_t clsLEAMDNSHost::clsServiceTxts::length(void) const +{ + size_t szLength = 0; + + for (clsServiceTxt* pTxt : m_Txts) + { + szLength += 1; // Length byte + szLength += pTxt->length(); // Text + } + return szLength; +} + +/* + clsLEAMDNSHost::clsServiceTxts::c_strLength + + (incl. closing '\0'). Length bytes place is used for delimiting ';' and closing '\0' + +*/ +size_t clsLEAMDNSHost::clsServiceTxts::c_strLength(void) const +{ + return length(); +} + +/* + clsLEAMDNSHost::clsServiceTxts::c_str + +*/ +bool clsLEAMDNSHost::clsServiceTxts::c_str(char* p_pcBuffer) +{ + bool bResult = false; + + if (p_pcBuffer) + { + bResult = true; + + char* pcCursor = p_pcBuffer; + *pcCursor = 0; + for (const clsServiceTxt* pTxt : m_Txts) + { + size_t stLength; + if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) + { + if (pcCursor != p_pcBuffer) + { + *pcCursor++ = ';'; + } + strncpy(pcCursor, pTxt->m_pcKey, stLength); pcCursor[stLength] = 0; + pcCursor += stLength; + *pcCursor++ = '='; + if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) + { + strncpy(pcCursor, pTxt->m_pcValue, stLength); pcCursor[stLength] = 0; + pcCursor += stLength; + } + } + else + { + break; + } + } + *pcCursor++ = 0; + } + return bResult; +} + +/* + clsLEAMDNSHost::clsServiceTxts::c_str + +*/ +const char* clsLEAMDNSHost::clsServiceTxts::c_str(void) const +{ + + if ((!m_pcCache) && + (m_Txts.size()) && + ((((clsServiceTxts*)this)->m_pcCache = new char[c_strLength()]))) // TRANSPARENT caching + { + ((clsServiceTxts*)this)->c_str(m_pcCache); + } + return m_pcCache; +} + +/* + clsLEAMDNSHost::clsServiceTxts::bufferLength + + (incl. closing '\0'). + +*/ +size_t clsLEAMDNSHost::clsServiceTxts::bufferLength(void) const +{ + return (length() + 1); +} + +/* + clsLEAMDNSHost::clsServiceTxts::toBuffer + +*/ +bool clsLEAMDNSHost::clsServiceTxts::buffer(char* p_pcBuffer) +{ + bool bResult = false; + + if (p_pcBuffer) + { + bResult = true; + + *p_pcBuffer = 0; + for (const clsServiceTxt* pTxt : m_Txts) + { + *(unsigned char*)p_pcBuffer++ = pTxt->length(); + size_t stLength; + if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) + { + memcpy(p_pcBuffer, pTxt->m_pcKey, stLength); + p_pcBuffer += stLength; + *p_pcBuffer++ = '='; + if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) + { + memcpy(p_pcBuffer, pTxt->m_pcValue, stLength); + p_pcBuffer += stLength; + } + } + else + { + break; + } + } + *p_pcBuffer++ = 0; + } + return bResult; +} + +/* + clsLEAMDNSHost::clsServiceTxts::compare + +*/ +bool clsLEAMDNSHost::clsServiceTxts::compare(const clsLEAMDNSHost::clsServiceTxts& p_Other) const +{ + bool bResult = false; + + if ((bResult = (length() == p_Other.length()))) + { + // Compare A->B + for (const clsServiceTxt* pTxt : m_Txts) + { + const clsServiceTxt* pOtherTxt = p_Other.find(pTxt->m_pcKey); + if (!((bResult = ((pOtherTxt) && + (pTxt->m_pcValue) && + (pOtherTxt->m_pcValue) && + (strlen(pTxt->m_pcValue) == strlen(pOtherTxt->m_pcValue)) && + (0 == strcmp(pTxt->m_pcValue, pOtherTxt->m_pcValue)))))) + { + break; + } + } + // Compare B->A + for (const clsServiceTxt* pOtherTxt : p_Other.m_Txts) + { + const clsServiceTxt* pTxt = find(pOtherTxt->m_pcKey); + if (!((bResult = ((pTxt) && + (pOtherTxt->m_pcValue) && + (pTxt->m_pcValue) && + (strlen(pOtherTxt->m_pcValue) == strlen(pTxt->m_pcValue)) && + (0 == strcmp(pOtherTxt->m_pcValue, pTxt->m_pcValue)))))) + { + break; + } + } + } + return bResult; +} + +/* + clsLEAMDNSHost::clsServiceTxts::operator== + +*/ +bool clsLEAMDNSHost::clsServiceTxts::operator==(const clsServiceTxts& p_Other) const +{ + return compare(p_Other); +} + +/* + clsLEAMDNSHost::clsServiceTxts::operator!= + +*/ +bool clsLEAMDNSHost::clsServiceTxts::operator!=(const clsServiceTxts& p_Other) const +{ + return !compare(p_Other); +} + + +/** + clsLEAMDNSHost::clsProbeInformation_Base + + Probing status information for a host or service domain + +*/ + +/* + clsLEAMDNSHost::clsProbeInformation_Base::clsProbeInformation_Base constructor +*/ +clsLEAMDNSHost::clsProbeInformation_Base::clsProbeInformation_Base(void) + : m_ProbingStatus(enuProbingStatus::WaitingForData), + m_u8SentCount(0), + m_Timeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()), + m_bConflict(false), + m_bTiebreakNeeded(false) +{ +} + +/* + clsLEAMDNSHost::clsProbeInformation_Base::clear +*/ +bool clsLEAMDNSHost::clsProbeInformation_Base::clear(void) +{ + m_ProbingStatus = enuProbingStatus::WaitingForData; + m_u8SentCount = 0; + m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + m_bConflict = false; + m_bTiebreakNeeded = false; + + return true; +} + + +/** + clsLEAMDNSHost::clsProbeInformation_Host + + Probing status information for a host or service domain + +*/ + +/* + clsLEAMDNSHost::clsProbeInformation::clsProbeInformation constructor +*/ +clsLEAMDNSHost::clsProbeInformation::clsProbeInformation(void) + : m_fnProbeResultCallback(0) +{ +} + +/* + clsLEAMDNSHost::clsProbeInformation::clear +*/ +bool clsLEAMDNSHost::clsProbeInformation::clear(bool p_bClearUserdata /*= false*/) +{ + if (p_bClearUserdata) + { + m_fnProbeResultCallback = 0; + } + return clsProbeInformation_Base::clear(); +} + + +/** + clsLEAMDNSHost::clsService::clsProbeInformation + + Probing status information for a host or service domain + +*/ + +/* + clsLEAMDNSHost::clsService::clsProbeInformation::clsProbeInformation constructor +*/ +clsLEAMDNSHost::clsService::clsProbeInformation::clsProbeInformation(void) + : m_fnProbeResultCallback(0) +{ +} + +/* + clsLEAMDNSHost::clsService::clsProbeInformation::clear +*/ +bool clsLEAMDNSHost::clsService::clsProbeInformation::clear(bool p_bClearUserdata /*= false*/) +{ + if (p_bClearUserdata) + { + m_fnProbeResultCallback = 0; + } + return clsProbeInformation_Base::clear(); +} + + +/** + clsLEAMDNSHost::clsService + + A MDNS service object (to be announced by the MDNS responder) + The service instance may be '\0'; in this case the hostname is used + and the flag m_bAutoName is set. If the hostname changes, all 'auto- + named' services are renamed also. + m_u8Replymask is used while preparing a response to a MDNS query. It is + resetted in '_sendMDNSMessage' afterwards. +*/ + +/* + clsLEAMDNSHost::clsService::clsService constructor + +*/ +clsLEAMDNSHost::clsService::clsService(void) + : m_pcInstanceName(0), + m_bAutoName(false), + m_pcType(0), + m_pcProtocol(0), + m_u16Port(0), + m_u32ReplyMask(0), + m_fnTxtCallback(0) +{ +} + +/* + clsLEAMDNSHost::clsService::~clsService destructor + +*/ +clsLEAMDNSHost::clsService::~clsService(void) +{ + _releaseInstanceName(); + _releaseType(); + _releaseProtocol(); +} + +/* + clsLEAMDNSHost::clsService::setInstanceName + +*/ +bool clsLEAMDNSHost::clsService::setInstanceName(const char* p_pcInstanceName) +{ + bool bResult = false; + + _releaseInstanceName(); + size_t stLength = (p_pcInstanceName ? strlen(p_pcInstanceName) : 0); + if ((stLength) && + (stLength <= clsConsts::stDomainLabelMaxLength)) + { + if ((bResult = (0 != (m_pcInstanceName = new char[stLength + 1])))) + { + strncpy(m_pcInstanceName, p_pcInstanceName, stLength); + m_pcInstanceName[stLength] = 0; + + _resetProbeStatus(); + } + } + return bResult; +} + +/* + clsLEAMDNSHost::clsService::indexInstanceName + +*/ +bool clsLEAMDNSHost::clsService::indexInstanceName(void) +{ + bool bResult = false; + + if ((bResult = setInstanceName(clsLEAMDNSHost::indexDomainName(m_pcInstanceName, "#", 0)))) + { + _resetProbeStatus(); + } + return bResult; +} + +/* + clsLEAMDNSHost::clsService::instanceName + +*/ +const char* clsLEAMDNSHost::clsService::instanceName(void) const +{ + return m_pcInstanceName; +} + +/* + clsLEAMDNSHost::clsService::_releaseInstanceName + +*/ +bool clsLEAMDNSHost::clsService::_releaseInstanceName(void) +{ + if (m_pcInstanceName) + { + delete[] m_pcInstanceName; + m_pcInstanceName = 0; + } + return true; +} + +/* + clsLEAMDNSHost::clsService::setType + +*/ +bool clsLEAMDNSHost::clsService::setType(const char* p_pcType) +{ + bool bResult = false; + + _releaseType(); + size_t stLength = (p_pcType ? strlen(p_pcType) : 0); + if ((stLength) && + (stLength <= clsConsts::stServiceTypeMaxLength)) + { + if ((bResult = (0 != (m_pcType = new char[stLength + 1])))) + { + strncpy(m_pcType, p_pcType, stLength); + m_pcType[stLength] = 0; + + _resetProbeStatus(); + } + } + return bResult; +} + +/* + clsLEAMDNSHost::clsService::type + +*/ +const char* clsLEAMDNSHost::clsService::type(void) const +{ + return m_pcType; +} + +/* + clsLEAMDNSHost::clsService::_releaseType + +*/ +bool clsLEAMDNSHost::clsService::_releaseType(void) +{ + if (m_pcType) + { + delete[] m_pcType; + m_pcType = 0; + } + return true; +} + +/* + clsLEAMDNSHost::clsService::setProtocol + +*/ +bool clsLEAMDNSHost::clsService::setProtocol(const char* p_pcProtocol) +{ + bool bResult = false; + + _releaseProtocol(); + size_t stLength = (p_pcProtocol ? strlen(p_pcProtocol) : 0); + if ((stLength) && + (stLength <= clsConsts::stServiceProtocolMaxLength)) + { + if ((bResult = (0 != (m_pcProtocol = new char[stLength + 1])))) + { + strncpy(m_pcProtocol, p_pcProtocol, stLength); + m_pcProtocol[stLength] = 0; + + _resetProbeStatus(); + } + } + return bResult; +} + +/* + clsLEAMDNSHost::clsService::protocol + +*/ +const char* clsLEAMDNSHost::clsService::protocol(void) const +{ + return m_pcProtocol; +} + +/* + clsLEAMDNSHost::clsService::_releaseProtocol + +*/ +bool clsLEAMDNSHost::clsService::_releaseProtocol(void) +{ + if (m_pcProtocol) + { + delete[] m_pcProtocol; + m_pcProtocol = 0; + } + return true; +} + +/* + clsLEAMDNSHost::clsService::setPort + +*/ +bool clsLEAMDNSHost::clsService::setPort(uint16_t p_u16Port) +{ + bool bResult = false; + + if ((bResult = (0 != p_u16Port))) + { + m_u16Port = p_u16Port; + + _resetProbeStatus(); + } + return bResult; +} + +/* + clsLEAMDNSHost::clsService::port + +*/ +uint16_t clsLEAMDNSHost::clsService::port(void) const +{ + return m_u16Port; +} + +/* + clsLEAMDNSHost::clsService::setProbeResultCallback + +*/ +bool clsLEAMDNSHost::clsService::setProbeResultCallback(fnProbeResultCallback p_fnProbeResultCallback) +{ + m_ProbeInformation.m_fnProbeResultCallback = p_fnProbeResultCallback; + return true; +} + +/* + clsLEAMDNSHost::clsService::probeStatus + +*/ +bool clsLEAMDNSHost::clsService::probeStatus(void) const +{ + return (clsProbeInformation_Base::enuProbingStatus::DoneFinally == m_ProbeInformation.m_ProbingStatus); +} + +/* + clsLEAMDNSHost::clsService::_resetProbeStatus + +*/ +void clsLEAMDNSHost::clsService::_resetProbeStatus(void) +{ + m_ProbeInformation.clear(false); + m_ProbeInformation.m_ProbingStatus = clsProbeInformation_Base::enuProbingStatus::ReadyToStart; +} + +/* + clsLEAMDNSHost::clsService::addServiceTxt (const char*) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, + const char* p_pcValue) +{ + return _addServiceTxt(p_pcKey, p_pcValue, false); +} + +/* + clsLEAMDNSHost::clsService::addServiceTxt (uint32_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, + uint32_t p_u32Value) +{ + return _addServiceTxt(p_pcKey, p_u32Value, false); +} + +/* + clsLEAMDNSHost::clsService::addServiceTxt (uint16_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, + uint16_t p_u16Value) +{ + return _addServiceTxt(p_pcKey, p_u16Value, false); +} + +/* + clsLEAMDNSHost::clsService::addServiceTxt (uint8_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, + uint8_t p_u8Value) +{ + return _addServiceTxt(p_pcKey, p_u8Value, false); +} + +/* + clsLEAMDNSHost::clsService::addServiceTxt (int32_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, + int32_t p_i32Value) +{ + return _addServiceTxt(p_pcKey, p_i32Value, false); +} + +/* + clsLEAMDNSHost::clsService::addServiceTxt (int16_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, + int16_t p_i16Value) +{ + return _addServiceTxt(p_pcKey, p_i16Value, false); +} + +/* + clsLEAMDNSHost::clsService::addServiceTxt (int8_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, + int8_t p_i8Value) +{ + return _addServiceTxt(p_pcKey, p_i8Value, false); +} + +/* + clsLEAMDNSHost::clsService::addDynamicServiceTxt (const char*) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, + const char* p_pcValue) +{ + return _addServiceTxt(p_pcKey, p_pcValue, true); +} + +/* + clsLEAMDNSHost::clsService::addDynamicServiceTxt (uint32_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, + uint32_t p_u32Value) +{ + return _addServiceTxt(p_pcKey, p_u32Value, true); +} + +/* + clsLEAMDNSHost::clsService::addDynamicServiceTxt (uint16_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, + uint16_t p_u16Value) +{ + return _addServiceTxt(p_pcKey, p_u16Value, true); +} + +/* + clsLEAMDNSHost::clsService::addDynamicServiceTxt (uint8_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, + uint8_t p_u8Value) +{ + return _addServiceTxt(p_pcKey, p_u8Value, true); +} + +/* + clsLEAMDNSHost::clsService::addDynamicServiceTxt (int32_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, + int32_t p_i32Value) +{ + return _addServiceTxt(p_pcKey, p_i32Value, true); +} + +/* + clsLEAMDNSHost::clsService::addDynamicServiceTxt (int16_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, + int16_t p_i16Value) +{ + return _addServiceTxt(p_pcKey, p_i16Value, true); +} + +/* + clsLEAMDNSHost::clsService::addDynamicServiceTxt (int8_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, + int8_t p_i8Value) +{ + return _addServiceTxt(p_pcKey, p_i8Value, true); +} + +/* + clsLEAMDNSHost::clsService::setDynamicServiceTxtCallback + +*/ +bool clsLEAMDNSHost::clsService::setDynamicServiceTxtCallback(fnDynamicServiceTxtCallback p_fnCallback) +{ + m_fnTxtCallback = p_fnCallback; + return true; +} + +/* + clsLEAMDNSHost::clsService::_addServiceTxt (const char*) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp) +{ + clsServiceTxt* pServiceTxt = 0; + + if ((p_pcKey) && + (*p_pcKey)) + { + if ((pServiceTxt = m_Txts.find(p_pcKey))) + { + // Change existing TXT + if (clsConsts::stServiceTxtMaxLength > (m_Txts.length() - + (pServiceTxt->m_pcValue ? strlen(pServiceTxt->m_pcValue) : 0) + + (p_pcValue ? strlen(p_pcValue) : 0))) + { + // Enough space left for changed content + if (!pServiceTxt->update(p_pcValue)) + { + // FAILED to update + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[LEAmDNS2_Host] clsService::_addServiceTxt: FAILED to update TXT item '%s'!\n"), p_pcKey)); + pServiceTxt = 0; + } + } + else + { + // NOT enough space for changed TXT content + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[LEAmDNS2_Host] clsService::_addServiceTxt: FAILED to change TXT item '%s' (too large)!\n"), p_pcKey)); + pServiceTxt = 0; + } + } + else + { + // Create new TXT + if (clsConsts::stServiceTxtMaxLength > (m_Txts.length() + + 1 + // Length byte + (p_pcKey ? strlen(p_pcKey) : 0) + + 1 + // '=' + (p_pcValue ? strlen(p_pcValue) : 0))) + { + if (!(((pServiceTxt = new clsServiceTxt)) && + (pServiceTxt->set(p_pcKey, p_pcValue, p_bTemp)) && + (m_Txts.add(pServiceTxt)))) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[LEAmDNS2_Host] clsService::_addServiceTxt: FAILED to add TXT item '%s'!\n"), p_pcKey)); + if (pServiceTxt) + { + delete pServiceTxt; + pServiceTxt = 0; + } + } + } + else + { + // NOT enough space for added TXT item + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[LEAmDNS2_Host] clsService::_addServiceTxt: FAILED to add TXT item '%s' (too large)!\n"), p_pcKey)); + pServiceTxt = 0; + } + } + } + return pServiceTxt; +} + +/* + clsLEAMDNSHost::clsService::_addServiceTxt (uint32_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, + uint32_t p_u32Value, + bool p_bTemp) +{ + char acValueBuffer[16]; // 32-bit max 10 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%u", p_u32Value); + + return _addServiceTxt(p_pcKey, acValueBuffer, p_bTemp); +} + +/* + clsLEAMDNSHost::clsService::_addServiceTxt (uint16_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, + uint16_t p_u16Value, + bool p_bTemp) +{ + char acValueBuffer[8]; // 16-bit max 5 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%hu", p_u16Value); + + return _addServiceTxt(p_pcKey, acValueBuffer, p_bTemp); +} + +/* + clsLEAMDNSHost::clsService::_addServiceTxt (uint8_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, + uint8_t p_u8Value, + bool p_bTemp) +{ + char acValueBuffer[8]; // 8-bit max 3 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%hhu", p_u8Value); + + return _addServiceTxt(p_pcKey, acValueBuffer, p_bTemp); +} + +/* + clsLEAMDNSHost::clsService::_addServiceTxt (int32_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, + int32_t p_i32Value, + bool p_bTemp) +{ + char acValueBuffer[16]; // 32-bit max 10 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%i", p_i32Value); + + return _addServiceTxt(p_pcKey, acValueBuffer, p_bTemp); +} + +/* + clsLEAMDNSHost::clsService::_addServiceTxt (int16_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, + int16_t p_i16Value, + bool p_bTemp) +{ + char acValueBuffer[8]; // 16-bit max 5 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%hi", p_i16Value); + + return _addServiceTxt(p_pcKey, acValueBuffer, p_bTemp); +} + +/* + clsLEAMDNSHost::clsService::_addServiceTxt (int8_t) + +*/ +clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, + int8_t p_i8Value, + bool p_bTemp) +{ + char acValueBuffer[8]; // 8-bit max 3 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%hhi", p_i8Value); + + return _addServiceTxt(p_pcKey, acValueBuffer, p_bTemp); +} + + +/** + clsLEAMDNSHost::clsMsgHeader + + A MDNS message header. + +*/ + +/* + clsLEAMDNSHost::clsMsgHeader::clsMsgHeader + +*/ +clsLEAMDNSHost::clsMsgHeader::clsMsgHeader(uint16_t p_u16ID /*= 0*/, + bool p_bQR /*= false*/, + uint8_t p_u8Opcode /*= 0*/, + bool p_bAA /*= false*/, + bool p_bTC /*= false*/, + bool p_bRD /*= false*/, + bool p_bRA /*= false*/, + uint8_t p_u8RCode /*= 0*/, + uint16_t p_u16QDCount /*= 0*/, + uint16_t p_u16ANCount /*= 0*/, + uint16_t p_u16NSCount /*= 0*/, + uint16_t p_u16ARCount /*= 0*/) + : m_u16ID(p_u16ID), + m_1bQR(p_bQR), m_4bOpcode(p_u8Opcode), m_1bAA(p_bAA), m_1bTC(p_bTC), m_1bRD(p_bRD), + m_1bRA(p_bRA), m_3bZ(0), m_4bRCode(p_u8RCode), + m_u16QDCount(p_u16QDCount), + m_u16ANCount(p_u16ANCount), + m_u16NSCount(p_u16NSCount), + m_u16ARCount(p_u16ARCount) +{ +} + + +/** + clsLEAMDNSHost::clsRRDomain + + A MDNS domain object. + The labels of the domain are stored (DNS-like encoded) in 'm_acName': + [length byte]varlength label[length byte]varlength label[0] + 'm_u16NameLength' stores the used length of 'm_acName'. + Dynamic label addition is supported. + Comparison is supported. + Export as byte array 'esp8266.local' is supported. + +*/ + +/* + clsLEAMDNSHost::clsRRDomain::clsRRDomain constructor + +*/ +clsLEAMDNSHost::clsRRDomain::clsRRDomain(void) + : m_u16NameLength(0), + m_pcDecodedName(0) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsRRDomain::clsRRDomain copy-constructor + +*/ +clsLEAMDNSHost::clsRRDomain::clsRRDomain(const clsRRDomain& p_Other) + : m_u16NameLength(0), + m_pcDecodedName(0) +{ + operator=(p_Other); +} + +/* + clsLEAMDNSHost::clsRRDomain::clsRRDomain destructor + +*/ +clsLEAMDNSHost::clsRRDomain::~clsRRDomain(void) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsRRDomain::operator = + +*/ +clsLEAMDNSHost::clsRRDomain& clsLEAMDNSHost::clsRRDomain::operator=(const clsRRDomain& p_Other) +{ + if (&p_Other != this) + { + clear(); + memcpy(m_acName, p_Other.m_acName, sizeof(m_acName)); + m_u16NameLength = p_Other.m_u16NameLength; + } + return *this; +} + +/* + clsLEAMDNSHost::clsRRDomain::clear + +*/ +bool clsLEAMDNSHost::clsRRDomain::clear(void) +{ + memset(m_acName, 0, sizeof(m_acName)); + m_u16NameLength = 0; + return clearNameCache(); +} + +/* + clsLEAMDNSHost::clsRRDomain::clearNameCache + +*/ +bool clsLEAMDNSHost::clsRRDomain::clearNameCache(void) +{ + if (m_pcDecodedName) + { + delete[] m_pcDecodedName; + m_pcDecodedName = 0; + } + return true; +} + +/* + clsLEAMDNSHost::clsRRDomain::addLabel + +*/ +bool clsLEAMDNSHost::clsRRDomain::addLabel(const char* p_pcLabel, + bool p_bPrependUnderline /*= false*/) +{ + bool bResult = false; + + size_t stLength = (p_pcLabel + ? (strlen(p_pcLabel) + (p_bPrependUnderline ? 1 : 0)) + : 0); + if ((clsConsts::stDomainLabelMaxLength >= stLength) && + (clsConsts::stDomainMaxLength >= (m_u16NameLength + (1 + stLength)))) + { + // Length byte + m_acName[m_u16NameLength] = (unsigned char)stLength; // Might be 0! + ++m_u16NameLength; + // Label + if (stLength) + { + if (p_bPrependUnderline) + { + m_acName[m_u16NameLength++] = '_'; + --stLength; + } + strncpy(&(m_acName[m_u16NameLength]), p_pcLabel, stLength); m_acName[m_u16NameLength + stLength] = 0; + m_u16NameLength += stLength; + } + bResult = clearNameCache(); + } + return bResult; +} + +/* + clsLEAMDNSHost::clsRRDomain::compare + +*/ +bool clsLEAMDNSHost::clsRRDomain::compare(const clsRRDomain& p_Other) const +{ + bool bResult = false; + + if (m_u16NameLength == p_Other.m_u16NameLength) + { + const char* pT = m_acName; + const char* pO = p_Other.m_acName; + while ((pT) && + (pO) && + (*((unsigned char*)pT) == *((unsigned char*)pO)) && // Same length AND + (0 == strncasecmp((pT + 1), (pO + 1), *((unsigned char*)pT)))) // Same content + { + if (*((unsigned char*)pT)) // Not 0 + { + pT += (1 + * ((unsigned char*)pT)); // Shift by length byte and lenght + pO += (1 + * ((unsigned char*)pO)); + } + else // Is 0 -> Successfully reached the end + { + bResult = true; + break; + } + } + } + return bResult; +} + +/* + clsLEAMDNSHost::clsRRDomain::operator == + +*/ +bool clsLEAMDNSHost::clsRRDomain::operator==(const clsRRDomain& p_Other) const +{ + return compare(p_Other); +} + +/* + clsLEAMDNSHost::clsRRDomain::operator != + +*/ +bool clsLEAMDNSHost::clsRRDomain::operator!=(const clsRRDomain& p_Other) const +{ + return !compare(p_Other); +} + +/* + clsLEAMDNSHost::clsRRDomain::operator > + +*/ +bool clsLEAMDNSHost::clsRRDomain::operator>(const clsRRDomain& p_Other) const +{ + // TODO: Check, if this is a good idea... + return !compare(p_Other); +} + +/* + clsLEAMDNSHost::clsRRDomain::c_strLength + +*/ +size_t clsLEAMDNSHost::clsRRDomain::c_strLength(void) const +{ + size_t stLength = 0; + + unsigned char* pucLabelLength = (unsigned char*)m_acName; + while (*pucLabelLength) + { + stLength += (*pucLabelLength + 1 /* +1 for '.' or '\0'*/); + pucLabelLength += (*pucLabelLength + 1); + } + return stLength; +} + +/* + clsLEAMDNSHost::clsRRDomain::c_str (const) + +*/ +bool clsLEAMDNSHost::clsRRDomain::c_str(char* p_pcBuffer) const +{ + bool bResult = false; + + if (p_pcBuffer) + { + *p_pcBuffer = 0; + unsigned char* pucLabelLength = (unsigned char*)m_acName; + while (*pucLabelLength) + { + memcpy(p_pcBuffer, (const char*)(pucLabelLength + 1), *pucLabelLength); + p_pcBuffer += *pucLabelLength; + pucLabelLength += (*pucLabelLength + 1); + *p_pcBuffer++ = (*pucLabelLength ? '.' : '\0'); + } + bResult = true; + } + return bResult; +} + +/* + clsLEAMDNSHost::clsRRDomain::c_str + +*/ +const char* clsLEAMDNSHost::clsRRDomain::c_str(void) const +{ + if ((!m_pcDecodedName) && + (m_u16NameLength) && + ((((clsRRDomain*)this)->m_pcDecodedName = new char[c_strLength()]))) // TRANSPARENT caching + { + ((clsRRDomain*)this)->c_str(m_pcDecodedName); + } + return m_pcDecodedName; +} + + +/** + clsLEAMDNSHost::clsRRAttributes + + A MDNS attributes object. + +*/ + +/* + clsLEAMDNSHost::clsRRAttributes::clsRRAttributes constructor + +*/ +clsLEAMDNSHost::clsRRAttributes::clsRRAttributes(uint16_t p_u16Type /*= 0*/, + uint16_t p_u16Class /*= 1 DNS_RRCLASS_IN Internet*/) + : m_u16Type(p_u16Type), + m_u16Class(p_u16Class) +{ +} + +/* + clsLEAMDNSHost::clsRRAttributes::clsRRAttributes copy-constructor + +*/ +clsLEAMDNSHost::clsRRAttributes::clsRRAttributes(const clsLEAMDNSHost::clsRRAttributes& p_Other) +{ + operator=(p_Other); +} + +/* + clsLEAMDNSHost::clsRRAttributes::operator = + +*/ +clsLEAMDNSHost::clsRRAttributes& clsLEAMDNSHost::clsRRAttributes::operator=(const clsLEAMDNSHost::clsRRAttributes& p_Other) +{ + if (&p_Other != this) + { + m_u16Type = p_Other.m_u16Type; + m_u16Class = p_Other.m_u16Class; + } + return *this; +} + + +/** + clsLEAMDNSHost::clsRRHeader + + A MDNS record header (domain and attributes) object. + +*/ + +/* + clsLEAMDNSHost::clsRRHeader::clsRRHeader constructor + +*/ +clsLEAMDNSHost::clsRRHeader::clsRRHeader(void) +{ +} + +/* + clsLEAMDNSHost::clsRRHeader::clsRRHeader copy-constructor + +*/ +clsLEAMDNSHost::clsRRHeader::clsRRHeader(const clsRRHeader& p_Other) +{ + operator=(p_Other); +} + +/* + clsLEAMDNSHost::clsRRHeader::operator = + +*/ +clsLEAMDNSHost::clsRRHeader& clsLEAMDNSHost::clsRRHeader::operator=(const clsLEAMDNSHost::clsRRHeader& p_Other) +{ + if (&p_Other != this) + { + m_Domain = p_Other.m_Domain; + m_Attributes = p_Other.m_Attributes; + } + return *this; +} + +/* + clsLEAMDNSHost::clsRRHeader::clear + +*/ +bool clsLEAMDNSHost::clsRRHeader::clear(void) +{ + m_Domain.clear(); + return true; +} + + +/** + clsLEAMDNSHost::clsRRQuestion + + A MDNS question record object (header + question flags) + +*/ + +/* + clsLEAMDNSHost::clsRRQuestion::clsRRQuestion constructor +*/ +clsLEAMDNSHost::clsRRQuestion::clsRRQuestion(void) + : m_bUnicast(false) +{ +} + + +/** + clsLEAMDNSHost::clsNSECBitmap + + A MDNS question record object (header + question flags) + +*/ + +/* + clsLEAMDNSHost::clsNSECBitmap::clsNSECBitmap constructor + +*/ +clsLEAMDNSHost::clsNSECBitmap::clsNSECBitmap(void) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsNSECBitmap::clsNSECBitmap destructor + +*/ +bool clsLEAMDNSHost::clsNSECBitmap::clear(void) +{ + memset(m_au8BitmapData, 0, sizeof(m_au8BitmapData)); + return true; +} + +/* + clsLEAMDNSHost::clsNSECBitmap::length + +*/ +uint16_t clsLEAMDNSHost::clsNSECBitmap::length(void) const +{ + return sizeof(m_au8BitmapData); // 6 +} + +/* + clsLEAMDNSHost::clsNSECBitmap::setBit + +*/ +bool clsLEAMDNSHost::clsNSECBitmap::setBit(uint16_t p_u16Bit) +{ + bool bResult = false; + + if ((p_u16Bit) && + (length() > (p_u16Bit / 8))) // bit between 0..47(2F) + { + + uint8_t& ru8Byte = m_au8BitmapData[p_u16Bit / 8]; + uint8_t u8Flag = 1 << (7 - (p_u16Bit % 8)); // (7 - (0..7)) = 7..0 + + ru8Byte |= u8Flag; + + bResult = true; + } + return bResult; +} + +/* + clsLEAMDNSHost::clsNSECBitmap::getBit + +*/ +bool clsLEAMDNSHost::clsNSECBitmap::getBit(uint16_t p_u16Bit) const +{ + bool bResult = false; + + if ((p_u16Bit) && + (length() > (p_u16Bit / 8))) // bit between 0..47(2F) + { + + uint8_t u8Byte = m_au8BitmapData[p_u16Bit / 8]; + uint8_t u8Flag = 1 << (7 - (p_u16Bit % 8)); // (7 - (0..7)) = 7..0 + + bResult = (u8Byte & u8Flag); + } + return bResult; +} + + +/** + clsLEAMDNSHost::clsRRAnswer + + A MDNS answer record object (header + answer content). + This is a 'virtual' base class for all other MDNS answer classes. + +*/ + +/* + clsLEAMDNSHost::clsRRAnswer::clsRRAnswer constructor + +*/ +clsLEAMDNSHost::clsRRAnswer::clsRRAnswer(enuAnswerType p_AnswerType, + const clsLEAMDNSHost::clsRRHeader& p_Header, + uint32_t p_u32TTL) + : m_pNext(0), + m_AnswerType(p_AnswerType), + m_Header(p_Header), + m_u32TTL(p_u32TTL) +{ + // Extract 'cache flush'-bit + m_bCacheFlush = (m_Header.m_Attributes.m_u16Class & 0x8000); + m_Header.m_Attributes.m_u16Class &= (~0x8000); +} + +/* + clsLEAMDNSHost::clsRRAnswer::~stcRRAnswer destructor + +*/ +clsLEAMDNSHost::clsRRAnswer::~clsRRAnswer(void) +{ +} + +/* + clsLEAMDNSHost::clsRRAnswer::answerType + +*/ +clsLEAMDNSHost::enuAnswerType clsLEAMDNSHost::clsRRAnswer::answerType(void) const +{ + return m_AnswerType; +} + +/* + clsLEAMDNSHost::clsRRAnswer::clear + +*/ +bool clsLEAMDNSHost::clsRRAnswer::clear(void) +{ + m_pNext = 0; + m_Header.clear(); + return true; +} + + +/** + clsLEAMDNSHost::clsRRAnswerA + + A MDNS A answer object. + Extends the base class by an IPv4 address member. + +*/ + +#ifdef MDNS_IPV4_SUPPORT +/* + clsLEAMDNSHost::clsRRAnswerA::clsRRAnswerA constructor + +*/ +clsLEAMDNSHost::clsRRAnswerA::clsRRAnswerA(const clsLEAMDNSHost::clsRRHeader& p_Header, + uint32_t p_u32TTL) + : clsRRAnswer(enuAnswerType::A, p_Header, p_u32TTL), + m_IPAddress() +{ +} + +/* + clsLEAMDNSHost::clsRRAnswerA::clsRRAnswerA destructor + +*/ +clsLEAMDNSHost::clsRRAnswerA::~clsRRAnswerA(void) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsRRAnswerA::clear + +*/ +bool clsLEAMDNSHost::clsRRAnswerA::clear(void) +{ + m_IPAddress = IPAddress(); + return true; +} +#endif + + +/** + clsLEAMDNSHost::clsRRAnswerPTR + + A MDNS PTR answer object. + Extends the base class by a MDNS domain member. + +*/ + +/* + clsLEAMDNSHost::clsRRAnswerPTR::clsRRAnswerPTR constructor + +*/ +clsLEAMDNSHost::clsRRAnswerPTR::clsRRAnswerPTR(const clsLEAMDNSHost::clsRRHeader& p_Header, + uint32_t p_u32TTL) + : clsRRAnswer(enuAnswerType::PTR, p_Header, p_u32TTL) +{ +} + +/* + clsLEAMDNSHost::clsRRAnswerPTR::~stcRRAnswerPTR destructor + +*/ +clsLEAMDNSHost::clsRRAnswerPTR::~clsRRAnswerPTR(void) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsRRAnswerPTR::clear + +*/ +bool clsLEAMDNSHost::clsRRAnswerPTR::clear(void) +{ + m_PTRDomain.clear(); + return true; +} + + +/** + clsLEAMDNSHost::clsRRAnswerTXT + + A MDNS TXT answer object. + Extends the base class by a MDNS TXT items list member. + +*/ + +/* + clsLEAMDNSHost::clsRRAnswerTXT::clsRRAnswerTXT constructor + +*/ +clsLEAMDNSHost::clsRRAnswerTXT::clsRRAnswerTXT(const clsLEAMDNSHost::clsRRHeader& p_Header, + uint32_t p_u32TTL) + : clsRRAnswer(enuAnswerType::TXT, p_Header, p_u32TTL) +{ +} + +/* + clsLEAMDNSHost::clsRRAnswerTXT::~stcRRAnswerTXT destructor + +*/ +clsLEAMDNSHost::clsRRAnswerTXT::~clsRRAnswerTXT(void) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsRRAnswerTXT::clear + +*/ +bool clsLEAMDNSHost::clsRRAnswerTXT::clear(void) +{ + m_Txts.clear(); + return true; +} + + +/** + clsLEAMDNSHost::clsRRAnswerAAAA + + A MDNS AAAA answer object. + Extends the base class by an IPv6 address member. + +*/ + +#ifdef MDNS_IPV6_SUPPORT +/* + clsLEAMDNSHost::clsRRAnswerAAAA::clsRRAnswerAAAA constructor + +*/ +clsLEAMDNSHost::clsRRAnswerAAAA::clsRRAnswerAAAA(const clsLEAMDNSHost::clsRRHeader& p_Header, + uint32_t p_u32TTL) + : clsRRAnswer(enuAnswerType::AAAA, p_Header, p_u32TTL), + m_IPAddress() +{ +} + +/* + clsLEAMDNSHost::clsRRAnswerAAAA::~stcRRAnswerAAAA destructor + +*/ +clsLEAMDNSHost::clsRRAnswerAAAA::~clsRRAnswerAAAA(void) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsRRAnswerAAAA::clear + +*/ +bool clsLEAMDNSHost::clsRRAnswerAAAA::clear(void) +{ + m_IPAddress = IPAddress(); + return true; +} +#endif + + +/** + clsLEAMDNSHost::clsRRAnswerSRV + + A MDNS SRV answer object. + Extends the base class by a port member. + +*/ + +/* + clsLEAMDNSHost::clsRRAnswerSRV::clsRRAnswerSRV constructor + +*/ +clsLEAMDNSHost::clsRRAnswerSRV::clsRRAnswerSRV(const clsLEAMDNSHost::clsRRHeader& p_Header, + uint32_t p_u32TTL) + : clsRRAnswer(enuAnswerType::SRV, p_Header, p_u32TTL), + m_u16Priority(0), + m_u16Weight(0), + m_u16Port(0) +{ +} + +/* + clsLEAMDNSHost::clsRRAnswerSRV::~stcRRAnswerSRV destructor + +*/ +clsLEAMDNSHost::clsRRAnswerSRV::~clsRRAnswerSRV(void) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsRRAnswerSRV::clear + +*/ +bool clsLEAMDNSHost::clsRRAnswerSRV::clear(void) +{ + m_u16Priority = 0; + m_u16Weight = 0; + m_u16Port = 0; + m_SRVDomain.clear(); + return true; +} + + +/** + clsLEAMDNSHost::clsRRAnswerGeneric + + An unknown (generic) MDNS answer object. + Extends the base class by a RDATA buffer member. + +*/ + +/* + clsLEAMDNSHost::clsRRAnswerGeneric::clsRRAnswerGeneric constructor + +*/ +clsLEAMDNSHost::clsRRAnswerGeneric::clsRRAnswerGeneric(const clsRRHeader& p_Header, + uint32_t p_u32TTL) + : clsRRAnswer(enuAnswerType::Generic, p_Header, p_u32TTL), + m_u16RDLength(0), + m_pu8RDData(0) +{ +} + +/* + clsLEAMDNSHost::clsRRAnswerGeneric::~stcRRAnswerGeneric destructor + +*/ +clsLEAMDNSHost::clsRRAnswerGeneric::~clsRRAnswerGeneric(void) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsRRAnswerGeneric::clear + +*/ +bool clsLEAMDNSHost::clsRRAnswerGeneric::clear(void) +{ + if (m_pu8RDData) + { + delete[] m_pu8RDData; + m_pu8RDData = 0; + } + m_u16RDLength = 0; + + return true; +} + + +/** + clsLEAMDNSHost::clsSendParameter + + A 'collection' of properties and flags for one MDNS query or response. + Mainly managed by the 'Control' functions. + The current offset in the UPD output buffer is tracked to be able to do + a simple host or service domain compression. + +*/ + +/** + clsLEAMDNSHost::clsSendParameter::clsDomainCacheItem + + A cached host or service domain, incl. the offset in the UDP output buffer. + +*/ + +/* + clsLEAMDNSHost::clsSendParameter::clsDomainCacheItem::clsDomainCacheItem constructor + +*/ +clsLEAMDNSHost::clsSendParameter::clsDomainCacheItem::clsDomainCacheItem(const void* p_pHostNameOrService, + bool p_bAdditionalData, + uint32_t p_u16Offset) + : m_pHostNameOrService(p_pHostNameOrService), + m_bAdditionalData(p_bAdditionalData), + m_u16Offset(p_u16Offset) +{ +} + +/** + clsLEAMDNSHost::clsSendParameter + +*/ + +/* + clsLEAMDNSHost::clsSendParameter::clsSendParameter constructor + +*/ +clsLEAMDNSHost::clsSendParameter::clsSendParameter(void) + : m_u16ID(0), + m_u32HostReplyMask(0), + m_bLegacyDNSQuery(false), + m_Response(enuResponseType::None), + m_bAuthorative(false), + m_bCacheFlush(false), + m_bUnicast(false), + m_bUnannounce(false), + m_u16Offset(0) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsSendParameter::~stcSendParameter destructor + +*/ +clsLEAMDNSHost::clsSendParameter::~clsSendParameter(void) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsSendParameter::clear + +*/ +bool clsLEAMDNSHost::clsSendParameter::clear(void) +{ + m_u16ID = 0; + flushQuestions(); + m_u32HostReplyMask = 0; + + m_bLegacyDNSQuery = false; + m_Response = enuResponseType::None; + m_bAuthorative = false; + m_bCacheFlush = true; + m_bUnicast = false; + m_bUnannounce = false; + + m_u16Offset = 0; + flushDomainCache(); + return true; +} + +/* + clsLEAMDNSHost::clsSendParameter::flushQuestions + +*/ +bool clsLEAMDNSHost::clsSendParameter::flushQuestions(void) +{ + for (clsRRQuestion* pRRQuestion : m_RRQuestions) + { + delete pRRQuestion; + } + m_RRQuestions.clear(); + return true; +} + +/* + clsLEAMDNSHost::clsSendParameter::flushDomainCache + +*/ +bool clsLEAMDNSHost::clsSendParameter::flushDomainCache(void) +{ + for (clsDomainCacheItem* pDomainCacheItem : m_DomainCacheItems) + { + delete pDomainCacheItem; + } + m_DomainCacheItems.clear(); + return true; +} + +/* + clsLEAMDNSHost::clsSendParameter::flushTempContent + +*/ +bool clsLEAMDNSHost::clsSendParameter::flushTempContent(void) +{ + m_u16Offset = 0; + flushDomainCache(); + return true; +} + +/* + clsLEAMDNSHost::clsSendParameter::shiftOffset + +*/ +bool clsLEAMDNSHost::clsSendParameter::shiftOffset(uint16_t p_u16Shift) +{ + m_u16Offset += p_u16Shift; + return true; +} + +/* + clsLEAMDNSHost::clsSendParameter::addDomainCacheItem + +*/ +bool clsLEAMDNSHost::clsSendParameter::addDomainCacheItem(const void* p_pHostNameOrService, + bool p_bAdditionalData, + uint16_t p_u16Offset) +{ + bool bResult = false; + + clsDomainCacheItem* pNewItem = 0; + if ((p_pHostNameOrService) && + (p_u16Offset) && + ((pNewItem = new clsDomainCacheItem(p_pHostNameOrService, p_bAdditionalData, p_u16Offset)))) + { + m_DomainCacheItems.push_back(pNewItem); + bResult = true; + } + return bResult; +} + +/* + clsLEAMDNSHost::clsSendParameter::findCachedDomainOffset + +*/ +uint16_t clsLEAMDNSHost::clsSendParameter::findCachedDomainOffset(const void* p_pHostNameOrService, + bool p_bAdditionalData) const +{ + const clsDomainCacheItem* pMatchingCacheItem = 0; + + for (const clsDomainCacheItem* pCacheItem : m_DomainCacheItems) + { + if ((pCacheItem->m_pHostNameOrService == p_pHostNameOrService) && + (pCacheItem->m_bAdditionalData == p_bAdditionalData)) // Found cache item + { + pMatchingCacheItem = pCacheItem; + break; + } + } + return (pMatchingCacheItem ? pMatchingCacheItem->m_u16Offset : 0); +} + + +/** + clsLEAMDNSHost::clsQuery + + A MDNS service query object. + Service queries may be static or dynamic. + As the static service query is processed in the blocking function 'queryService', + only one static service service may exist. The processing of the answers is done + on the WiFi-stack side of the ESP stack structure (via 'UDPContext.onRx(_update)'). + +*/ + +/** + clsLEAMDNSHost::clsQuery::clsAnswer + + One answer for a query. + Every answer must contain + - a service instance entry (pivot), + and may contain + - a host domain, + - a port + - an IPv4 address + (- an IPv6 address) + - a MDNS TXTs + The existance of a component is flaged in 'm_u32ContentFlags'. + For every answer component a TTL value is maintained. + Answer objects can be connected to a linked list. + + For the host domain, service domain and TXTs components, a char array + representation can be retrieved (which is created on demand). + +*/ + +/** + clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL + + The TTL (Time-To-Live) for an specific answer content. + If the answer is scheduled for an update, the corresponding flag should be set. + +*/ + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::clsTTL constructor + +*/ +clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::clsTTL(void) + : m_u32TTL(0), + m_TTLTimeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()), + m_TimeoutLevel(static_cast<typeTimeoutLevel>(enuTimeoutLevel::None)) +{ +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::set + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::set(uint32_t p_u32TTL) +{ + m_u32TTL = p_u32TTL; + if (m_u32TTL) + { + m_TimeoutLevel = static_cast<typeTimeoutLevel>(enuTimeoutLevel::Base); // Set to 80% + m_TTLTimeout.reset(timeout()); + } + else + { + m_TimeoutLevel = static_cast<typeTimeoutLevel>(enuTimeoutLevel::None); // undef + m_TTLTimeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + } + return true; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::flagged + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::flagged(void) const +{ + return ((m_u32TTL) && + (static_cast<typeTimeoutLevel>(enuTimeoutLevel::None) != m_TimeoutLevel) && + (((esp8266::polledTimeout::timeoutTemplate<false>*)&m_TTLTimeout)->expired())); // Cast-away the const; in case of oneShot-timer OK (but ugly...) +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::restart + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::restart(void) +{ + bool bResult = true; + + if ((static_cast<typeTimeoutLevel>(enuTimeoutLevel::Base) <= m_TimeoutLevel) && // >= 80% AND + (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final) > m_TimeoutLevel)) // < 100% + { + m_TimeoutLevel += static_cast<typeTimeoutLevel>(enuTimeoutLevel::Interval); // increment by 5% + m_TTLTimeout.reset(timeout()); + } + else + { + bResult = false; + m_TTLTimeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + m_TimeoutLevel = static_cast<typeTimeoutLevel>(enuTimeoutLevel::None); + } + return bResult; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::prepareDeletion + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::prepareDeletion(void) +{ + m_TimeoutLevel = static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final); + m_TTLTimeout.reset(1 * 1000); // See RFC 6762, 10.1 + + return true; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::finalTimeoutLevel + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::finalTimeoutLevel(void) const +{ + return (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final) == m_TimeoutLevel); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::timeout + +*/ +unsigned long clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::timeout(void) const +{ + uint32_t u32Timeout = std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max(); + + if (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Base) == m_TimeoutLevel) // 80% + { + u32Timeout = (m_u32TTL * 800); // to milliseconds + } + else if ((static_cast<typeTimeoutLevel>(enuTimeoutLevel::Base) < m_TimeoutLevel) && // >80% AND + (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final) >= m_TimeoutLevel)) // <= 100% + { + u32Timeout = (m_u32TTL * 50); + } // else: invalid + return u32Timeout; +} + + +/** + clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddress + +*/ + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddress::clsIPAddress constructor + +*/ +clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL::clsIPAddressWithTTL(IPAddress p_IPAddress, + uint32_t p_u32TTL /*= 0*/) + : m_IPAddress(p_IPAddress) +{ + m_TTL.set(p_u32TTL); +} + + +/** + clsLEAMDNSHost::clsQuery::clsAnswer + +*/ + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::clsAnswer constructor + +*/ +clsLEAMDNSHost::clsQuery::clsAnswer::clsAnswer(void) + : m_u16Port(0), + m_QueryAnswerFlags(0) +{ +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::~clsAnswer destructor + +*/ +clsLEAMDNSHost::clsQuery::clsAnswer::~clsAnswer(void) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::clear + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswer::clear(void) +{ + return ( +#ifdef MDNS_IPV4_SUPPORT + (releaseIPv4Addresses()) +#else + (true) +#endif + && +#ifdef MDNS_IPV6_SUPPORT + (releaseIPv6Addresses()) +#else + (true) +#endif + ); +} + +#ifdef MDNS_IPV4_SUPPORT +/* + clsLEAMDNSHost::clsQuery::clsAnswer::releaseIPv4Addresses + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswer::releaseIPv4Addresses(void) +{ + for (clsIPAddressWithTTL* pIPAddress : m_IPv4Addresses) + { + delete pIPAddress; + } + m_IPv4Addresses.clear(); + return true; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::addIPv4Address + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswer::addIPv4Address(clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* p_pIPv4Address) +{ + bool bResult = false; + + if (p_pIPv4Address) + { + m_IPv4Addresses.push_back(p_pIPv4Address); + bResult = true; + } + return bResult; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::removeIPv4Address + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswer::removeIPv4Address(clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* p_pIPv4Address) +{ + bool bResult = false; + + clsIPAddressWithTTL::list::iterator it(p_pIPv4Address + ? std::find(m_IPv4Addresses.begin(), m_IPv4Addresses.end(), p_pIPv4Address) + : m_IPv4Addresses.end()); + if (m_IPv4Addresses.end() != it) + { + m_IPv4Addresses.erase(it); + delete p_pIPv4Address; + + bResult = true; + } + return bResult; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::findIPv4Address (const) + +*/ +const clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* clsLEAMDNSHost::clsQuery::clsAnswer::findIPv4Address(const IPAddress& p_IPAddress) const +{ + return (clsIPAddressWithTTL*)(((const clsAnswer*)this)->findIPv4Address(p_IPAddress)); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::findIPv4Address + +*/ +clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* clsLEAMDNSHost::clsQuery::clsAnswer::findIPv4Address(const IPAddress& p_IPAddress) +{ + clsIPAddressWithTTL* pMatchingIPv4Address = 0; + + for (clsIPAddressWithTTL* pIPv4Address : m_IPv4Addresses) + { + if (pIPv4Address->m_IPAddress == p_IPAddress) + { + pMatchingIPv4Address = pIPv4Address; + break; + } + } + return pMatchingIPv4Address; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::IPv4AddressCount + +*/ +uint32_t clsLEAMDNSHost::clsQuery::clsAnswer::IPv4AddressCount(void) const +{ + uint32_t u32Count = m_IPv4Addresses.size(); + return u32Count; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::IPv4AddressAtIndex + +*/ +clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* clsLEAMDNSHost::clsQuery::clsAnswer::IPv4AddressAtIndex(uint32_t p_u32Index) +{ + return (clsIPAddressWithTTL*)(((const clsAnswer*)this)->IPv4AddressAtIndex(p_u32Index)); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::IPv4AddressAtIndex (const) + +*/ +const clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* clsLEAMDNSHost::clsQuery::clsAnswer::IPv4AddressAtIndex(uint32_t p_u32Index) const +{ + const clsIPAddressWithTTL* pIPv4AddressAtIndex = 0; + + uint32_t u32CurIndex = 0; + for (clsIPAddressWithTTL::list::const_iterator it = m_IPv4Addresses.begin(); + (((uint32_t)(-1) != p_u32Index) && (u32CurIndex <= p_u32Index) && (it != m_IPv4Addresses.end())); + it++, u32CurIndex++) + { + if (p_u32Index == u32CurIndex++) + { + pIPv4AddressAtIndex = *it; + break; + } + } + return pIPv4AddressAtIndex; +} +#endif + +#ifdef MDNS_IPV6_SUPPORT +/* + clsLEAMDNSHost::clsQuery::clsAnswer::releaseIPv6Addresses + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswer::releaseIPv6Addresses(void) +{ + for (clsIPAddressWithTTL* pIPAddress : m_IPv6Addresses) + { + delete pIPAddress; + } + m_IPv6Addresses.clear(); + return true; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::addIPv6Address + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswer::addIPv6Address(clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* p_pIPv6Address) +{ + bool bResult = false; + + if (p_pIPv6Address) + { + m_IPv6Addresses.push_back(p_pIPv6Address); + bResult = true; + } + return bResult; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::removeIPv6Address + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswer::removeIPv6Address(clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* p_pIPv6Address) +{ + bool bResult = false; + + clsIPAddressWithTTL::list::iterator it(p_pIPv6Address + ? std::find(m_IPv6Addresses.begin(), m_IPv6Addresses.end(), p_pIPv6Address) + : m_IPv6Addresses.end()); + if (m_IPv6Addresses.end() != it) + { + m_IPv6Addresses.erase(it); + delete p_pIPv6Address; + + bResult = true; + } + return bResult; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::findIPv6Address + +*/ +clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* clsLEAMDNSHost::clsQuery::clsAnswer::findIPv6Address(const IPAddress& p_IPAddress) +{ + return (clsIPAddressWithTTL*)(((const clsAnswer*)this)->findIPv6Address(p_IPAddress)); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::findIPv6Address (const) + +*/ +const clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* clsLEAMDNSHost::clsQuery::clsAnswer::findIPv6Address(const IPAddress& p_IPAddress) const +{ + clsIPAddressWithTTL* pMatchingIPv6Address = 0; + + for (clsIPAddressWithTTL* pIPv6Address : m_IPv6Addresses) + { + if (pIPv6Address->m_IPAddress == p_IPAddress) + { + pMatchingIPv6Address = pIPv6Address; + break; + } + } + return pMatchingIPv6Address; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::IPv6AddressCount + +*/ +uint32_t clsLEAMDNSHost::clsQuery::clsAnswer::IPv6AddressCount(void) const +{ + uint32_t u32Count = m_IPv6Addresses.size(); + return u32Count; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::IPv6AddressAtIndex + +*/ +clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* clsLEAMDNSHost::clsQuery::clsAnswer::IPv6AddressAtIndex(uint32_t p_u32Index) +{ + return (clsIPAddressWithTTL*)(((const clsAnswer*)this)->IPv6AddressAtIndex(p_u32Index)); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswer::IPv6AddressAtIndex (const) + +*/ +const clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* clsLEAMDNSHost::clsQuery::clsAnswer::IPv6AddressAtIndex(uint32_t p_u32Index) const +{ + const clsIPAddressWithTTL* pIPv6AddressAtIndex = 0; + + uint32_t u32CurIndex = 0; + for (clsIPAddressWithTTL::list::const_iterator it = m_IPv6Addresses.begin(); + (((uint32_t)(-1) != p_u32Index) && (u32CurIndex <= p_u32Index) && (it != m_IPv6Addresses.end())); + it++, u32CurIndex++) + { + if (p_u32Index == u32CurIndex++) + { + pIPv6AddressAtIndex = *it; + break; + } + } + return pIPv6AddressAtIndex; +} +#endif + + +/** + clsLEAMDNSHost::clsQuery::clsAnswerAccessor + +*/ + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::clsAnswerAccessor constructor + +*/ +clsLEAMDNSHost::clsQuery::clsAnswerAccessor::clsAnswerAccessor(const clsLEAMDNSHost::clsQuery::clsAnswer* p_pAnswer) + : m_pAnswer(p_pAnswer) +{ + if ((m_pAnswer) && + (txtsAvailable())) + { + // Prepare m_TxtKeyValueMap + for (const clsLEAMDNSHost::clsServiceTxt* pTxt : m_pAnswer->m_Txts.m_Txts) + { + m_TxtKeyValueMap.emplace(std::pair<const char*, const char*>(pTxt->m_pcKey, pTxt->m_pcValue)); + } + } +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::~clsAnswerAccessor destructor +*/ +clsLEAMDNSHost::clsQuery::clsAnswerAccessor::~clsAnswerAccessor(void) +{ +} + +/** + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::clsCompareTxtKey + +*/ + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::stcCompareTxtKey::operator() + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswerAccessor::stcCompareTxtKey::operator()(char const* p_pA, + char const* p_pB) const +{ + return (0 > strcasecmp(p_pA, p_pB)); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::serviceDomainAvailable + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswerAccessor::serviceDomainAvailable(void) const +{ + return ((m_pAnswer) && + (m_pAnswer->m_QueryAnswerFlags & static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain))); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::serviceDomain + +*/ +const char* clsLEAMDNSHost::clsQuery::clsAnswerAccessor::serviceDomain(void) const +{ + return ((m_pAnswer) + ? m_pAnswer->m_ServiceDomain.c_str() + : 0); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::hostDomainAvailable + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswerAccessor::hostDomainAvailable(void) const +{ + return ((m_pAnswer) && + (m_pAnswer->m_QueryAnswerFlags & static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain))); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::hostDomain + +*/ +const char* clsLEAMDNSHost::clsQuery::clsAnswerAccessor::hostDomain(void) const +{ + return ((m_pAnswer) + ? m_pAnswer->m_HostDomain.c_str() + : 0); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::hostPortAvailable + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswerAccessor::hostPortAvailable(void) const +{ + return ((m_pAnswer) && + (m_pAnswer->m_QueryAnswerFlags & static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::Port))); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::hostPort + +*/ +uint16_t clsLEAMDNSHost::clsQuery::clsAnswerAccessor::hostPort(void) const +{ + return ((m_pAnswer) + ? (m_pAnswer->m_u16Port) + : 0); +} + +#ifdef MDNS_IPV4_SUPPORT +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::IPv4AddressAvailable + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswerAccessor::IPv4AddressAvailable(void) const +{ + return ((m_pAnswer) && + (m_pAnswer->m_QueryAnswerFlags & static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address))); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::IPv4Addresses + +*/ +clsLEAMDNSHost::clsQuery::clsAnswerAccessor::clsIPAddressVector clsLEAMDNSHost::clsQuery::clsAnswerAccessor::IPv4Addresses(void) const +{ + clsIPAddressVector internalIP; + if ((m_pAnswer) && + (IPv4AddressAvailable())) + { + for (uint32_t u = 0; u < m_pAnswer->IPv4AddressCount(); ++u) + { + const clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* pIPAddr = m_pAnswer->IPv4AddressAtIndex(u); + if (pIPAddr) + { + internalIP.emplace_back(pIPAddr->m_IPAddress); + } + } + } + return internalIP; +} +#endif + +#ifdef MDNS_IPV6_SUPPORT +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::IPv6AddressAvailable + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswerAccessor::IPv6AddressAvailable(void) const +{ + return ((m_pAnswer) && + (m_pAnswer->m_QueryAnswerFlags & static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address))); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::IPv6Addresses + +*/ +clsLEAMDNSHost::clsQuery::clsAnswerAccessor::clsIPAddressVector clsLEAMDNSHost::clsQuery::clsAnswerAccessor::IPv6Addresses(void) const +{ + clsIPAddressVector internalIP; + if ((m_pAnswer) && + (IPv6AddressAvailable())) + { + for (uint32_t u = 0; u < m_pAnswer->IPv6AddressCount(); ++u) + { + const clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* pIPAddr = m_pAnswer->IPv6AddressAtIndex(u); + if (pIPAddr) + { + internalIP.emplace_back(pIPAddr->m_IPAddress); + } + } + } + return internalIP; +} +#endif + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::txtsAvailable + +*/ +bool clsLEAMDNSHost::clsQuery::clsAnswerAccessor::txtsAvailable(void) const +{ + return ((m_pAnswer) && + (m_pAnswer->m_QueryAnswerFlags & static_cast<clsQuery::clsAnswer::typeQueryAnswerType>(clsQuery::clsAnswer::enuQueryAnswerType::Txts))); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::txts + + Returns all TXT items for the given service as a ';'-separated string. + If not already existing; the string is alloced, filled and attached to the answer. + +*/ +const char* clsLEAMDNSHost::clsQuery::clsAnswerAccessor::txts(void) const +{ + return ((m_pAnswer) + ? m_pAnswer->m_Txts.c_str() + : 0); +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::txtKeyValues + +*/ +const clsLEAMDNSHost::clsQuery::clsAnswerAccessor::clsTxtKeyValueMap& clsLEAMDNSHost::clsQuery::clsAnswerAccessor::txtKeyValues(void) const +{ + return m_TxtKeyValueMap; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::txtValue + +*/ +const char* clsLEAMDNSHost::clsQuery::clsAnswerAccessor::txtValue(const char* p_pcKey) const +{ + char* pcResult = 0; + + if (m_pAnswer) + { + for (const clsLEAMDNSHost::clsServiceTxt* pTxt : m_pAnswer->m_Txts.m_Txts) + { + if ((p_pcKey) && + (0 == strcasecmp(pTxt->m_pcKey, p_pcKey))) + { + pcResult = pTxt->m_pcValue; + break; + } + } + } + return pcResult; +} + +/* + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::printTo + +*/ +size_t clsLEAMDNSHost::clsQuery::clsAnswerAccessor::printTo(Print& p_Print) const +{ + size_t stLen = 0; + const char* cpcI = " * "; + const char* cpcS = " "; + + stLen += p_Print.println(" * * * * *"); + if (hostDomainAvailable()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print("Host domain: "); + stLen += p_Print.println(hostDomain()); + } +#ifdef MDNS_IPV4_SUPPORT + if (IPv4AddressAvailable()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.println("IPv4 address(es):"); + for (const IPAddress& addr : IPv4Addresses()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print(cpcS); + stLen += p_Print.println(addr); + } + } +#endif +#ifdef MDNS_IPV6_SUPPORT + if (IPv6AddressAvailable()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.println("IPv6 address(es):"); + for (const IPAddress& addr : IPv6Addresses()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print(cpcS); + stLen += p_Print.println(addr); + } + } +#endif + if (serviceDomainAvailable()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print("Service domain: "); + stLen += p_Print.println(serviceDomain()); + } + if (hostPortAvailable()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print("Host port: "); + stLen += p_Print.println(hostPort()); + } + if (txtsAvailable()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print("TXTs:"); + for (auto const& x : txtKeyValues()) + { + stLen += p_Print.print(cpcI); + stLen += p_Print.print(cpcS); + stLen += p_Print.print(x.first); + stLen += p_Print.print("="); + stLen += p_Print.println(x.second); + } + } + stLen += p_Print.println(" * * * * *"); + + return stLen; +} + + +/** + clsLEAMDNSHost::clsQuery + + A service or host query object. + A static query is flaged via 'm_bLegacyQuery'; while the function 'queryService' + is waiting for answers, the internal flag 'm_bAwaitingAnswers' is set. When the + timeout is reached, the flag is removed. These two flags are only used for static + service queries. + All answers to the query are stored in the 'm_Answers' list. + Individual answers may be addressed by index (in the list of answers). + Every time a answer component is added (or changed) in a dynamic query, + the callback 'm_fnCallback' is called. + The answer list may be searched by service and host domain. + + Query object may be connected to a linked list. + +*/ + +/* + clsLEAMDNSHost::clsQuery::clsQuery constructor + +*/ +clsLEAMDNSHost::clsQuery::clsQuery(const enuQueryType p_QueryType) + : m_QueryType(p_QueryType), + m_fnCallbackAnswer(0), + m_fnCallbackAccessor(0), + m_bStaticQuery(false), + m_u8SentCount(0), + m_ResendTimeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()), + m_bAwaitingAnswers(true) +{ + clear(); + m_QueryType = p_QueryType; +} + +/* + clsLEAMDNSHost::clsQuery::~stcQuery destructor + +*/ +clsLEAMDNSHost::clsQuery::~clsQuery(void) +{ + clear(); +} + +/* + clsLEAMDNSHost::clsQuery::clear + +*/ +bool clsLEAMDNSHost::clsQuery::clear(void) +{ + m_QueryType = enuQueryType::None; + m_fnCallbackAnswer = 0; + m_fnCallbackAccessor = 0; + m_bStaticQuery = false; + m_u8SentCount = 0; + m_ResendTimeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); + m_bAwaitingAnswers = true; + for (clsAnswer* pAnswer : m_Answers) + { + delete pAnswer; + } + m_Answers.clear(); + return true; +} + +/* + clsLEAMDNSHost::clsQuery::answerCount + +*/ +uint32_t clsLEAMDNSHost::clsQuery::answerCount(void) const +{ + uint32_t u32Count = m_Answers.size(); + return u32Count; +} + +/* + clsLEAMDNSHost::clsQuery::answer + +*/ +const clsLEAMDNSHost::clsQuery::clsAnswer* clsLEAMDNSHost::clsQuery::answer(uint32_t p_u32Index) const +{ + const clsAnswer* pAnswerAtIndex = 0; + + uint32_t u32CurIndex = 0; + for (clsAnswer::list::const_iterator it = m_Answers.begin(); + (((uint32_t)(-1) != p_u32Index) && (u32CurIndex <= p_u32Index) && (it != m_Answers.end())); + it++, u32CurIndex++) + { + if (p_u32Index == u32CurIndex++) + { + pAnswerAtIndex = *it; + break; + } + } + return pAnswerAtIndex; +} + +/* + clsLEAMDNSHost::clsQuery::indexOfAnswer + +*/ +uint32_t clsLEAMDNSHost::clsQuery::indexOfAnswer(const clsLEAMDNSHost::clsQuery::clsAnswer* p_pAnswer) const +{ + uint32_t u32IndexOfAnswer = ((uint32_t)(-1)); + + uint32_t u32CurIndex = 0; + for (const clsAnswer* pAnswer : m_Answers) + { + if (pAnswer == p_pAnswer) + { + u32IndexOfAnswer = u32CurIndex; + break; + } + ++u32CurIndex; + } + return u32IndexOfAnswer; +} + +/* + clsLEAMDNSHost::clsQuery::answerAccessors + +*/ +clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::clsQuery::answerAccessors(void) const +{ + clsAnswerAccessor::vector tempAccessors; + for (const clsAnswer* pAnswer : m_Answers) + { + tempAccessors.emplace_back(pAnswer); + } + return tempAccessors; +} + +/* + clsLEAMDNSHost::clsQuery::answerAccessor + +*/ +clsLEAMDNSHost::clsQuery::clsAnswerAccessor clsLEAMDNSHost::clsQuery::answerAccessor(uint32 p_u32AnswerIndex) const +{ + return clsAnswerAccessor(answer(p_u32AnswerIndex)); +} + +/* + clsLEAMDNSHost::clsQuery::addAnswer + +*/ +bool clsLEAMDNSHost::clsQuery::addAnswer(clsLEAMDNSHost::clsQuery::clsAnswer* p_pAnswer) +{ + bool bResult = false; + + if (p_pAnswer) + { + m_Answers.push_back(p_pAnswer); + bResult = true; + } + return bResult; +} + +/* + clsLEAMDNSHost::clsQuery::removeAnswer + +*/ +bool clsLEAMDNSHost::clsQuery::removeAnswer(clsLEAMDNSHost::clsQuery::clsAnswer* p_pAnswer) +{ + bool bResult = false; + + clsAnswer::list::iterator it(p_pAnswer + ? std::find(m_Answers.begin(), m_Answers.end(), p_pAnswer) + : m_Answers.end()); + if (m_Answers.end() != it) + { + m_Answers.erase(it); + delete p_pAnswer; + + bResult = true; + } + return bResult; +} + +/* + clsLEAMDNSHost::clsQuery::findAnswerForServiceDomain + +*/ +clsLEAMDNSHost::clsQuery::clsAnswer* clsLEAMDNSHost::clsQuery::findAnswerForServiceDomain(const clsLEAMDNSHost::clsRRDomain& p_ServiceDomain) +{ + clsAnswer* pAnswerForServiceDomain = 0; + + for (clsAnswer* pAnswer : m_Answers) + { + if (pAnswer->m_ServiceDomain == p_ServiceDomain) + { + pAnswerForServiceDomain = pAnswer; + break; + } + } + return pAnswerForServiceDomain; +} + +/* + clsLEAMDNSHost::clsQuery::findAnswerForHostDomain + +*/ +clsLEAMDNSHost::clsQuery::clsAnswer* clsLEAMDNSHost::clsQuery::findAnswerForHostDomain(const clsLEAMDNSHost::clsRRDomain& p_HostDomain) +{ + clsAnswer* pAnswerForHostDomain = 0; + + for (clsAnswer* pAnswer : m_Answers) + { + if (pAnswer->m_HostDomain == p_HostDomain) + { + pAnswerForHostDomain = pAnswer; + break; + } + } + return pAnswerForHostDomain; +} + + +} // namespace MDNSImplementation + + +} // namespace esp8266 + + + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp old mode 100755 new mode 100644 similarity index 71% rename from libraries/ESP8266mDNS/src/LEAmDNS2_Host_Transfer.cpp rename to libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 5da81255ab..50880585cc --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -1,5 +1,5 @@ /* - LEAmDNS2_Host_Transfer.cpp + LEAmDNS2Host_Transfer.cpp License (MIT license): Permission is hereby granted, free of charge, to any person obtaining a copy @@ -22,61 +22,35 @@ */ -extern "C" { -#include "user_interface.h" -} - -#include "lwip/netif.h" +#include <coredecls.h> // for can_yield() -#include "LEAmDNS2_lwIPdefs.h" -#include "LEAmDNS2_Priv.h" +#include "LEAmDNS2Host.h" namespace esp8266 { -/* - LEAmDNS -*/ + namespace experimental { -/** - CONST STRINGS -*/ -static const char* scpcLocal = "local"; -static const char* scpcServices = "services"; -static const char* scpcDNSSD = "dns-sd"; -static const char* scpcUDP = "udp"; -//static const char* scpcTCP = "tcp"; - -#ifdef MDNS_IPV4_SUPPORT -static const char* scpcReverseIPv4Domain = "in-addr"; -#endif -#ifdef MDNS_IPV6_SUPPORT -static const char* scpcReverseIPv6Domain = "ip6"; -#endif -static const char* scpcReverseTopDomain = "arpa"; - -/** - TRANSFER -*/ +/* -/** SENDING + */ /* - MDNSResponder::_sendMDNSMessage + MDNSResponder::_sendMessage Unicast responses are prepared and sent directly to the querier. - Multicast responses or queries are transferred to _sendMDNSMessage_Multicast + Multicast responses or queries are transferred to _sendMessage_Multicast Any reply flags in installed services are removed at the end! */ -bool MDNSResponder::clsHost::_sendMDNSMessage(MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { bool bResult = false; @@ -89,7 +63,7 @@ bool MDNSResponder::clsHost::_sendMDNSMessage(MDNSResponder::clsHost::stcSendPar } DEBUG_EX_INFO(else { - DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage: No IPv4 address available!\n"), _DH()); + DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage: No IPv4 address available!\n"), _DH()); }); #endif #ifdef MDNS_IPV6_SUPPORT @@ -100,72 +74,86 @@ bool MDNSResponder::clsHost::_sendMDNSMessage(MDNSResponder::clsHost::stcSendPar } DEBUG_EX_INFO(else { - DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage: No IPv6 address available!\n"), _DH()); + DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage: No IPv6 address available!\n"), _DH()); }); #endif - if (stcSendParameter::enuResponseType::None != p_rSendParameter.m_Response) + if (clsBackbone::sm_pBackbone->setDelayUDPProcessing(true)) { - IPAddress ipRemote = ((stcSendParameter::enuResponseType::Response == p_rSendParameter.m_Response) - ? m_rUDPContext.getRemoteAddress() - : IPAddress()); - - if (p_rSendParameter.m_bUnicast) // Unicast response -> Send to querier + // Avoid 're-entry-like problems because delay() is called! + if (clsSendParameter::enuResponseType::None != p_rSendParameter.m_Response) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage: Will send unicast to '%s'.\n"), _DH(), ipRemote.toString().c_str());); - DEBUG_EX_ERR(if (!ipRemote.isSet()) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage: MISSING remote address for unicast response!\n"), _DH());); + IPAddress ipRemote = ((clsSendParameter::enuResponseType::Response == p_rSendParameter.m_Response) + ? m_pUDPContext->getRemoteAddress() + : IPAddress()); - bResult = ((ipRemote.isSet()) && - (_prepareMDNSMessage(p_rSendParameter)) && - (m_rUDPContext.send(ipRemote, m_rUDPContext.getRemotePort()))); - } - else // Multicast response -> Send via the same network interface, that received the query - { -#ifdef MDNS_IPV4_SUPPORT - if (((!ipRemote.isSet()) || // NO remote IP - (ipRemote.isV4())) && // OR IPv4 - (u8AvailableProtocols & static_cast<uint8_t>(enuIPProtocolType::V4))) // AND IPv4 protocol available + if (p_rSendParameter.m_bUnicast) { - - bResult = _sendMDNSMessage_Multicast(p_rSendParameter, static_cast<uint8_t>(enuIPProtocolType::V4)); + // Unicast response -> Send to querier + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage: Will send unicast to '%s'.\n"), _DH(), ipRemote.toString().c_str());); + DEBUG_EX_ERR(if (!ipRemote.isSet()) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage: MISSING remote address for unicast response!\n"), _DH());); + + bResult = ((ipRemote.isSet()) && + (_prepareMessage(p_rSendParameter)) && + (m_pUDPContext->send(ipRemote, m_pUDPContext->getRemotePort())) /*&& + (Serial.println("Did send UC"), true)*/); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage (V4): FAILED!\n"), _DH());); + + if ((clsConsts::u32SendCooldown) && + (can_yield())) + { + delay(clsConsts::u32SendCooldown); + } } + else + { + // Multicast response -> Send via the same network interface, that received the query +#ifdef MDNS_IPV4_SUPPORT + if (((!ipRemote.isSet()) || // NO remote IP + (ipRemote.isV4())) && // OR IPv4 + (u8AvailableProtocols & static_cast<uint8_t>(enuIPProtocolType::V4))) // AND IPv4 protocol available + { + bResult = _sendMessage_Multicast(p_rSendParameter, static_cast<uint8_t>(enuIPProtocolType::V4)); + } #endif #ifdef MDNS_IPV6_SUPPORT - if (((!ipRemote.isSet()) || // NO remote IP - (ipRemote.isV6())) && // OR IPv6 - (u8AvailableProtocols & static_cast<uint8_t>(enuIPProtocolType::V6))) // AND IPv6 protocol available - { - - bResult = _sendMDNSMessage_Multicast(p_rSendParameter, static_cast<uint8_t>(enuIPProtocolType::V6)); - } + if (((!ipRemote.isSet()) || // NO remote IP + (ipRemote.isV6())) && // OR IPv6 + (u8AvailableProtocols & static_cast<uint8_t>(enuIPProtocolType::V6))) // AND IPv6 protocol available + { + bResult = _sendMessage_Multicast(p_rSendParameter, static_cast<uint8_t>(enuIPProtocolType::V6)); + } #endif + } + } + else + { + // Multicast query -> Send by all available protocols + bResult = ((u8AvailableProtocols) && + (_sendMessage_Multicast(p_rSendParameter, u8AvailableProtocols))); } - } - else // Multicast query -> Send by all available protocols - { - bResult = ((u8AvailableProtocols) && - (_sendMDNSMessage_Multicast(p_rSendParameter, u8AvailableProtocols))); - } - // Finally clear service reply masks - for (stcService* pService = m_pServices; pService; pService = pService->m_pNext) - { - pService->m_u32ReplyMask = 0; + // Finally clear service reply masks + for (clsService* pService : m_Services) + { + pService->m_u32ReplyMask = 0; + } + + clsBackbone::sm_pBackbone->setDelayUDPProcessing(false); } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage: FAILED!\n"), _DH());); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage: FAILED!\n"), _DH());); return bResult; } -#include "cont.h" /* - MDNSResponder::_sendMDNSMessage_Multicast + MDNSResponder::_sendMessage_Multicast - Fills the UDP output buffer (via _prepareMDNSMessage) and sends the buffer + Fills the UDP output buffer (via _prepareMessage) and sends the buffer via the selected WiFi protocols */ -bool MDNSResponder::clsHost::_sendMDNSMessage_Multicast(MDNSResponder::clsHost::stcSendParameter& p_rSendParameter, - uint8_t p_IPProtocolTypes) +bool clsLEAMDNSHost::_sendMessage_Multicast(clsLEAMDNSHost::clsSendParameter& p_rSendParameter, + uint8_t p_IPProtocolTypes) { bool bIPv4Result = true; bool bIPv6Result = true; @@ -175,13 +163,20 @@ bool MDNSResponder::clsHost::_sendMDNSMessage_Multicast(MDNSResponder::clsHost:: { IPAddress ip4MulticastAddress(DNS_MQUERY_IPV4_GROUP_INIT); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast v4: Will send to '%s'.\n"), _DH(), ip4MulticastAddress.toString().c_str());); - DEBUG_EX_INFO(if (!_getResponderIPAddress(enuIPProtocolType::V4)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast v4: NO IPv4 address!.\n"), _DH());); - bIPv4Result = ((_prepareMDNSMessage(p_rSendParameter)) && - (m_rUDPContext.setMulticastInterface(&m_rNetIf), true) && - (m_rUDPContext.send(ip4MulticastAddress, DNS_MQUERY_PORT)) && - (m_rUDPContext.setMulticastInterface(0), true)); - DEBUG_EX_ERR(if (!bIPv4Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast (V4): FAILED!\n"), _DH());); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast IPv4: Will send to '%s'.\n"), _DH(), ip4MulticastAddress.toString().c_str());); + DEBUG_EX_INFO(if (!_getResponderIPAddress(enuIPProtocolType::V4)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast IPv4: NO IPv4 address!.\n"), _DH());); + bIPv4Result = ((_prepareMessage(p_rSendParameter)) && + (m_pUDPContext->setMulticastInterface(m_pNetIf), true) && + (m_pUDPContext->send(ip4MulticastAddress, DNS_MQUERY_PORT)) && + (m_pUDPContext->setMulticastInterface(0), true) /*&& + (Serial.println("Did send MC V4"), true)*/); + DEBUG_EX_ERR(if (!bIPv4Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (V4): FAILED!\n"), _DH());); + + if ((clsConsts::u32SendCooldown) && + (can_yield())) + { + delay(clsConsts::u32SendCooldown); + } } #endif @@ -190,27 +185,34 @@ bool MDNSResponder::clsHost::_sendMDNSMessage_Multicast(MDNSResponder::clsHost:: { IPAddress ip6MulticastAddress(DNS_MQUERY_IPV6_GROUP_INIT); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast v6: Will send to '%s'.\n"), _DH(), ip6MulticastAddress.toString().c_str());); - DEBUG_EX_INFO(if (!_getResponderIPAddress(enuIPProtocolType::V6)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast v6: NO IPv6 address!.\n"), _DH());); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast IPv6: Will send to '%s'.\n"), _DH(), ip6MulticastAddress.toString().c_str());); + DEBUG_EX_INFO(if (!_getResponderIPAddress(enuIPProtocolType::V6)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast IPv6: NO IPv6 address!.\n"), _DH());); DEBUG_EX_ERR( bool bPrepareMessage = false; bool bUDPContextSend = false; ); - bIPv6Result = ((DEBUG_EX_ERR(bPrepareMessage =)_prepareMDNSMessage(p_rSendParameter)) && - (m_rUDPContext.setMulticastInterface(&m_rNetIf), true) && - (DEBUG_EX_ERR(bUDPContextSend =)m_rUDPContext.send(ip6MulticastAddress, DNS_MQUERY_PORT)) && - (m_rUDPContext.setMulticastInterface(0), true)); - DEBUG_EX_ERR(if (!bIPv6Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast (V6): FAILED! (%s, %s, %s)\n"), _DH(), (_getResponderIPAddress(enuIPProtocolType::V6).isSet() ? "1" : "0"), (bPrepareMessage ? "1" : "0"), (bUDPContextSend ? "1" : "0"));); + bIPv6Result = ((DEBUG_EX_ERR(bPrepareMessage =)_prepareMessage(p_rSendParameter)) && + (m_pUDPContext->setMulticastInterface(m_pNetIf), true) && + (DEBUG_EX_ERR(bUDPContextSend =)m_pUDPContext->send(ip6MulticastAddress, DNS_MQUERY_PORT)) && + (m_pUDPContext->setMulticastInterface(0), true) /*&& + (Serial.println("Did send MC V6"), true)*/); + DEBUG_EX_ERR(if (!bIPv6Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (IPv6): FAILED! (%s, %s, %s)\n"), _DH(), (_getResponderIPAddress(enuIPProtocolType::V6).isSet() ? "1" : "0"), (bPrepareMessage ? "1" : "0"), (bUDPContextSend ? "1" : "0"));); + + if ((clsConsts::u32SendCooldown) && + (can_yield())) + { + delay(clsConsts::u32SendCooldown); + } } #endif - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast: %s!\n\n"), _DH(), ((bIPv4Result && bIPv6Result) ? "Succeeded" : "FAILED"));); - DEBUG_EX_ERR(if (!(bIPv4Result && bIPv6Result)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSMessage_Multicast: FAILED!\n"), _DH());); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast: %s!\n\n"), _DH(), ((bIPv4Result && bIPv6Result) ? "Succeeded" : "FAILED"));); + DEBUG_EX_ERR(if (!(bIPv4Result && bIPv6Result)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast: FAILED!\n"), _DH());); return (bIPv4Result && bIPv6Result); } /* - MDNSResponder::_prepareMDNSMessage + MDNSResponder::_prepareMessage The MDNS message is composed in a two-step process. In the first loop 'only' the header informations (mainly number of answers) are collected, @@ -218,7 +220,7 @@ bool MDNSResponder::clsHost::_sendMDNSMessage_Multicast(MDNSResponder::clsHost:: output buffer. */ -bool MDNSResponder::clsHost::_prepareMDNSMessage(MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage\n"));); bool bResult = true; @@ -227,13 +229,13 @@ bool MDNSResponder::clsHost::_prepareMDNSMessage(MDNSResponder::clsHost::stcSend p_rSendParameter.flushTempContent(); // Prepare header; count answers - stcMsgHeader msgHeader(p_rSendParameter.m_u16ID, - (static_cast<stcSendParameter::enuResponseType>(stcSendParameter::enuResponseType::None) != p_rSendParameter.m_Response), + clsMsgHeader msgHeader(p_rSendParameter.m_u16ID, + (static_cast<clsSendParameter::enuResponseType>(clsSendParameter::enuResponseType::None) != p_rSendParameter.m_Response), 0, p_rSendParameter.m_bAuthorative); // If this is a response, the answers are anwers, // else this is a query or probe and the answers go into auth section - uint16_t& ru16Answers = ((stcSendParameter::enuResponseType::None != p_rSendParameter.m_Response) + uint16_t& ru16Answers = ((clsSendParameter::enuResponseType::None != p_rSendParameter.m_Response) ? msgHeader.m_u16ANCount // Usual answers : msgHeader.m_u16NSCount); // Authorative answers @@ -269,8 +271,10 @@ bool MDNSResponder::clsHost::_prepareMDNSMessage(MDNSResponder::clsHost::stcSend : _writeMDNSMsgHeader(msgHeader, p_rSendParameter)); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSMsgHeader FAILED!\n"), _DH());); // Questions - for (stcRRQuestion* pQuestion = p_rSendParameter.m_pQuestions; ((bResult) && (pQuestion)); pQuestion = pQuestion->m_pNext) + for (clsRRQuestion::list::iterator it = p_rSendParameter.m_RRQuestions.begin(); ((bResult) && (it != p_rSendParameter.m_RRQuestions.end())); it++) { + clsRRQuestion* pQuestion = *it; + ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++msgHeader.m_u16QDCount : (bResult = _writeMDNSQuestion(*pQuestion, p_rSendParameter))); @@ -333,8 +337,10 @@ bool MDNSResponder::clsHost::_prepareMDNSMessage(MDNSResponder::clsHost::stcSend } #endif - for (stcService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) { + clsService* pService = *it; + // PTR_TYPE if ((bResult) && (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_TYPE))) @@ -382,8 +388,10 @@ bool MDNSResponder::clsHost::_prepareMDNSMessage(MDNSResponder::clsHost::stcSend #ifdef MDNS_IPV6_SUPPORT bool bNeedsAdditionalAnswerAAAA = false; #endif - for (stcService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) { + clsService* pService = *it; + if ((bResult) && (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_NAME)) && // If PTR_NAME is requested, AND (!(pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::SRV)))) // NOT SRV -> add SRV as additional answer @@ -425,9 +433,8 @@ bool MDNSResponder::clsHost::_prepareMDNSMessage(MDNSResponder::clsHost::stcSend // NSEC record for service if ((bResult) && (pService->m_u32ReplyMask) && - ((stcSendParameter::enuResponseType::None != p_rSendParameter.m_Response))) + ((clsSendParameter::enuResponseType::None != p_rSendParameter.m_Response))) { - ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16AdditionalAnswers : (bResult = _writeMDNSAnswer_NSEC(*pService, (static_cast<uint32_t>(enuContentFlag::TXT) | static_cast<uint32_t>(enuContentFlag::SRV)), p_rSendParameter))); @@ -468,10 +475,9 @@ bool MDNSResponder::clsHost::_prepareMDNSMessage(MDNSResponder::clsHost::stcSend // NSEC host (part 2) if ((bResult) && - ((stcSendParameter::enuResponseType::None != p_rSendParameter.m_Response)) && + ((clsSendParameter::enuResponseType::None != p_rSendParameter.m_Response)) && (u32NSECContent)) { - // NSEC PTR IPv4/IPv6 are separate answers; make sure, that this is counted for #ifdef MDNS_IPV4_SUPPORT uint32_t u32NSECContent_PTR_IPv4 = (u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)); @@ -518,61 +524,60 @@ bool MDNSResponder::clsHost::_prepareMDNSMessage(MDNSResponder::clsHost::stcSend } /* - MDNSResponder::_addMDNSQueryRecord + MDNSResponder::_addQueryRecord Adds a query for the given domain and query type. */ -bool MDNSResponder::clsHost::_addMDNSQueryRecord(MDNSResponder::clsHost::stcSendParameter& p_rSendParameter, - const MDNSResponder::clsHost::stcRRDomain& p_QueryDomain, - uint16_t p_u16RecordType) +bool clsLEAMDNSHost::_addQueryRecord(clsLEAMDNSHost::clsSendParameter& p_rSendParameter, + const clsLEAMDNSHost::clsRRDomain& p_QueryDomain, + uint16_t p_u16RecordType) { bool bResult = false; - stcRRQuestion* pQuestion = new stcRRQuestion; - if ((bResult = (0 != pQuestion))) + clsRRQuestion* pNewRRQuestion = new clsRRQuestion; + if ((bResult = (0 != pNewRRQuestion))) { // Link to list of questions - pQuestion->m_pNext = p_rSendParameter.m_pQuestions; - p_rSendParameter.m_pQuestions = pQuestion; + p_rSendParameter.m_RRQuestions.push_back(pNewRRQuestion); - pQuestion->m_Header.m_Domain = p_QueryDomain; + pNewRRQuestion->m_Header.m_Domain = p_QueryDomain; - pQuestion->m_Header.m_Attributes.m_u16Type = p_u16RecordType; + pNewRRQuestion->m_Header.m_Attributes.m_u16Type = p_u16RecordType; // It seems, that some mDNS implementations don't support 'unicast response' questions... - pQuestion->m_Header.m_Attributes.m_u16Class = (/*0x8000 |*/ DNS_RRCLASS_IN); // /*Unicast &*/ INternet + pNewRRQuestion->m_Header.m_Attributes.m_u16Class = (/*0x8000 |*/ DNS_RRCLASS_IN); // /*Unicast &*/ INternet } return bResult; } /* - MDNSResponder::_sendMDNSQuery + MDNSResponder::_sendQuery Creates and sends a query for the given domain and query type. */ -bool MDNSResponder::clsHost::_sendMDNSQuery(const MDNSResponder::clsHost::stcQuery& p_Query, - MDNSResponder::clsHost::stcQuery::stcAnswer* p_pKnownAnswers /*= 0*/) +bool clsLEAMDNSHost::_sendQuery(const clsLEAMDNSHost::clsQuery& p_Query, + clsLEAMDNSHost::clsQuery::clsAnswer::list* p_pKnownAnswers /*= 0*/) { bool bResult = false; - stcSendParameter sendParameter; + clsSendParameter sendParameter; switch (p_Query.m_QueryType) { - case stcQuery::enuQueryType::Host: + case clsQuery::enuQueryType::Host: #ifdef MDNS_IPV4_SUPPORT - bResult = _addMDNSQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_A); + bResult = _addQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_A); #endif #ifdef MDNS_IPV6_SUPPORT - bResult = _addMDNSQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_AAAA); + bResult = _addQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_AAAA); #endif break; - case stcQuery::enuQueryType::Service: - bResult = _addMDNSQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_PTR); + case clsQuery::enuQueryType::Service: + bResult = _addQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_PTR); break; - case stcQuery::enuQueryType::None: + case clsQuery::enuQueryType::None: default: break; } @@ -581,44 +586,48 @@ bool MDNSResponder::clsHost::_sendMDNSQuery(const MDNSResponder::clsHost::stcQue (void)p_pKnownAnswers; bResult = ((bResult) && - (_sendMDNSMessage(sendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSQuery: FAILED!\n"), _DH());); + (_sendMessage(sendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendQuery: FAILED!\n"), _DH());); return bResult; } /* - MDNSResponder::_sendMDNSQuery + MDNSResponder::_sendQuery Creates and sends a query for the given domain and record type. */ -bool MDNSResponder::clsHost::_sendMDNSQuery(const MDNSResponder::clsHost::stcRRDomain& p_QueryDomain, - uint16_t p_u16RecordType, - MDNSResponder::clsHost::stcQuery::stcAnswer* p_pKnownAnswers /*= 0*/) +bool clsLEAMDNSHost::_sendQuery(const clsLEAMDNSHost::clsRRDomain& p_QueryDomain, + uint16_t p_u16RecordType, + clsLEAMDNSHost::clsQuery::clsAnswer::list* p_pKnownAnswers /*= 0*/) { bool bResult = false; - stcSendParameter sendParameter; - bResult = ((_addMDNSQueryRecord(sendParameter, p_QueryDomain, p_u16RecordType)) && - (_sendMDNSMessage(sendParameter))); + clsSendParameter sendParameter; + bResult = ((_addQueryRecord(sendParameter, p_QueryDomain, p_u16RecordType)) && + (_sendMessage(sendParameter))); // TODO: Add known answer records (void) p_pKnownAnswers; - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMDNSQuery: FAILED!\n"), _DH());); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendQuery: FAILED!\n"), _DH());); return bResult; } /* MDNSResponder::_getResponderIPAddress */ -IPAddress MDNSResponder::clsHost::_getResponderIPAddress(enuIPProtocolType p_IPProtocolType) const +IPAddress clsLEAMDNSHost::_getResponderIPAddress(enuIPProtocolType p_IPProtocolType) const { IPAddress ipResponder; #ifdef MDNS_IPV4_SUPPORT if (enuIPProtocolType::V4 == p_IPProtocolType) { - ipResponder = netif_ip_addr4(&m_rNetIf); +#if LWIP_VERSION_MAJOR == 1 + ipResponder = ip_2_ip4(m_rNetIf.ip_addr); +#else + ipResponder = netif_ip_addr4(m_pNetIf); +#endif } #endif #ifdef MDNS_IPV6_SUPPORT @@ -629,13 +638,13 @@ IPAddress MDNSResponder::clsHost::_getResponderIPAddress(enuIPProtocolType p_IPP { for (int idx = 0; idx < LWIP_IPV6_NUM_ADDRESSES; ++idx) { - //DEBUG_EX_INFO(if ip6_addr_isvalid(netif_ip6_addr_state(&m_rNetIf, idx)) DEBUG_OUTPUT.printf_P(PSTR("%s _getResponderIPAddress: Checking IPv6 address %s (LL: %s)\n"), _DH(), IPAddress(netif_ip_addr6(&m_rNetIf, idx)).toString().c_str(), (bCheckLinkLocal ? "YES" : "NO"));); - if ((ip6_addr_isvalid(netif_ip6_addr_state(&m_rNetIf, idx))) && + //DEBUG_EX_INFO(if ip6_addr_isvalid(netif_ip6_addr_state(&m_rNetIf, idx)) DEBUG_OUTPUT.printf_P(PSTR("%s _getResponderIPAddress: Checking IPv6 address %s (LL: %s)\n"), _DH(), IPAddress(netif_ip_addr6(m_pNetIf, idx)).toString().c_str(), (bCheckLinkLocal ? "YES" : "NO"));); + if ((ip6_addr_isvalid(netif_ip6_addr_state(m_pNetIf, idx))) && (((!bCheckLinkLocal) || - (ip6_addr_islinklocal(netif_ip6_addr(&m_rNetIf, idx)))))) + (ip6_addr_islinklocal(netif_ip6_addr(m_pNetIf, idx)))))) { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _getResponderIPAddress: Selected IPv6 address %s (LL: %s)\n"), _DH(), IPAddress(netif_ip_addr6(&m_rNetIf, idx)).toString().c_str(), (bCheckLinkLocal ? "YES" : "NO"));); - ipResponder = netif_ip_addr6(&m_rNetIf, idx); + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _getResponderIPAddress: Selected IPv6 address %s (LL: %s)\n"), _DH(), IPAddress(netif_ip_addr6(m_pNetIf, idx)).toString().c_str(), (bCheckLinkLocal ? "YES" : "NO"));); + ipResponder = netif_ip_addr6(m_pNetIf, idx); break; } } @@ -661,7 +670,7 @@ IPAddress MDNSResponder::clsHost::_getResponderIPAddress(enuIPProtocolType p_IPP Reads a question (eg. MyESP._http._tcp.local ANY IN) from the UPD input buffer. */ -bool MDNSResponder::clsHost::_readRRQuestion(MDNSResponder::clsHost::stcRRQuestion& p_rRRQuestion) +bool clsLEAMDNSHost::_readRRQuestion(clsLEAMDNSHost::clsRRQuestion& p_rRRQuestion) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRQuestion\n"));); @@ -694,20 +703,19 @@ bool MDNSResponder::clsHost::_readRRQuestion(MDNSResponder::clsHost::stcRRQuesti from the input buffer). */ -bool MDNSResponder::clsHost::_readRRAnswer(MDNSResponder::clsHost::stcRRAnswer*& p_rpRRAnswer) +bool clsLEAMDNSHost::_readRRAnswer(clsLEAMDNSHost::clsRRAnswer*& p_rpRRAnswer) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer\n"));); bool bResult = false; - stcRRHeader header; + clsRRHeader header; uint32_t u32TTL; uint16_t u16RDLength; if ((_readRRHeader(header)) && (_udpRead32(u32TTL)) && (_udpRead16(u16RDLength))) { - /* DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer: Reading 0x%04X answer (class:0x%04X, TTL:%u, RDLength:%u) for "), header.m_Attributes.m_u16Type, header.m_Attributes.m_u16Class, u32TTL, u16RDLength); _printRRDomain(header.m_Domain); @@ -718,31 +726,31 @@ bool MDNSResponder::clsHost::_readRRAnswer(MDNSResponder::clsHost::stcRRAnswer*& { #ifdef MDNS_IPV4_SUPPORT case DNS_RRTYPE_A: - p_rpRRAnswer = new stcRRAnswerA(header, u32TTL); - bResult = _readRRAnswerA(*(stcRRAnswerA*&)p_rpRRAnswer, u16RDLength); + p_rpRRAnswer = new clsRRAnswerA(header, u32TTL); + bResult = _readRRAnswerA(*(clsRRAnswerA*&)p_rpRRAnswer, u16RDLength); break; #endif case DNS_RRTYPE_PTR: - p_rpRRAnswer = new stcRRAnswerPTR(header, u32TTL); - bResult = _readRRAnswerPTR(*(stcRRAnswerPTR*&)p_rpRRAnswer, u16RDLength); + p_rpRRAnswer = new clsRRAnswerPTR(header, u32TTL); + bResult = _readRRAnswerPTR(*(clsRRAnswerPTR*&)p_rpRRAnswer, u16RDLength); break; case DNS_RRTYPE_TXT: - p_rpRRAnswer = new stcRRAnswerTXT(header, u32TTL); - bResult = _readRRAnswerTXT(*(stcRRAnswerTXT*&)p_rpRRAnswer, u16RDLength); + p_rpRRAnswer = new clsRRAnswerTXT(header, u32TTL); + bResult = _readRRAnswerTXT(*(clsRRAnswerTXT*&)p_rpRRAnswer, u16RDLength); break; #ifdef MDNS_IPV6_SUPPORT case DNS_RRTYPE_AAAA: - p_rpRRAnswer = new stcRRAnswerAAAA(header, u32TTL); - bResult = _readRRAnswerAAAA(*(stcRRAnswerAAAA*&)p_rpRRAnswer, u16RDLength); + p_rpRRAnswer = new clsRRAnswerAAAA(header, u32TTL); + bResult = _readRRAnswerAAAA(*(clsRRAnswerAAAA*&)p_rpRRAnswer, u16RDLength); break; #endif case DNS_RRTYPE_SRV: - p_rpRRAnswer = new stcRRAnswerSRV(header, u32TTL); - bResult = _readRRAnswerSRV(*(stcRRAnswerSRV*&)p_rpRRAnswer, u16RDLength); + p_rpRRAnswer = new clsRRAnswerSRV(header, u32TTL); + bResult = _readRRAnswerSRV(*(clsRRAnswerSRV*&)p_rpRRAnswer, u16RDLength); break; default: - p_rpRRAnswer = new stcRRAnswerGeneric(header, u32TTL); - bResult = _readRRAnswerGeneric(*(stcRRAnswerGeneric*&)p_rpRRAnswer, u16RDLength); + p_rpRRAnswer = new clsRRAnswerGeneric(header, u32TTL); + bResult = _readRRAnswerGeneric(*(clsRRAnswerGeneric*&)p_rpRRAnswer, u16RDLength); break; } DEBUG_EX_INFO( @@ -760,20 +768,20 @@ bool MDNSResponder::clsHost::_readRRAnswer(MDNSResponder::clsHost::stcRRAnswer*& { #ifdef MDNS_IPV4_SUPPORT case DNS_RRTYPE_A: - DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((stcRRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); + DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((clsRRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); break; #endif case DNS_RRTYPE_PTR: DEBUG_OUTPUT.printf_P(PSTR("PTR ")); - _printRRDomain(((stcRRAnswerPTR*&)p_rpRRAnswer)->m_PTRDomain); + _printRRDomain(((clsRRAnswerPTR*&)p_rpRRAnswer)->m_PTRDomain); break; case DNS_RRTYPE_TXT: { - size_t stTxtLength = ((stcRRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_strLength(); + size_t stTxtLength = ((clsRRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_strLength(); char* pTxts = new char[stTxtLength]; if (pTxts) { - ((stcRRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_str(pTxts); + ((clsRRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_str(pTxts); DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts); delete[] pTxts; } @@ -781,12 +789,12 @@ bool MDNSResponder::clsHost::_readRRAnswer(MDNSResponder::clsHost::stcRRAnswer*& } #ifdef MDNS_IPV6_SUPPORT case DNS_RRTYPE_AAAA: - DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((stcRRAnswerAAAA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); + DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((clsRRAnswerAAAA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); break; #endif case DNS_RRTYPE_SRV: - DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((stcRRAnswerSRV*&)p_rpRRAnswer)->m_u16Port); - _printRRDomain(((stcRRAnswerSRV*&)p_rpRRAnswer)->m_SRVDomain); + DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((clsRRAnswerSRV*&)p_rpRRAnswer)->m_u16Port); + _printRRDomain(((clsRRAnswerSRV*&)p_rpRRAnswer)->m_SRVDomain); break; /* case DNS_RRTYPE_NSEC: DEBUG_OUTPUT.printf_P(PSTR("NSEC ")); @@ -819,13 +827,12 @@ bool MDNSResponder::clsHost::_readRRAnswer(MDNSResponder::clsHost::stcRRAnswer*& /* MDNSResponder::_readRRAnswerA */ -bool MDNSResponder::clsHost::_readRRAnswerA(MDNSResponder::clsHost::stcRRAnswerA& p_rRRAnswerA, - uint16_t p_u16RDLength) +bool clsLEAMDNSHost::_readRRAnswerA(clsLEAMDNSHost::clsRRAnswerA& p_rRRAnswerA, + uint16_t p_u16RDLength) { - uint32_t u32IPv4Address; - bool bResult = ((MDNS_IPV4_SIZE == p_u16RDLength) && - (_udpReadBuffer((unsigned char*)&u32IPv4Address, MDNS_IPV4_SIZE)) && + bool bResult = ((clsConsts::u16IPv4Size == p_u16RDLength) && + (_udpReadBuffer((unsigned char*)&u32IPv4Address, clsConsts::u16IPv4Size)) && ((p_rRRAnswerA.m_IPAddress = IPAddress(u32IPv4Address)))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerA: FAILED!\n"), _DH());); return bResult; @@ -835,8 +842,8 @@ bool MDNSResponder::clsHost::_readRRAnswerA(MDNSResponder::clsHost::stcRRAnswerA /* MDNSResponder::_readRRAnswerPTR */ -bool MDNSResponder::clsHost::_readRRAnswerPTR(MDNSResponder::clsHost::stcRRAnswerPTR& p_rRRAnswerPTR, - uint16_t p_u16RDLength) +bool clsLEAMDNSHost::_readRRAnswerPTR(clsLEAMDNSHost::clsRRAnswerPTR& p_rRRAnswerPTR, + uint16_t p_u16RDLength) { bool bResult = ((p_u16RDLength) && (_readRRDomain(p_rRRAnswerPTR.m_PTRDomain))); @@ -849,8 +856,8 @@ bool MDNSResponder::clsHost::_readRRAnswerPTR(MDNSResponder::clsHost::stcRRAnswe Read TXT items from a buffer like 4c#=15ff=20 */ -bool MDNSResponder::clsHost::_readRRAnswerTXT(MDNSResponder::clsHost::stcRRAnswerTXT& p_rRRAnswerTXT, - uint16_t p_u16RDLength) +bool clsLEAMDNSHost::_readRRAnswerTXT(clsLEAMDNSHost::clsRRAnswerTXT& p_rRRAnswerTXT, + uint16_t p_u16RDLength) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: RDLength:%u\n"), _DH(), p_u16RDLength);); bool bResult = true; @@ -873,7 +880,7 @@ bool MDNSResponder::clsHost::_readRRAnswerTXT(MDNSResponder::clsHost::stcRRAnswe { bResult = false; - stcServiceTxt* pTxt = 0; + clsServiceTxt* pTxt = 0; unsigned char ucLength = *pucCursor++; // Length of the next txt item if (ucLength) { @@ -890,7 +897,7 @@ bool MDNSResponder::clsHost::_readRRAnswerTXT(MDNSResponder::clsHost::stcRRAnswe ((ucKeyLength = (pucEqualSign - pucCursor)))) { unsigned char ucValueLength = (ucLength - (pucEqualSign - pucCursor + 1)); - bResult = (((pTxt = new stcServiceTxt)) && + bResult = (((pTxt = new clsServiceTxt)) && (pTxt->setKey((const char*)pucCursor, ucKeyLength)) && (pTxt->setValue((const char*)(pucEqualSign + 1), ucValueLength))); } @@ -902,25 +909,26 @@ bool MDNSResponder::clsHost::_readRRAnswerTXT(MDNSResponder::clsHost::stcRRAnswe } else // no/zero length TXT { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: TXT answer contains no items.\n"), _DH());); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: INFO! TXT answer contains no items.\n"), _DH());); bResult = true; } if ((bResult) && - (pTxt)) // Everythings fine so far + (pTxt)) { + // Everythings fine so far // Link TXT item to answer TXTs - pTxt->m_pNext = p_rRRAnswerTXT.m_Txts.m_pTxts; - p_rRRAnswerTXT.m_Txts.m_pTxts = pTxt; + p_rRRAnswerTXT.m_Txts.add(pTxt); } - else // At least no TXT (migth be OK, if length was 0) OR an error + else { + // At least no TXT (migth be OK, if length was 0) OR an error if (!bResult) { DEBUG_EX_ERR( DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: FAILED to read TXT item!\n"), _DH()); DEBUG_OUTPUT.printf_P(PSTR("RData dump:\n")); - _udpDump((m_rUDPContext.tell() - p_u16RDLength), p_u16RDLength); + _udpDump((m_pUDPContext->tell() - p_u16RDLength), p_u16RDLength); DEBUG_OUTPUT.printf_P(PSTR("\n")); ); } @@ -937,7 +945,7 @@ bool MDNSResponder::clsHost::_readRRAnswerTXT(MDNSResponder::clsHost::stcRRAnswe if (!bResult) // Some failure { DEBUG_OUTPUT.printf_P(PSTR("RData dump:\n")); - _udpDump((m_rUDPContext.tell() - p_u16RDLength), p_u16RDLength); + _udpDump((m_pUDPContext->tell() - p_u16RDLength), p_u16RDLength); DEBUG_OUTPUT.printf_P(PSTR("\n")); } ); @@ -956,23 +964,26 @@ bool MDNSResponder::clsHost::_readRRAnswerTXT(MDNSResponder::clsHost::stcRRAnswe } else { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: WARNING! No content!\n"), _DH());); + DEBUG_EX_ERR( + DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: WARNING! No content in TXT answer from "), _DH()); + _printRRDomain(p_rRRAnswerTXT.m_Header.m_Domain); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + ); } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: FAILED!\n"), _DH());); return bResult; } #ifdef MDNS_IPV6_SUPPORT -bool MDNSResponder::clsHost::_readRRAnswerAAAA(MDNSResponder::clsHost::stcRRAnswerAAAA& p_rRRAnswerAAAA, - uint16_t p_u16RDLength) +bool clsLEAMDNSHost::_readRRAnswerAAAA(clsLEAMDNSHost::clsRRAnswerAAAA& p_rRRAnswerAAAA, + uint16_t p_u16RDLength) { bool bResult = false; uint32_t au32IPv6Address[4]; // 16 bytes - if ((bResult = ((MDNS_IPV6_SIZE == p_u16RDLength) && - (_udpReadBuffer((uint8_t*)&au32IPv6Address[0], MDNS_IPV6_SIZE))))) + if ((bResult = ((clsConsts::u16IPv6Size == p_u16RDLength) && + (_udpReadBuffer((uint8_t*)&au32IPv6Address[0], clsConsts::u16IPv6Size))))) { - // ?? IPADDR6_INIT_HOST ?? ip_addr_t addr = IPADDR6_INIT(au32IPv6Address[0], au32IPv6Address[1], au32IPv6Address[2], au32IPv6Address[3]); p_rRRAnswerAAAA.m_IPAddress = IPAddress(addr); @@ -985,8 +996,8 @@ bool MDNSResponder::clsHost::_readRRAnswerAAAA(MDNSResponder::clsHost::stcRRAnsw /* MDNSResponder::_readRRAnswerSRV */ -bool MDNSResponder::clsHost::_readRRAnswerSRV(MDNSResponder::clsHost::stcRRAnswerSRV& p_rRRAnswerSRV, - uint16_t p_u16RDLength) +bool clsLEAMDNSHost::_readRRAnswerSRV(clsLEAMDNSHost::clsRRAnswerSRV& p_rRRAnswerSRV, + uint16_t p_u16RDLength) { bool bResult = (((3 * sizeof(uint16_t)) < p_u16RDLength) && (_udpRead16(p_rRRAnswerSRV.m_u16Priority)) && @@ -1000,8 +1011,8 @@ bool MDNSResponder::clsHost::_readRRAnswerSRV(MDNSResponder::clsHost::stcRRAnswe /* MDNSResponder::_readRRAnswerGeneric */ -bool MDNSResponder::clsHost::_readRRAnswerGeneric(MDNSResponder::clsHost::stcRRAnswerGeneric& p_rRRAnswerGeneric, - uint16_t p_u16RDLength) +bool clsLEAMDNSHost::_readRRAnswerGeneric(clsLEAMDNSHost::clsRRAnswerGeneric& p_rRRAnswerGeneric, + uint16_t p_u16RDLength) { bool bResult = (0 == p_u16RDLength); @@ -1009,7 +1020,6 @@ bool MDNSResponder::clsHost::_readRRAnswerGeneric(MDNSResponder::clsHost::stcRRA if (((p_rRRAnswerGeneric.m_u16RDLength = p_u16RDLength)) && ((p_rRRAnswerGeneric.m_pu8RDData = new unsigned char[p_rRRAnswerGeneric.m_u16RDLength]))) { - bResult = _udpReadBuffer(p_rRRAnswerGeneric.m_pu8RDData, p_rRRAnswerGeneric.m_u16RDLength); } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerGeneric: FAILED!\n"), _DH());); @@ -1019,7 +1029,7 @@ bool MDNSResponder::clsHost::_readRRAnswerGeneric(MDNSResponder::clsHost::stcRRA /* MDNSResponder::_readRRHeader */ -bool MDNSResponder::clsHost::_readRRHeader(MDNSResponder::clsHost::stcRRHeader& p_rRRHeader) +bool clsLEAMDNSHost::_readRRHeader(clsLEAMDNSHost::clsRRHeader& p_rRRHeader) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRHeader\n"));); @@ -1035,7 +1045,7 @@ bool MDNSResponder::clsHost::_readRRHeader(MDNSResponder::clsHost::stcRRHeader& Reads a (maybe multilevel compressed) domain from the UDP input buffer. */ -bool MDNSResponder::clsHost::_readRRDomain(MDNSResponder::clsHost::stcRRDomain& p_rRRDomain) +bool clsLEAMDNSHost::_readRRDomain(clsLEAMDNSHost::clsRRDomain& p_rRRDomain) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain\n"));); @@ -1053,40 +1063,40 @@ bool MDNSResponder::clsHost::_readRRDomain(MDNSResponder::clsHost::stcRRDomain& the maximum recursion depth is set by MDNS_DOMAIN_MAX_REDIRCTION. */ -bool MDNSResponder::clsHost::_readRRDomain_Loop(MDNSResponder::clsHost::stcRRDomain& p_rRRDomain, - uint8_t p_u8Depth) +bool clsLEAMDNSHost::_readRRDomain_Loop(clsLEAMDNSHost::clsRRDomain& p_rRRDomain, + uint8_t p_u8Depth) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u)\n"), _DH(), p_u8Depth);); bool bResult = false; - if (MDNS_DOMAIN_MAX_REDIRCTION >= p_u8Depth) + if (clsConsts::u8DomainMaxRedirections >= p_u8Depth) { bResult = true; uint8_t u8Len = 0; do { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u): Offset:%u p0:%02x\n"), _DH(), p_u8Depth, m_rUDPContext.tell(), m_rUDPContext.peek());); + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u): Offset:%u p0:%02x\n"), _DH(), p_u8Depth, m_pUDPContext->tell(), m_pUDPContext->peek());); _udpRead8(u8Len); - if (u8Len & MDNS_DOMAIN_COMPRESS_MARK) + if (u8Len & clsConsts::u8DomainCompressMark) { // Compressed label(s) - uint16_t u16Offset = ((u8Len & ~MDNS_DOMAIN_COMPRESS_MARK) << 8); // Implicit BE to LE conversion! + uint16_t u16Offset = ((u8Len & ~clsConsts::u8DomainCompressMark) << 8); // Implicit BE to LE conversion! _udpRead8(u8Len); u16Offset |= u8Len; - if (m_rUDPContext.isValidOffset(u16Offset)) + if (m_pUDPContext->isValidOffset(u16Offset)) { - size_t stCurrentPosition = m_rUDPContext.tell(); // Prepare return from recursion + size_t stCurrentPosition = m_pUDPContext->tell(); // Prepare return from recursion //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u): Redirecting from %u to %u!\n"), _DH(), p_u8Depth, stCurrentPosition, u16Offset);); - m_rUDPContext.seek(u16Offset); + m_pUDPContext->seek(u16Offset); if (_readRRDomain_Loop(p_rRRDomain, p_u8Depth + 1)) // Do recursion { //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(%u): Succeeded to read redirected label! Returning to %u\n"), _DH(), p_u8Depth, stCurrentPosition);); - m_rUDPContext.seek(stCurrentPosition); // Restore after recursion + m_pUDPContext->seek(stCurrentPosition); // Restore after recursion } else { @@ -1104,7 +1114,7 @@ bool MDNSResponder::clsHost::_readRRDomain_Loop(MDNSResponder::clsHost::stcRRDom else { // Normal (uncompressed) label (maybe '\0' only) - if (MDNS_DOMAIN_MAXLENGTH > (p_rRRDomain.m_u16NameLength + u8Len)) + if (clsConsts::stDomainMaxLength > (p_rRRDomain.m_u16NameLength + u8Len)) { // Add length byte p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength] = u8Len; @@ -1121,7 +1131,7 @@ bool MDNSResponder::clsHost::_readRRDomain_Loop(MDNSResponder::clsHost::stcRRDom p_rRRDomain.m_u16NameLength += u8Len; } } - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(2) offset:%u p0:%x\n"), _DH(), m_rUDPContext.tell(), m_rUDPContext.peek());); + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRDomain_Loop(2) offset:%u p0:%x\n"), _DH(), m_pUDPContext->tell(), m_pUDPContext->peek());); } else { @@ -1142,8 +1152,9 @@ bool MDNSResponder::clsHost::_readRRDomain_Loop(MDNSResponder::clsHost::stcRRDom /* MDNSResponder::_readRRAttributes + */ -bool MDNSResponder::clsHost::_readRRAttributes(MDNSResponder::clsHost::stcRRAttributes& p_rRRAttributes) +bool clsLEAMDNSHost::_readRRAttributes(clsLEAMDNSHost::clsRRAttributes& p_rRRAttributes) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAttributes\n"));); @@ -1155,7 +1166,9 @@ bool MDNSResponder::clsHost::_readRRAttributes(MDNSResponder::clsHost::stcRRAttr /* + DOMAIN NAMES + */ /* @@ -1164,15 +1177,15 @@ bool MDNSResponder::clsHost::_readRRAttributes(MDNSResponder::clsHost::stcRRAttr Builds a MDNS host domain (eg. esp8266.local) for the given hostname. */ -bool MDNSResponder::clsHost::_buildDomainForHost(const char* p_pcHostName, - MDNSResponder::clsHost::stcRRDomain& p_rHostDomain) const +bool clsLEAMDNSHost::_buildDomainForHost(const char* p_pcHostName, + clsLEAMDNSHost::clsRRDomain& p_rHostDomain) const { p_rHostDomain.clear(); bool bResult = ((p_pcHostName) && (*p_pcHostName) && (p_rHostDomain.addLabel(p_pcHostName)) && - (p_rHostDomain.addLabel(scpcLocal)) && + (p_rHostDomain.addLabel(clsConsts::pcLocal)) && (p_rHostDomain.addLabel(0))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _buildDomainForHost: FAILED!\n"), _DH());); return bResult; @@ -1185,13 +1198,13 @@ bool MDNSResponder::clsHost::_buildDomainForHost(const char* p_pcHostName, Used while detecting generic service enum question (DNS-SD) and answering these questions. */ -bool MDNSResponder::clsHost::_buildDomainForDNSSD(MDNSResponder::clsHost::stcRRDomain& p_rDNSSDDomain) const +bool clsLEAMDNSHost::_buildDomainForDNSSD(clsLEAMDNSHost::clsRRDomain& p_rDNSSDDomain) const { p_rDNSSDDomain.clear(); - bool bResult = ((p_rDNSSDDomain.addLabel(scpcServices, true)) && - (p_rDNSSDDomain.addLabel(scpcDNSSD, true)) && - (p_rDNSSDDomain.addLabel(scpcUDP, true)) && - (p_rDNSSDDomain.addLabel(scpcLocal)) && + bool bResult = ((p_rDNSSDDomain.addLabel(clsConsts::pcServices, true)) && + (p_rDNSSDDomain.addLabel(clsConsts::pcDNSSD, true)) && + (p_rDNSSDDomain.addLabel(clsConsts::pcUDP, true)) && + (p_rDNSSDDomain.addLabel(clsConsts::pcLocal)) && (p_rDNSSDDomain.addLabel(0))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _buildDomainForDNSSD: FAILED!\n"), _DH());); return bResult; @@ -1204,16 +1217,16 @@ bool MDNSResponder::clsHost::_buildDomainForDNSSD(MDNSResponder::clsHost::stcRRD MyESP._http._tcp.local (if p_bIncludeName is set)). */ -bool MDNSResponder::clsHost::_buildDomainForService(const MDNSResponder::clsHost::stcService& p_Service, - bool p_bIncludeName, - MDNSResponder::clsHost::stcRRDomain& p_rServiceDomain) const +bool clsLEAMDNSHost::_buildDomainForService(const clsLEAMDNSHost::clsService& p_Service, + bool p_bIncludeName, + clsLEAMDNSHost::clsRRDomain& p_rServiceDomain) const { p_rServiceDomain.clear(); bool bResult = (((!p_bIncludeName) || - (p_rServiceDomain.addLabel(p_Service.m_pcName))) && - (p_rServiceDomain.addLabel(p_Service.m_pcServiceType, ('_' != *p_Service.m_pcServiceType))) && - (p_rServiceDomain.addLabel(p_Service.m_pcProtocol, ('_' != *p_Service.m_pcProtocol))) && - (p_rServiceDomain.addLabel(scpcLocal)) && + (p_rServiceDomain.addLabel(p_Service.instanceName()))) && + (p_rServiceDomain.addLabel(p_Service.type(), ('_' != *p_Service.type()))) && + (p_rServiceDomain.addLabel(p_Service.protocol(), ('_' != *p_Service.protocol()))) && + (p_rServiceDomain.addLabel(clsConsts::pcLocal)) && (p_rServiceDomain.addLabel(0))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _buildDomainForService: FAILED!\n"), _DH());); return bResult; @@ -1226,16 +1239,16 @@ bool MDNSResponder::clsHost::_buildDomainForService(const MDNSResponder::clsHost The usual prepended '_' are added, if missing in the input strings. */ -bool MDNSResponder::clsHost::_buildDomainForService(const char* p_pcServiceType, - const char* p_pcProtocol, - MDNSResponder::clsHost::stcRRDomain& p_rServiceDomain) const +bool clsLEAMDNSHost::_buildDomainForService(const char* p_pcServiceType, + const char* p_pcProtocol, + clsLEAMDNSHost::clsRRDomain& p_rServiceDomain) const { p_rServiceDomain.clear(); bool bResult = ((p_pcServiceType) && (p_pcProtocol) && (p_rServiceDomain.addLabel(p_pcServiceType, ('_' != *p_pcServiceType))) && (p_rServiceDomain.addLabel(p_pcProtocol, ('_' != *p_pcProtocol))) && - (p_rServiceDomain.addLabel(scpcLocal)) && + (p_rServiceDomain.addLabel(clsConsts::pcLocal)) && (p_rServiceDomain.addLabel(0))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _buildDomainForService: FAILED for (%s.%s)!\n"), _DH(), (p_pcServiceType ? : "-"), (p_pcProtocol ? : "-"));); return bResult; @@ -1248,9 +1261,10 @@ bool MDNSResponder::clsHost::_buildDomainForService(const char* p_pcServiceType, The IPv4 address is stringized by printing the four address bytes into a char buffer in reverse order and adding 'in-addr.arpa' (eg. 012.789.456.123.in-addr.arpa). Used while detecting reverse IPv4 questions and answering these + */ -bool MDNSResponder::clsHost::_buildDomainForReverseIPv4(IPAddress p_IPv4Address, - MDNSResponder::clsHost::stcRRDomain& p_rReverseIPv4Domain) const +bool clsLEAMDNSHost::_buildDomainForReverseIPv4(IPAddress p_IPv4Address, + clsLEAMDNSHost::clsRRDomain& p_rReverseIPv4Domain) const { bool bResult = ((p_IPv4Address.isSet()) && (p_IPv4Address.isV4())); @@ -1258,14 +1272,14 @@ bool MDNSResponder::clsHost::_buildDomainForReverseIPv4(IPAddress p_IPv4Address, p_rReverseIPv4Domain.clear(); char acBuffer[32]; - for (int i = MDNS_IPV4_SIZE; ((bResult) && (i >= 1)); --i) + for (int i = clsConsts::u16IPv4Size; ((bResult) && (i >= 1)); --i) { itoa(p_IPv4Address[i - 1], acBuffer, 10); bResult = p_rReverseIPv4Domain.addLabel(acBuffer); } bResult = ((bResult) && - (p_rReverseIPv4Domain.addLabel(scpcReverseIPv4Domain)) && - (p_rReverseIPv4Domain.addLabel(scpcReverseTopDomain)) && + (p_rReverseIPv4Domain.addLabel(clsConsts::pcReverseIPv4Domain)) && + (p_rReverseIPv4Domain.addLabel(clsConsts::pcReverseTopDomain)) && (p_rReverseIPv4Domain.addLabel(0))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _buildDomainForReverseIPv4: FAILED!\n"), _DH());); return bResult; @@ -1279,9 +1293,10 @@ bool MDNSResponder::clsHost::_buildDomainForReverseIPv4(IPAddress p_IPv4Address, The IPv6 address is stringized by printing the 16 address bytes (32 nibbles) into a char buffer in reverse order and adding 'ip6.arpa' (eg. 3.B.6.E.A.1.B.B.A.B.F.7.F.8.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.ip6.arpa). Used while detecting reverse IPv6 questions and answering these + */ -bool MDNSResponder::clsHost::_buildDomainForReverseIPv6(IPAddress p_IPv6Address, - MDNSResponder::clsHost::stcRRDomain& p_rReverseIPv6Domain) const +bool clsLEAMDNSHost::_buildDomainForReverseIPv6(IPAddress p_IPv6Address, + clsLEAMDNSHost::clsRRDomain& p_rReverseIPv6Domain) const { bool bResult = ((p_IPv6Address.isSet()) && (p_IPv6Address.isV6())); @@ -1289,7 +1304,7 @@ bool MDNSResponder::clsHost::_buildDomainForReverseIPv6(IPAddress p_IPv6Address, p_rReverseIPv6Domain.clear(); const uint16_t* pRaw = p_IPv6Address.raw6(); - for (int8_t i8 = (MDNS_IPV6_SIZE / 2); ((bResult) && (i8 > 0)); --i8) // 8..1 + for (int8_t i8 = (clsConsts::u16IPv6Size / 2); ((bResult) && (i8 > 0)); --i8) // 8..1 { uint16_t u16Part = ntohs(pRaw[i8 - 1] & 0xFFFF); char acBuffer[2]; @@ -1301,8 +1316,8 @@ bool MDNSResponder::clsHost::_buildDomainForReverseIPv6(IPAddress p_IPv6Address, } } bResult = ((bResult) && - (p_rReverseIPv6Domain.addLabel(scpcReverseIPv6Domain)) && // .ip6.arpa - (p_rReverseIPv6Domain.addLabel(scpcReverseTopDomain)) && // .local + (p_rReverseIPv6Domain.addLabel(clsConsts::pcReverseIPv6Domain)) && // .ip6.arpa + (p_rReverseIPv6Domain.addLabel(clsConsts::pcReverseTopDomain)) && // .local (p_rReverseIPv6Domain.addLabel(0))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _buildDomainForReverseIPv6: FAILED!\n"), _DH());); return bResult; @@ -1311,35 +1326,40 @@ bool MDNSResponder::clsHost::_buildDomainForReverseIPv6(IPAddress p_IPv6Address, /* + UDP + */ /* MDNSResponder::_udpReadBuffer + */ -bool MDNSResponder::clsHost::_udpReadBuffer(unsigned char* p_pBuffer, - size_t p_stLength) +bool clsLEAMDNSHost::_udpReadBuffer(unsigned char* p_pBuffer, + size_t p_stLength) { - bool bResult = ((true/*m_rUDPContext.getSize() > p_stLength*/) && + bool bResult = ((m_pUDPContext->getSize() >= p_stLength) && (p_pBuffer) && (p_stLength) && - ((p_stLength == m_rUDPContext.read((char*)p_pBuffer, p_stLength)))); + ((p_stLength == m_pUDPContext->read((char*)p_pBuffer, p_stLength)))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _udpReadBuffer: FAILED!\n"), _DH());); return bResult; } /* MDNSResponder::_udpRead8 + */ -bool MDNSResponder::clsHost::_udpRead8(uint8_t& p_ru8Value) +bool clsLEAMDNSHost::_udpRead8(uint8_t& p_ru8Value) { return _udpReadBuffer((unsigned char*)&p_ru8Value, sizeof(p_ru8Value)); } /* MDNSResponder::_udpRead16 + */ -bool MDNSResponder::clsHost::_udpRead16(uint16_t& p_ru16Value) +bool clsLEAMDNSHost::_udpRead16(uint16_t& p_ru16Value) { bool bResult = false; @@ -1353,8 +1373,9 @@ bool MDNSResponder::clsHost::_udpRead16(uint16_t& p_ru16Value) /* MDNSResponder::_udpRead32 + */ -bool MDNSResponder::clsHost::_udpRead32(uint32_t& p_ru32Value) +bool clsLEAMDNSHost::_udpRead32(uint32_t& p_ru32Value) { bool bResult = false; @@ -1368,29 +1389,32 @@ bool MDNSResponder::clsHost::_udpRead32(uint32_t& p_ru32Value) /* MDNSResponder::_udpAppendBuffer + */ -bool MDNSResponder::clsHost::_udpAppendBuffer(const unsigned char* p_pcBuffer, - size_t p_stLength) +bool clsLEAMDNSHost::_udpAppendBuffer(const unsigned char* p_pcBuffer, + size_t p_stLength) { bool bResult = ((p_pcBuffer) && (p_stLength) && - (p_stLength == m_rUDPContext.append((const char*)p_pcBuffer, p_stLength))); + (p_stLength == m_pUDPContext->append((const char*)p_pcBuffer, p_stLength))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _udpAppendBuffer: FAILED!\n"), _DH());); return bResult; } /* MDNSResponder::_udpAppend8 + */ -bool MDNSResponder::clsHost::_udpAppend8(uint8_t p_u8Value) +bool clsLEAMDNSHost::_udpAppend8(uint8_t p_u8Value) { return (_udpAppendBuffer((unsigned char*)&p_u8Value, sizeof(p_u8Value))); } /* MDNSResponder::_udpAppend16 + */ -bool MDNSResponder::clsHost::_udpAppend16(uint16_t p_u16Value) +bool clsLEAMDNSHost::_udpAppend16(uint16_t p_u16Value) { p_u16Value = lwip_htons(p_u16Value); return (_udpAppendBuffer((unsigned char*)&p_u16Value, sizeof(p_u16Value))); @@ -1398,8 +1422,9 @@ bool MDNSResponder::clsHost::_udpAppend16(uint16_t p_u16Value) /* MDNSResponder::_udpAppend32 + */ -bool MDNSResponder::clsHost::_udpAppend32(uint32_t p_u32Value) +bool clsLEAMDNSHost::_udpAppend32(uint32_t p_u32Value) { p_u32Value = lwip_htonl(p_u32Value); return (_udpAppendBuffer((unsigned char*)&p_u32Value, sizeof(p_u32Value))); @@ -1408,12 +1433,13 @@ bool MDNSResponder::clsHost::_udpAppend32(uint32_t p_u32Value) #ifdef DEBUG_ESP_MDNS_RESPONDER /* MDNSResponder::_udpDump + */ -bool MDNSResponder::clsHost::_udpDump(bool p_bMovePointer /*= false*/) +bool clsLEAMDNSHost::_udpDump(bool p_bMovePointer /*= false*/) { const uint8_t cu8BytesPerLine = 16; - uint32_t u32StartPosition = m_rUDPContext.tell(); + uint32_t u32StartPosition = m_pUDPContext->tell(); DEBUG_OUTPUT.println("UDP Context Dump:"); uint32_t u32Counter = 0; uint8_t u8Byte = 0; @@ -1426,29 +1452,30 @@ bool MDNSResponder::clsHost::_udpDump(bool p_bMovePointer /*= false*/) if (!p_bMovePointer) // Restore { - m_rUDPContext.seek(u32StartPosition); + m_pUDPContext->seek(u32StartPosition); } return true; } /* MDNSResponder::_udpDump + */ -bool MDNSResponder::clsHost::_udpDump(unsigned p_uOffset, - unsigned p_uLength) +bool clsLEAMDNSHost::_udpDump(unsigned p_uOffset, + unsigned p_uLength) { - if (m_rUDPContext.isValidOffset(p_uOffset)) + if (m_pUDPContext->isValidOffset(p_uOffset)) { - unsigned uCurrentPosition = m_rUDPContext.tell(); // Remember start position + unsigned uCurrentPosition = m_pUDPContext->tell(); // Remember start position - m_rUDPContext.seek(p_uOffset); + m_pUDPContext->seek(p_uOffset); uint8_t u8Byte; for (unsigned u = 0; ((u < p_uLength) && (_udpRead8(u8Byte))); ++u) { DEBUG_OUTPUT.printf_P(PSTR("%02x "), u8Byte); } // Return to start position - m_rUDPContext.seek(uCurrentPosition); + m_pUDPContext->seek(uCurrentPosition); } return true; } @@ -1471,8 +1498,9 @@ bool MDNSResponder::clsHost::_udpDump(unsigned p_uOffset, All 16-bit and 32-bit elements need to be translated form network coding to host coding (done in _udpRead16 and _udpRead32) In addition, bitfield memory order is undefined in C standard (GCC doesn't order them in the coded direction...), so they need some mapping here + */ -bool MDNSResponder::clsHost::_readMDNSMsgHeader(MDNSResponder::clsHost::stcMsgHeader& p_rMsgHeader) +bool clsLEAMDNSHost::_readMDNSMsgHeader(clsLEAMDNSHost::clsMsgHeader& p_rMsgHeader) { bool bResult = false; @@ -1514,9 +1542,10 @@ bool MDNSResponder::clsHost::_readMDNSMsgHeader(MDNSResponder::clsHost::stcMsgHe /* MDNSResponder::_write8 + */ -bool MDNSResponder::clsHost::_write8(uint8_t p_u8Value, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_write8(uint8_t p_u8Value, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { return ((_udpAppend8(p_u8Value)) && (p_rSendParameter.shiftOffset(sizeof(p_u8Value)))); @@ -1524,9 +1553,10 @@ bool MDNSResponder::clsHost::_write8(uint8_t p_u8Value, /* MDNSResponder::_write16 + */ -bool MDNSResponder::clsHost::_write16(uint16_t p_u16Value, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_write16(uint16_t p_u16Value, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { return ((_udpAppend16(p_u16Value)) && (p_rSendParameter.shiftOffset(sizeof(p_u16Value)))); @@ -1534,9 +1564,10 @@ bool MDNSResponder::clsHost::_write16(uint16_t p_u16Value, /* MDNSResponder::_write32 + */ -bool MDNSResponder::clsHost::_write32(uint32_t p_u32Value, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_write32(uint32_t p_u32Value, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { return ((_udpAppend32(p_u32Value)) && (p_rSendParameter.shiftOffset(sizeof(p_u32Value)))); @@ -1550,9 +1581,10 @@ bool MDNSResponder::clsHost::_write32(uint32_t p_u32Value, All 16-bit and 32-bit elements need to be translated form host coding to network coding (done in _udpAppend16 and _udpAppend32) In addition, bitfield memory order is undefined in C standard (GCC doesn't order them in the coded direction...), so they need some mapping here + */ -bool MDNSResponder::clsHost::_writeMDNSMsgHeader(const MDNSResponder::clsHost::stcMsgHeader& p_MsgHeader, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSMsgHeader(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { /* DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSMsgHeader: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), _DH(), @@ -1580,9 +1612,10 @@ bool MDNSResponder::clsHost::_writeMDNSMsgHeader(const MDNSResponder::clsHost::s /* MDNSResponder::_writeRRAttributes + */ -bool MDNSResponder::clsHost::_writeMDNSRRAttributes(const MDNSResponder::clsHost::stcRRAttributes& p_Attributes, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSRRAttributes(const clsLEAMDNSHost::clsRRAttributes& p_Attributes, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { bool bResult = ((_write16(p_Attributes.m_u16Type, p_rSendParameter)) && (_write16(p_Attributes.m_u16Class, p_rSendParameter))); @@ -1593,9 +1626,10 @@ bool MDNSResponder::clsHost::_writeMDNSRRAttributes(const MDNSResponder::clsHost /* MDNSResponder::_writeMDNSRRDomain + */ -bool MDNSResponder::clsHost::_writeMDNSRRDomain(const MDNSResponder::clsHost::stcRRDomain& p_Domain, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSRRDomain(const clsLEAMDNSHost::clsRRDomain& p_Domain, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { bool bResult = ((_udpAppendBuffer((const unsigned char*)p_Domain.m_acName, p_Domain.m_u16NameLength)) && (p_rSendParameter.shiftOffset(p_Domain.m_u16NameLength))); @@ -1619,26 +1653,26 @@ bool MDNSResponder::clsHost::_writeMDNSRRDomain(const MDNSResponder::clsHost::st and written to the output buffer. */ -bool MDNSResponder::clsHost::_writeMDNSHostDomain(const char* p_pcHostName, - bool p_bPrependRDLength, - uint16_t p_u16AdditionalLength, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSHostDomain(const char* p_pcHostName, + bool p_bPrependRDLength, + uint16_t p_u16AdditionalLength, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { // The 'skip-compression' version is handled in '_writeMDNSAnswer_SRV' uint16_t u16CachedDomainOffset = p_rSendParameter.findCachedDomainOffset((const void*)p_pcHostName, false); - stcRRDomain hostDomain; + clsRRDomain hostDomain; bool bResult = (u16CachedDomainOffset // Found cached domain -> mark as compressed domain - ? ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset + ? ((clsConsts::u8DomainCompressMark > ((u16CachedDomainOffset >> 8) & ~clsConsts::u8DomainCompressMark)) && // Valid offset ((!p_bPrependRDLength) || - (_write16((2 + p_u16AdditionalLength), p_rSendParameter))) && // Length of 'Cxxx' - (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) + (_write16((2 + p_u16AdditionalLength), p_rSendParameter))) && // Length of 'Cxxx' + (_write8(((u16CachedDomainOffset >> 8) | clsConsts::u8DomainCompressMark), p_rSendParameter)) && // Compression mark (and offset) (_write8((uint8_t)(u16CachedDomainOffset & 0xFF), p_rSendParameter))) // No cached domain -> add this domain to cache and write full domain name - : ((_buildDomainForHost(p_pcHostName, hostDomain)) && // eg. esp8266.local + : ((_buildDomainForHost(p_pcHostName, hostDomain)) && // eg. esp8266.local ((!p_bPrependRDLength) || - (_write16((hostDomain.m_u16NameLength + p_u16AdditionalLength), p_rSendParameter))) && // RDLength (if needed) + (_write16((hostDomain.m_u16NameLength + p_u16AdditionalLength), p_rSendParameter))) && // RDLength (if needed) (p_rSendParameter.addDomainCacheItem((const void*)p_pcHostName, false, p_rSendParameter.m_u16Offset)) && (_writeMDNSRRDomain(hostDomain, p_rSendParameter)))); @@ -1659,27 +1693,27 @@ bool MDNSResponder::clsHost::_writeMDNSHostDomain(const char* p_pcHostName, the instance name (p_bIncludeName is set) and thoose who don't. */ -bool MDNSResponder::clsHost::_writeMDNSServiceDomain(const MDNSResponder::clsHost::stcService& p_Service, - bool p_bIncludeName, - bool p_bPrependRDLength, - uint16_t p_u16AdditionalLength, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSServiceDomain(const clsLEAMDNSHost::clsService& p_Service, + bool p_bIncludeName, + bool p_bPrependRDLength, + uint16_t p_u16AdditionalLength, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { // The 'skip-compression' version is handled in '_writeMDNSAnswer_SRV' uint16_t u16CachedDomainOffset = p_rSendParameter.findCachedDomainOffset((const void*)&p_Service, p_bIncludeName); - stcRRDomain serviceDomain; + clsRRDomain serviceDomain; bool bResult = (u16CachedDomainOffset // Found cached domain -> mark as compressed domain - ? ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset + ? ((clsConsts::u8DomainCompressMark > ((u16CachedDomainOffset >> 8) & ~clsConsts::u8DomainCompressMark)) && // Valid offset ((!p_bPrependRDLength) || - (_write16((2 + p_u16AdditionalLength), p_rSendParameter))) && // Lenght of 'Cxxx' - (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) + (_write16((2 + p_u16AdditionalLength), p_rSendParameter))) && // Lenght of 'Cxxx' + (_write8(((u16CachedDomainOffset >> 8) | clsConsts::u8DomainCompressMark), p_rSendParameter)) && // Compression mark (and offset) (_write8((uint8_t)(u16CachedDomainOffset & 0xFF), p_rSendParameter))) // No cached domain -> add this domain to cache and write full domain name - : ((_buildDomainForService(p_Service, p_bIncludeName, serviceDomain)) && // eg. MyESP._http._tcp.local + : ((_buildDomainForService(p_Service, p_bIncludeName, serviceDomain)) && // eg. MyESP._http._tcp.local ((!p_bPrependRDLength) || - (_write16((serviceDomain.m_u16NameLength + p_u16AdditionalLength), p_rSendParameter))) && // RDLength (if needed) + (_write16((serviceDomain.m_u16NameLength + p_u16AdditionalLength), p_rSendParameter))) && // RDLength (if needed) (p_rSendParameter.addDomainCacheItem((const void*)&p_Service, p_bIncludeName, p_rSendParameter.m_u16Offset)) && (_writeMDNSRRDomain(serviceDomain, p_rSendParameter)))); @@ -1698,8 +1732,8 @@ bool MDNSResponder::clsHost::_writeMDNSServiceDomain(const MDNSResponder::clsHos QCLASS (16bit, eg. IN) */ -bool MDNSResponder::clsHost::_writeMDNSQuestion(MDNSResponder::clsHost::stcRRQuestion& p_Question, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSQuestion(clsLEAMDNSHost::clsRRQuestion& p_Question, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSQuestion\n"));); @@ -1716,7 +1750,6 @@ bool MDNSResponder::clsHost::_writeMDNSQuestion(MDNSResponder::clsHost::stcRRQue }); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSQuestion: FAILED!\n"), _DH());); return bResult; - } @@ -1735,24 +1768,25 @@ bool MDNSResponder::clsHost::_writeMDNSQuestion(MDNSResponder::clsHost::stcRRQue eg. esp8266.local A 0x8001 120 4 123.456.789.012 Ref: http://www.zytrax.com/books/dns/ch8/a.html + */ -bool MDNSResponder::clsHost::_writeMDNSAnswer_A(IPAddress p_IPAddress, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSAnswer_A(IPAddress p_IPAddress, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_A (%s)%s\n"), p_IPAddress.toString().c_str(), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); - stcRRAttributes attributes(DNS_RRTYPE_A, + clsRRAttributes attributes(DNS_RRTYPE_A, ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - const unsigned char aucIPAddress[MDNS_IPV4_SIZE] = { p_IPAddress[0], p_IPAddress[1], p_IPAddress[2], p_IPAddress[3] }; + const unsigned char aucIPAddress[clsConsts::u16IPv4Size] = { p_IPAddress[0], p_IPAddress[1], p_IPAddress[2], p_IPAddress[3] }; bool bResult = ((p_IPAddress.isV4()) && (_writeMDNSHostDomain(m_pcHostName, false, 0, p_rSendParameter)) && (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS (_write32((p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL - (_write16(MDNS_IPV4_SIZE, p_rSendParameter)) && // RDLength - (_udpAppendBuffer(aucIPAddress, MDNS_IPV4_SIZE)) && // RData - (p_rSendParameter.shiftOffset(MDNS_IPV4_SIZE))); + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), p_rSendParameter)) && // TTL + (_write16(clsConsts::u16IPv4Size, p_rSendParameter)) && // RDLength + (_udpAppendBuffer(aucIPAddress, clsConsts::u16IPv4Size)) && // RData + (p_rSendParameter.shiftOffset(clsConsts::u16IPv4Size))); DEBUG_EX_INFO(if (bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_A %s.local Type:%s Class:0x%04X TTL:%u %s\n"), @@ -1762,7 +1796,7 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_A(IPAddress p_IPAddress, attributes.m_u16Class, (p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), p_IPAddress.toString().c_str()); ); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_A: FAILED!\n"), _DH());); @@ -1778,23 +1812,24 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_A(IPAddress p_IPAddress, eg. 012.789.456.123.in-addr.arpa PTR 0x8001 120 15 esp8266.local Used while answering reverse IPv4 questions + */ -bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_IPv4(IPAddress p_IPAddress, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSAnswer_PTR_IPv4(IPAddress p_IPAddress, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_IPv4 (%s)%s\n"), p_IPAddress.toString().c_str(), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); - stcRRDomain reverseIPv4Domain; - stcRRAttributes attributes(DNS_RRTYPE_PTR, + clsRRDomain reverseIPv4Domain; + clsRRAttributes attributes(DNS_RRTYPE_PTR, ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - stcRRDomain hostDomain; + clsRRDomain hostDomain; bool bResult = ((p_IPAddress.isV4()) && (_buildDomainForReverseIPv4(p_IPAddress, reverseIPv4Domain)) && // 012.789.456.123.in-addr.arpa (_writeMDNSRRDomain(reverseIPv4Domain, p_rSendParameter)) && (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS (_write32((p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), p_rSendParameter)) && // TTL (_writeMDNSHostDomain(m_pcHostName, true, 0, p_rSendParameter))); // RDLength & RData (host domain, eg. esp8266.local) DEBUG_EX_INFO(if (bResult) @@ -1805,7 +1840,7 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_IPv4(IPAddress p_IPAddress, attributes.m_u16Class, (p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), m_pcHostName); ); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_IPv4: FAILED!\n"), _DH());); @@ -1822,21 +1857,22 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_IPv4(IPAddress p_IPAddress, PTR all-services -> service type eg. _services._dns-sd._udp.local PTR 0x8001 5400 xx _http._tcp.local http://www.zytrax.com/books/dns/ch8/ptr.html + */ -bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_TYPE(MDNSResponder::clsHost::stcService& p_rService, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSAnswer_PTR_TYPE(clsLEAMDNSHost::clsService& p_rService, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_TYPE\n"));); - stcRRDomain dnssdDomain; - stcRRDomain serviceDomain; - stcRRAttributes attributes(DNS_RRTYPE_PTR, DNS_RRCLASS_IN); // No cache flush for shared records! only INternet + clsRRDomain dnssdDomain; + clsRRDomain serviceDomain; + clsRRAttributes attributes(DNS_RRTYPE_PTR, DNS_RRCLASS_IN); // No cache flush for shared records! only INternet bool bResult = ((_buildDomainForDNSSD(dnssdDomain)) && // _services._dns-sd._udp.local (_writeMDNSRRDomain(dnssdDomain, p_rSendParameter)) && (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS (_write32((p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), p_rSendParameter)) && // TTL + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL)), p_rSendParameter)) && // TTL (_writeMDNSServiceDomain(p_rService, false, true, 0, p_rSendParameter))); // RDLength & RData (service domain, eg. _http._tcp.local) DEBUG_EX_INFO(if (bResult) @@ -1847,8 +1883,8 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_TYPE(MDNSResponder::clsHost::s attributes.m_u16Class, (p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), - p_rService.m_pcServiceType, + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL)), + p_rService.m_pcType, p_rService.m_pcProtocol); ); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_TYPE: FAILED!\n"), _DH());); @@ -1864,32 +1900,33 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_TYPE(MDNSResponder::clsHost::s PTR service type -> service name eg. _http.tcp.local PTR 0x8001 120 xx myESP._http._tcp.local http://www.zytrax.com/books/dns/ch8/ptr.html + */ -bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_NAME(MDNSResponder::clsHost::stcService& p_rService, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSAnswer_PTR_NAME(clsLEAMDNSHost::clsService& p_rService, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_NAME\n"), _DH());); - stcRRAttributes attributes(DNS_RRTYPE_PTR, DNS_RRCLASS_IN); // No cache flush for shared records! only INternet + clsRRAttributes attributes(DNS_RRTYPE_PTR, DNS_RRCLASS_IN); // No cache flush for shared records! only INternet bool bResult = ((_writeMDNSServiceDomain(p_rService, false, false, 0, p_rSendParameter)) && // _http._tcp.local (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS (_write32((p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), p_rSendParameter)) && // TTL + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL)), p_rSendParameter)) && // TTL (_writeMDNSServiceDomain(p_rService, true, true, 0, p_rSendParameter))); // RDLength & RData (service domain, eg. MyESP._http._tcp.local) DEBUG_EX_INFO(if (bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_NAME _%s._%s.local Type:%s Class:0x%04X TTL:%u %s._%s._%s.local\n"), _DH(), - p_rService.m_pcServiceType, + p_rService.m_pcType, p_rService.m_pcProtocol, _RRType2Name(attributes.m_u16Type), attributes.m_u16Class, (p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), - p_rService.m_pcName, - p_rService.m_pcServiceType, + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL)), + p_rService.m_pcInstanceName, + p_rService.m_pcType, p_rService.m_pcProtocol); ); DEBUG_EX_ERR(if (!bResult)DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_NAME: FAILED!\n"), _DH());); @@ -1907,15 +1944,16 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_NAME(MDNSResponder::clsHost::s eg. myESP._http._tcp.local TXT 0x8001 120 4 c#=1 http://www.zytrax.com/books/dns/ch8/txt.html + */ -bool MDNSResponder::clsHost::_writeMDNSAnswer_TXT(MDNSResponder::clsHost::stcService& p_rService, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSAnswer_TXT(clsLEAMDNSHost::clsService& p_rService, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_TXT%s\n"), (p_rSendParameter.m_bCacheFlush ? "" : " nF"), _DH());); bool bResult = false; - stcRRAttributes attributes(DNS_RRTYPE_TXT, + clsRRAttributes attributes(DNS_RRTYPE_TXT, ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet if ((_collectServiceTxts(p_rService)) && @@ -1923,42 +1961,59 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_TXT(MDNSResponder::clsHost::stcSer (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS (_write32((p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), p_rSendParameter)) && // TTL - (_write16(p_rService.m_Txts.length(), p_rSendParameter))) // RDLength + : (p_rSendParameter.m_bLegacyDNSQuery // TTL + ? clsConsts::u32LegacyTTL + : clsConsts::u32ServiceTTL)), p_rSendParameter)) && + (_write16((p_rService.m_Txts.count() // RDLength + ? p_rService.m_Txts.length() // default case + : 1), p_rSendParameter))) // If no TXT records exist, a single 0 byte is sent { - bResult = true; // RData Txts - for (stcServiceTxt* pTxt = p_rService.m_Txts.m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) + if (p_rService.m_Txts.count()) { - unsigned char ucLengthByte = pTxt->length(); - bResult = ((_udpAppendBuffer((unsigned char*)&ucLengthByte, sizeof(ucLengthByte))) && // Length - (p_rSendParameter.shiftOffset(sizeof(ucLengthByte))) && - ((size_t)os_strlen(pTxt->m_pcKey) == m_rUDPContext.append(pTxt->m_pcKey, os_strlen(pTxt->m_pcKey))) && // Key - (p_rSendParameter.shiftOffset((size_t)os_strlen(pTxt->m_pcKey))) && - (1 == m_rUDPContext.append("=", 1)) && // = - (p_rSendParameter.shiftOffset(1)) && - ((!pTxt->m_pcValue) || - (((size_t)os_strlen(pTxt->m_pcValue) == m_rUDPContext.append(pTxt->m_pcValue, os_strlen(pTxt->m_pcValue))) && // Value - (p_rSendParameter.shiftOffset((size_t)os_strlen(pTxt->m_pcValue)))))); - - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_TXT: FAILED to write %sTxt %s=%s!\n"), _DH(), (pTxt->m_bTemp ? "temp. " : ""), (pTxt->m_pcKey ? : "?"), (pTxt->m_pcValue ? : "?"));); + for (const clsServiceTxt* pTxt : p_rService.m_Txts.m_Txts) + { + unsigned char ucLengthByte = pTxt->length(); + if (!((bResult = ((_udpAppendBuffer((unsigned char*)&ucLengthByte, sizeof(ucLengthByte))) && // Length + (p_rSendParameter.shiftOffset(sizeof(ucLengthByte))) && + ((size_t)os_strlen(pTxt->m_pcKey) == m_pUDPContext->append(pTxt->m_pcKey, os_strlen(pTxt->m_pcKey))) && // Key + (p_rSendParameter.shiftOffset((size_t)os_strlen(pTxt->m_pcKey))) && + (1 == m_pUDPContext->append("=", 1)) && // = + (p_rSendParameter.shiftOffset(1)) && + ((!pTxt->m_pcValue) || + (((size_t)os_strlen(pTxt->m_pcValue) == m_pUDPContext->append(pTxt->m_pcValue, os_strlen(pTxt->m_pcValue))) && // Value + (p_rSendParameter.shiftOffset((size_t)os_strlen(pTxt->m_pcValue))))))))) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_TXT: FAILED to write %sTxt %s=%s!\n"), _DH(), (pTxt->m_bTemp ? "temp. " : ""), (pTxt->m_pcKey ? : "?"), (pTxt->m_pcValue ? : "?"));); + break; + } + } + } + else + { + // RFC 6763 Ch.6: Every DNS-SD service MUST have a TXT record in addition to its SRV record, ... + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_TXT: Adding EMPTY TXT record!\n"), _DH());); + unsigned char ucLengthByte = 0; + bResult = ((_udpAppendBuffer((unsigned char*)&ucLengthByte, sizeof(ucLengthByte))) && // Length + (p_rSendParameter.shiftOffset(sizeof(ucLengthByte)))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_TXT: FAILED to write EMPTY TXT record!\n"), _DH());); } } DEBUG_EX_INFO(if (bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_TXT %s._%s._%s.local Type:%s Class:0x%04X TTL:%u \n"), _DH(), - p_rService.m_pcName, - p_rService.m_pcServiceType, + p_rService.m_pcInstanceName, + p_rService.m_pcType, p_rService.m_pcProtocol, _RRType2Name(attributes.m_u16Type), attributes.m_u16Class, (p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), - p_rService.m_pcName, - p_rService.m_pcServiceType, + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL)), + p_rService.m_pcInstanceName, + p_rService.m_pcType, p_rService.m_pcProtocol); ); @@ -1977,23 +2032,24 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_TXT(MDNSResponder::clsHost::stcSer eg. esp8266.local AAAA 0x8001 120 16 xxxx::xx http://www.zytrax.com/books/dns/ch8/aaaa.html + */ -bool MDNSResponder::clsHost::_writeMDNSAnswer_AAAA(IPAddress p_IPAddress, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSAnswer_AAAA(IPAddress p_IPAddress, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_AAAA (%s)%s\n"), p_IPAddress.toString().c_str(), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); - stcRRAttributes attributes(DNS_RRTYPE_AAAA, + clsRRAttributes attributes(DNS_RRTYPE_AAAA, ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet bool bResult = ((p_IPAddress.isV6()) && (_writeMDNSHostDomain(m_pcHostName, false, 0, p_rSendParameter)) && // esp8266.local (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS (_write32((p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL - (_write16(MDNS_IPV6_SIZE, p_rSendParameter)) && // RDLength - (_udpAppendBuffer((uint8_t*)p_IPAddress.raw6(), MDNS_IPV6_SIZE)) && // RData - (p_rSendParameter.shiftOffset(MDNS_IPV6_SIZE))); + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), p_rSendParameter)) && // TTL + (_write16(clsConsts::u16IPv6Size, p_rSendParameter)) && // RDLength + (_udpAppendBuffer((uint8_t*)p_IPAddress.raw6(), clsConsts::u16IPv6Size)) && // RData + (p_rSendParameter.shiftOffset(clsConsts::u16IPv6Size))); DEBUG_EX_INFO(if (bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_AAAA %s.local Type:%s Class:0x%04X TTL:%u %s\n"), @@ -2003,7 +2059,7 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_AAAA(IPAddress p_IPAddress, attributes.m_u16Class, (p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), p_IPAddress.toString().c_str()); ); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_AAAA: FAILED!\n"), _DH());); @@ -2018,14 +2074,15 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_AAAA(IPAddress p_IPAddress, eg. xxxx::xx.ip6.arpa PTR 0x8001 120 15 esp8266.local Used while answering reverse IPv6 questions + */ -bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_IPv6(IPAddress p_IPAddress, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSAnswer_PTR_IPv6(IPAddress p_IPAddress, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_IPv6%s\n"), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); - stcRRDomain reverseIPv6Domain; - stcRRAttributes attributes(DNS_RRTYPE_PTR, + clsRRDomain reverseIPv6Domain; + clsRRAttributes attributes(DNS_RRTYPE_PTR, ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet bool bResult = ((p_IPAddress.isV6()) && (_buildDomainForReverseIPv6(p_IPAddress, reverseIPv6Domain)) && // xxxx::xx.ip6.arpa @@ -2033,7 +2090,7 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_IPv6(IPAddress p_IPAddress, (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS (_write32((p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), p_rSendParameter)) && // TTL (_writeMDNSHostDomain(m_pcHostName, true, 0, p_rSendParameter))); // RDLength & RData (host domain, eg. esp8266.local) DEBUG_EX_INFO(if (bResult) @@ -2044,7 +2101,7 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_IPv6(IPAddress p_IPAddress, attributes.m_u16Class, (p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), m_pcHostName); ); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_IPv6: FAILED!\n"), _DH());); @@ -2057,24 +2114,25 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_PTR_IPv6(IPAddress p_IPAddress, eg. MyESP._http.tcp.local SRV 0x8001 120 0 0 60068 esp8266.local http://www.zytrax.com/books/dns/ch8/srv.html ???? Include instance name ???? + */ -bool MDNSResponder::clsHost::_writeMDNSAnswer_SRV(MDNSResponder::clsHost::stcService& p_rService, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSAnswer_SRV(clsLEAMDNSHost::clsService& p_rService, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_SRV%s\n"), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); - uint16_t u16CachedDomainOffset = (p_rSendParameter.m_bLegacyQuery + uint16_t u16CachedDomainOffset = (p_rSendParameter.m_bLegacyDNSQuery ? 0 : p_rSendParameter.findCachedDomainOffset((const void*)m_pcHostName, false)); - stcRRAttributes attributes(DNS_RRTYPE_SRV, + clsRRAttributes attributes(DNS_RRTYPE_SRV, ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - stcRRDomain hostDomain; + clsRRDomain hostDomain; bool bResult = ((_writeMDNSServiceDomain(p_rService, true, false, 0, p_rSendParameter)) && // MyESP._http._tcp.local (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS (_write32((p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL/*MDNS_SERVICE_TTL*/)), p_rSendParameter)) && // TTL + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL/*Consts::u32ServiceTTL*/)), p_rSendParameter)) && // TTL (!u16CachedDomainOffset // No cache for domain name (or no compression allowed) ? ((_buildDomainForHost(m_pcHostName, hostDomain)) && @@ -2082,36 +2140,36 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_SRV(MDNSResponder::clsHost::stcSer sizeof(uint16_t /*Weight*/) + sizeof(uint16_t /*Port*/) + hostDomain.m_u16NameLength), p_rSendParameter)) && // Domain length - (_write16(MDNS_SRV_PRIORITY, p_rSendParameter)) && // Priority - (_write16(MDNS_SRV_WEIGHT, p_rSendParameter)) && // Weight + (_write16(clsConsts::u16SRVPriority, p_rSendParameter)) && // Priority + (_write16(clsConsts::u16SRVWeight, p_rSendParameter)) && // Weight (_write16(p_rService.m_u16Port, p_rSendParameter)) && // Port (p_rSendParameter.addDomainCacheItem((const void*)m_pcHostName, false, p_rSendParameter.m_u16Offset)) && (_writeMDNSRRDomain(hostDomain, p_rSendParameter))) // Host, eg. esp8266.local // Cache available for domain - : ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset + : ((clsConsts::u8DomainCompressMark > ((u16CachedDomainOffset >> 8) & ~clsConsts::u8DomainCompressMark)) && // Valid offset (_write16((sizeof(uint16_t /*Prio*/) + // RDLength sizeof(uint16_t /*Weight*/) + sizeof(uint16_t /*Port*/) + 2), p_rSendParameter)) && // Length of 'C0xx' - (_write16(MDNS_SRV_PRIORITY, p_rSendParameter)) && // Priority - (_write16(MDNS_SRV_WEIGHT, p_rSendParameter)) && // Weight + (_write16(clsConsts::u16SRVPriority, p_rSendParameter)) && // Priority + (_write16(clsConsts::u16SRVWeight, p_rSendParameter)) && // Weight (_write16(p_rService.m_u16Port, p_rSendParameter)) && // Port - (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) + (_write8(((u16CachedDomainOffset >> 8) | clsConsts::u8DomainCompressMark), p_rSendParameter)) && // Compression mark (and offset) (_write8((uint8_t)u16CachedDomainOffset, p_rSendParameter))))); // Offset DEBUG_EX_INFO(if (bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_SRV %s._%s._%s.local Type:%s Class:0x%04X TTL:%u %u %u %u %s.local\n"), _DH(), - p_rService.m_pcName, - p_rService.m_pcServiceType, + p_rService.m_pcInstanceName, + p_rService.m_pcType, p_rService.m_pcProtocol, _RRType2Name(attributes.m_u16Type), attributes.m_u16Class, (p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), - MDNS_SRV_PRIORITY, - MDNS_SRV_WEIGHT, + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), + clsConsts::u16SRVPriority, + clsConsts::u16SRVWeight, p_rService.m_u16Port, m_pcHostName); ); @@ -2121,37 +2179,42 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_SRV(MDNSResponder::clsHost::stcSer /* MDNSResponder::_createNSECBitmap + */ -MDNSResponder::clsHost::stcNSECBitmap* MDNSResponder::clsHost::_createNSECBitmap(uint32_t p_u32NSECContent) +clsLEAMDNSHost::clsNSECBitmap* clsLEAMDNSHost::_createNSECBitmap(uint32_t p_u32NSECContent) { // Currently 6 bytes (6*8 -> 0..47) are long enough, and only this is implemented - stcNSECBitmap* pNSECBitmap = new stcNSECBitmap; + clsNSECBitmap* pNSECBitmap = new clsNSECBitmap; if (pNSECBitmap) { +#ifdef MDNS_IPV4_SUPPORT if (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::A)) { - pNSECBitmap->setBit(DNS_RRTYPE_A); // 01/0x01 + pNSECBitmap->setBit(DNS_RRTYPE_A); // 01/0x01 } +#endif if ((p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)) || (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv6))) { - pNSECBitmap->setBit(DNS_RRTYPE_PTR); // 12/0x0C + pNSECBitmap->setBit(DNS_RRTYPE_PTR); // 12/0x0C } +#ifdef MDNS_IPV6_SUPPORT if (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::AAAA)) { - pNSECBitmap->setBit(DNS_RRTYPE_AAAA); // 28/0x1C + pNSECBitmap->setBit(DNS_RRTYPE_AAAA); // 28/0x1C } +#endif if (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::TXT)) { - pNSECBitmap->setBit(DNS_RRTYPE_TXT); // 16/0x10 + pNSECBitmap->setBit(DNS_RRTYPE_TXT); // 16/0x10 } if (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::SRV)) { - pNSECBitmap->setBit(DNS_RRTYPE_SRV); // 33/0x21 + pNSECBitmap->setBit(DNS_RRTYPE_SRV); // 33/0x21 } if (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::NSEC)) { - pNSECBitmap->setBit(DNS_RRTYPE_NSEC); // 47/0x2F + pNSECBitmap->setBit(clsConsts::u8DNS_RRTYPE_NSEC); // 47/0x2F } } return pNSECBitmap; @@ -2159,9 +2222,10 @@ MDNSResponder::clsHost::stcNSECBitmap* MDNSResponder::clsHost::_createNSECBitmap /* MDNSResponder::_writeMDNSNSECBitmap + */ -bool MDNSResponder::clsHost::_writeMDNSNSECBitmap(const MDNSResponder::clsHost::stcNSECBitmap& p_NSECBitmap, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSNSECBitmap(const clsLEAMDNSHost::clsNSECBitmap& p_NSECBitmap, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { /* DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("_writeMDNSNSECBitmap: ")); for (uint16_t u=0; u<p_NSECBitmap.m_u16BitmapLength; ++u) { @@ -2180,23 +2244,24 @@ bool MDNSResponder::clsHost::_writeMDNSNSECBitmap(const MDNSResponder::clsHost:: /* MDNSResponder::_writeMDNSAnswer_NSEC(host) - eg. esp8266.local NSEC 0x8001 120 XX esp8266.local xxx + eg. esp8266.local NSEC 0x8001 120 XX esp8266.local xyz http://www.zytrax.com/books/dns/ch8/nsec.html + */ -bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC(uint32_t p_u32NSECContent, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSAnswer_NSEC(uint32_t p_u32NSECContent, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC (host: %s)%s\n"), _replyFlags2String(p_u32NSECContent), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); - stcRRAttributes attributes(DNS_RRTYPE_NSEC, + clsRRAttributes attributes(clsConsts::u8DNS_RRTYPE_NSEC, ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - stcNSECBitmap* pNSECBitmap = _createNSECBitmap(p_u32NSECContent); + clsNSECBitmap* pNSECBitmap = _createNSECBitmap(p_u32NSECContent); bool bResult = ((pNSECBitmap) && // NSEC bitmap created (_writeMDNSHostDomain(m_pcHostName, false, 0, p_rSendParameter)) && // esp8266.local (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS (_write32((p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), p_rSendParameter)) && // TTL (_writeMDNSHostDomain(m_pcHostName, true, (2 + pNSECBitmap->length()), p_rSendParameter)) && // XX esp8266.local (_writeMDNSNSECBitmap(*pNSECBitmap, p_rSendParameter))); // NSEC bitmap @@ -2208,7 +2273,7 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC(uint32_t p_u32NSECContent, attributes.m_u16Class, (p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), m_pcHostName, _NSECBitmap2String(pNSECBitmap)); ); @@ -2228,18 +2293,19 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC(uint32_t p_u32NSECContent, /* MDNSResponder::_writeMDNSAnswer_NSEC_PTR_IPv4(host) - eg. 012.789.456.123.in-addr.arpa NSEC 0x8001 120 XX 012.789.456.123.in-addr.arpa xxx + eg. 012.789.456.123.in-addr.arpa NSEC 0x8001 120 XX 012.789.456.123.in-addr.arpa xyz http://www.zytrax.com/books/dns/ch8/nsec.html + */ -bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC_PTR_IPv4(IPAddress p_IPAddress, - stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSAnswer_NSEC_PTR_IPv4(IPAddress p_IPAddress, + clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC_PTR_IPv4\n"));); - stcRRAttributes attributes(DNS_RRTYPE_NSEC, + clsRRAttributes attributes(clsConsts::u8DNS_RRTYPE_NSEC, ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - stcNSECBitmap* pNSECBitmap = _createNSECBitmap(static_cast<uint32_t>(enuContentFlag::PTR_IPv4)); - stcRRDomain reverseIPv4Domain; + clsNSECBitmap* pNSECBitmap = _createNSECBitmap(static_cast<uint32_t>(enuContentFlag::PTR_IPv4)); + clsRRDomain reverseIPv4Domain; bool bResult = ((p_IPAddress.isV4()) && (pNSECBitmap) && // NSEC bitmap created (_buildDomainForReverseIPv4(p_IPAddress, reverseIPv4Domain)) && // 012.789.456.123.in-addr.arpa @@ -2247,7 +2313,7 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC_PTR_IPv4(IPAddress p_IPAddres (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS (_write32((p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), p_rSendParameter)) && // TTL (_write16((reverseIPv4Domain.m_u16NameLength + (2 + pNSECBitmap->length())), p_rSendParameter)) && (_writeMDNSRRDomain(reverseIPv4Domain, p_rSendParameter)) && // 012.789.456.123.in-addr.arpa (_writeMDNSNSECBitmap(*pNSECBitmap, p_rSendParameter))); // NSEC bitmap @@ -2261,7 +2327,7 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC_PTR_IPv4(IPAddress p_IPAddres attributes.m_u16Class, (p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL))); + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL))); _printRRDomain(reverseIPv4Domain); DEBUG_OUTPUT.printf_P(PSTR(" %s\n"), _NSECBitmap2String(pNSECBitmap)); }); @@ -2282,18 +2348,19 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC_PTR_IPv4(IPAddress p_IPAddres /* MDNSResponder::_writeMDNSAnswer_NSEC_PTR_IPv6(host) - eg. 9.0.0.0.0.0.0.0.0.0.0.0.0.7.8.5.6.3.4.1.2.ip6.arpa NSEC 0x8001 120 XX 9.0.0.0.0.0.0.0.0.0.0.0.0.7.8.5.6.3.4.1.2.ip6.arpa xxx + eg. 9.0.0.0.0.0.0.0.0.0.0.0.0.7.8.5.6.3.4.1.2.ip6.arpa NSEC 0x8001 120 XX 9.0.0.0.0.0.0.0.0.0.0.0.0.7.8.5.6.3.4.1.2.ip6.arpa xyz http://www.zytrax.com/books/dns/ch8/nsec.html + */ -bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC_PTR_IPv6(IPAddress p_IPAddress, - stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSAnswer_NSEC_PTR_IPv6(IPAddress p_IPAddress, + clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC_PTR_IPv6\n"));); - stcRRAttributes attributes(DNS_RRTYPE_NSEC, + clsRRAttributes attributes(clsConsts::u8DNS_RRTYPE_NSEC, ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - stcNSECBitmap* pNSECBitmap = _createNSECBitmap(static_cast<uint32_t>(enuContentFlag::PTR_IPv6)); - stcRRDomain reverseIPv6Domain; + clsNSECBitmap* pNSECBitmap = _createNSECBitmap(static_cast<uint32_t>(enuContentFlag::PTR_IPv6)); + clsRRDomain reverseIPv6Domain; bool bResult = ((p_IPAddress.isV6()) && (pNSECBitmap) && // NSEC bitmap created (_buildDomainForReverseIPv6(p_IPAddress, reverseIPv6Domain)) && // 9.0.0.0.0.0.0.0.0.0.0.0.0.7.8.5.6.3.4.1.2.ip6.arpa @@ -2301,7 +2368,7 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC_PTR_IPv6(IPAddress p_IPAddres (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS (_write32((p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_HOST_TTL)), p_rSendParameter)) && // TTL + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), p_rSendParameter)) && // TTL (_write16((reverseIPv6Domain.m_u16NameLength + (2 + pNSECBitmap->length())), p_rSendParameter)) && (_writeMDNSRRDomain(reverseIPv6Domain, p_rSendParameter)) && // 9.0.0.0.0.0.0.0.0.0.0.0.0.7.8.5.6.3.4.1.2.ip6.arpa (_writeMDNSNSECBitmap(*pNSECBitmap, p_rSendParameter))); // NSEC bitmap @@ -2315,7 +2382,7 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC_PTR_IPv6(IPAddress p_IPAddres attributes.m_u16Class, (p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL))); + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL))); _printRRDomain(reverseIPv6Domain); DEBUG_OUTPUT.printf_P(PSTR(" %s\n"), _NSECBitmap2String(pNSECBitmap)); }); @@ -2334,38 +2401,39 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC_PTR_IPv6(IPAddress p_IPAddres /* MDNSResponder::_writeMDNSAnswer_NSEC(service) - eg. MyESP._http.tcp.local NSEC 0x8001 4500 XX MyESP._http.tcp.local xxx + eg. MyESP._http.tcp.local NSEC 0x8001 4500 XX MyESP._http.tcp.local xyz http://www.zytrax.com/books/dns/ch8/nsec.html + */ -bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC(MDNSResponder::clsHost::stcService& p_rService, - uint32_t p_u32NSECContent, - MDNSResponder::clsHost::stcSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_writeMDNSAnswer_NSEC(clsLEAMDNSHost::clsService& p_rService, + uint32_t p_u32NSECContent, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC (service: %s)\n"), _DH(), _replyFlags2String(p_u32NSECContent));); - stcRRAttributes attributes(DNS_RRTYPE_NSEC, + clsRRAttributes attributes(clsConsts::u8DNS_RRTYPE_NSEC, ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - stcNSECBitmap* pNSECBitmap = _createNSECBitmap(p_u32NSECContent); + clsNSECBitmap* pNSECBitmap = _createNSECBitmap(p_u32NSECContent); bool bResult = ((pNSECBitmap) && // NSEC bitmap created (_writeMDNSServiceDomain(p_rService, true, false, 0, p_rSendParameter)) && // MyESP._http._tcp.local (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS (_write32((p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), p_rSendParameter)) && // TTL + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL)), p_rSendParameter)) && // TTL (_writeMDNSServiceDomain(p_rService, true, true, (2 + pNSECBitmap->length()), p_rSendParameter)) && // XX MyESP._http._tcp.local (_writeMDNSNSECBitmap(*pNSECBitmap, p_rSendParameter))); // NSEC bitmap DEBUG_EX_INFO(if (bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC %s._%s._%s.local Type:%s Class:0x%04X TTL:%u %s\n"), _DH(), - p_rService.m_pcName, - p_rService.m_pcServiceType, + p_rService.m_pcInstanceName, + p_rService.m_pcType, p_rService.m_pcProtocol, _RRType2Name(attributes.m_u16Type), attributes.m_u16Class, (p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyQuery ? MDNS_LEGACY_TTL : MDNS_SERVICE_TTL)), + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL)), _NSECBitmap2String(pNSECBitmap)); ); @@ -2379,8 +2447,10 @@ bool MDNSResponder::clsHost::_writeMDNSAnswer_NSEC(MDNSResponder::clsHost::stcSe return bResult; } + } // namespace MDNSImplementation + } // namespace esp8266 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_API.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_API.cpp deleted file mode 100755 index 4b3d22902e..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_API.cpp +++ /dev/null @@ -1,4164 +0,0 @@ -/* - LEAmDNS2_API.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - - -#include <Schedule.h> -#include <lwip/netif.h> - -#include "LEAmDNS2_Priv.h" - - -namespace -{ - -/* - strrstr (static) - - Backwards search for p_pcPattern in p_pcString - Based on: https://stackoverflow.com/a/1634398/2778898 - -*/ -const char* strrstr(const char*__restrict p_pcString, const char*__restrict p_pcPattern) -{ - const char* pcResult = 0; - - size_t stStringLength = (p_pcString ? strlen(p_pcString) : 0); - size_t stPatternLength = (p_pcPattern ? strlen(p_pcPattern) : 0); - - if ((stStringLength) && - (stPatternLength) && - (stPatternLength <= stStringLength)) - { - // Pattern is shorter or has the same length tham the string - - for (const char* s = (p_pcString + stStringLength - stPatternLength); s >= p_pcString; --s) - { - if (0 == strncmp(s, p_pcPattern, stPatternLength)) - { - pcResult = s; - break; - } - } - } - return pcResult; -} - -} // anonymous - - -namespace esp8266 -{ - -/* - LEAmDNS -*/ -namespace experimental -{ - -/** - STRINGIZE -*/ -#ifndef STRINGIZE -#define STRINGIZE(x) #x -#endif -#ifndef STRINGIZE_VALUE_OF -#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) -#endif - -/** - HELPERS -*/ - -/* - MDNSResponder::indexDomain (static) - - Updates the given domain 'p_rpcHostName' by appending a delimiter and an index number. - - If the given domain already hasa numeric index (after the given delimiter), this index - incremented. If not, the delimiter and index '2' is added. - - If 'p_rpcHostName' is empty (==0), the given default name 'p_pcDefaultHostName' is used, - if no default is given, 'esp8266' is used. - -*/ -/*static*/ bool MDNSResponder::indexDomain(char*& p_rpcDomain, - const char* p_pcDivider /*= "-"*/, - const char* p_pcDefaultDomain /*= 0*/) -{ - bool bResult = false; - - // Ensure a divider exists; use '-' as default - const char* pcDivider = (p_pcDivider ? : "-"); - - if (p_rpcDomain) - { - const char* pFoundDivider = strrstr(p_rpcDomain, pcDivider); - if (pFoundDivider) // maybe already extended - { - char* pEnd = 0; - unsigned long ulIndex = strtoul((pFoundDivider + strlen(pcDivider)), &pEnd, 10); - if ((ulIndex) && - ((pEnd - p_rpcDomain) == (ptrdiff_t)strlen(p_rpcDomain)) && - (!*pEnd)) // Valid (old) index found - { - - char acIndexBuffer[16]; - sprintf(acIndexBuffer, "%lu", (++ulIndex)); - size_t stLength = ((pFoundDivider - p_rpcDomain + strlen(pcDivider)) + strlen(acIndexBuffer) + 1); - char* pNewHostName = new char[stLength]; - if (pNewHostName) - { - memcpy(pNewHostName, p_rpcDomain, (pFoundDivider - p_rpcDomain + strlen(pcDivider))); - pNewHostName[pFoundDivider - p_rpcDomain + strlen(pcDivider)] = 0; - strcat(pNewHostName, acIndexBuffer); - - delete[] p_rpcDomain; - p_rpcDomain = pNewHostName; - - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] indexDomain: FAILED to alloc new hostname!\n"));); - } - } - else - { - pFoundDivider = 0; // Flag the need to (base) extend the hostname - } - } - - if (!pFoundDivider) // not yet extended (or failed to increment extension) -> start indexing - { - size_t stLength = strlen(p_rpcDomain) + (strlen(pcDivider) + 1 + 1); // Name + Divider + '2' + '\0' - char* pNewHostName = new char[stLength]; - if (pNewHostName) - { - sprintf(pNewHostName, "%s%s2", p_rpcDomain, pcDivider); - - delete[] p_rpcDomain; - p_rpcDomain = pNewHostName; - - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] indexDomain: FAILED to alloc new hostname!\n"));); - } - } - } - else - { - // No given host domain, use base or default - const char* cpcDefaultName = (p_pcDefaultDomain ? : "esp8266"); - - size_t stLength = strlen(cpcDefaultName) + 1; // '\0' - p_rpcDomain = new char[stLength]; - if (p_rpcDomain) - { - strncpy(p_rpcDomain, cpcDefaultName, stLength); - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] indexDomain: FAILED to alloc new hostname!\n"));); - } - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] indexDomain: %s\n"), p_rpcDomain);); - return bResult; -} - - -/* - MDNSResponder::setStationHostName (static) - - Sets the staion hostname - -*/ -/*static*/ bool MDNSResponder::setNetIfHostName(netif* p_pNetIf, - const char* p_pcHostName) -{ - if ((p_pNetIf) && - (p_pcHostName)) - { - netif_set_hostname(p_pNetIf, p_pcHostName); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setNetIfHostName host name: %s!\n"), p_pcHostName);); - } - return true; -} - - -/** - INTERFACE -*/ - -/** - MDNSResponder::MDNSResponder -*/ -MDNSResponder::MDNSResponder(void) - : m_pUDPContext(0) -{ - _allocUDPContext(); -} - -/* - MDNSResponder::~MDNSResponder -*/ -MDNSResponder::~MDNSResponder(void) -{ - close(); -} - -/* - MDNSResponder::begin (hostname, netif, probe_callback) -*/ -MDNSResponder::hMDNSHost MDNSResponder::begin(const char* p_pcHostName, - netif* p_pNetIf, - MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s, netif: %u)\n"), _DH(), (p_pcHostName ? : "-"), (p_pNetIf ? netif_get_index(p_pNetIf) : 0));); - - return (hMDNSHost)_begin(p_pcHostName, p_pNetIf, p_fnCallback); -} - -/* - MDNSResponder::begin (hostname, probe_callback) -*/ -bool MDNSResponder::begin(const char* p_pcHostName, - MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s)\n"), _DH(), (p_pcHostName ? : "_"));); - - return begin(p_pcHostName, (WiFiMode_t)wifi_get_opmode(), p_fnCallback); -} - -/* - MDNSResponder::begin (hostname, WiFiMode, probe_callback) -*/ -bool MDNSResponder::begin(const char* p_pcHostName, - WiFiMode_t p_WiFiMode, - MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s, opmode: %u)\n"), _DH(), (p_pcHostName ? : "_"), (uint32_t)p_WiFiMode);); - - bool bResult = true; - - if ((bResult) && - (p_WiFiMode & WIFI_STA)) - { - bResult = (0 != _begin(p_pcHostName, netif_get_by_index(WIFI_STA), p_fnCallback)); - } - if ((bResult) && - (p_WiFiMode & WIFI_AP)) - { - bResult = (0 != _begin(p_pcHostName, netif_get_by_index(WIFI_AP), p_fnCallback)); - } - return bResult; -} - -/* - MDNSResponder::close -*/ -bool MDNSResponder::close(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_close(*(clsHost*)p_hMDNSHost))); -} - -/* - MDNSResponder::close (convenience) -*/ -bool MDNSResponder::close(void) -{ - clsHostList::iterator it(m_HostList.begin()); - while (m_HostList.end() != it) - { - _close(**it++); - } - - return _releaseUDPContext(); -} - - -/* - MDNSResponder::getMDNSHost (netif) -*/ -MDNSResponder::hMDNSHost MDNSResponder::getMDNSHost(netif* p_pNetIf) const -{ - return (hMDNSHost)(p_pNetIf ? _findHost(p_pNetIf) : 0); -} - -/* - MDNSResponder::getMDNSHost (WiFiMode) -*/ -MDNSResponder::hMDNSHost MDNSResponder::getMDNSHost(WiFiMode_t p_WiFiMode) const -{ - hMDNSHost hResult = 0; - - if (WIFI_STA == p_WiFiMode) - { - hResult = getMDNSHost(netif_get_by_index(WIFI_STA)); - } - else if (WIFI_AP == p_WiFiMode) - { - hResult = getMDNSHost(netif_get_by_index(WIFI_AP)); - } - return hResult; -} - -/* - MDNSResponder::setHostName -*/ -bool MDNSResponder::setHostName(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcHostName, - MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_NRH2Ptr(p_hMDNSHost)->setHostName(p_pcHostName)) && - (p_fnCallback ? setHostProbeResultCallback(p_hMDNSHost, p_fnCallback) : true)); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setHostName: FAILED for '%s'!\n"), _DH(p_hMDNSHost), (p_pcHostName ? : "-"));); - return bResult; -} - -/* - MDNSResponder::hostName -*/ -const char* MDNSResponder::hostName(const MDNSResponder::hMDNSHost p_hMDNSHost) const -{ - return (_validateMDNSHostHandle(p_hMDNSHost) - ? (_NRH2Ptr(p_hMDNSHost)->hostName()) - : 0); -} - -/* - MDNSResponder::setHostProbeResultCallback -*/ -bool MDNSResponder::setHostProbeResultCallback(const hMDNSHost p_hMDNSHost, - MDNSHostProbeResultCallbackFn p_fnCallback) -{ - bool bResult = false; - if ((bResult = _validateMDNSHostHandle(p_hMDNSHost))) - { - if (p_fnCallback) - { - _NRH2Ptr(p_hMDNSHost)->m_HostProbeInformation.m_fnProbeResultCallback = [this, p_fnCallback](clsHost & p_rHost, - const char* p_pcDomainName, - bool p_bProbeResult)->void - { - p_fnCallback(*this, (hMDNSHost)&p_rHost, p_pcDomainName, p_bProbeResult); - }; - } - else - { - _NRH2Ptr(p_hMDNSHost)->m_HostProbeInformation.m_fnProbeResultCallback = 0; - } - } - return bResult; -} - -/* - MDNSResponder::status -*/ -bool MDNSResponder::status(const MDNSResponder::hMDNSHost p_hMDNSHost) const -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_NRH2Ptr(p_hMDNSHost)->probeStatus())); -} - - -/* - SERVICES -*/ - -/* - MDNSResponder::setInstanceName -*/ -bool MDNSResponder::setInstanceName(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcInstanceName) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_NRH2Ptr(p_hMDNSHost)->setInstanceName(p_pcInstanceName))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setInstanceName: FAILED for '%s'!\n"), _DH(p_hMDNSHost), (p_pcInstanceName ? : "-"));); - return bResult; -} - -/* - MDNSResponder::instanceName -*/ -const char* MDNSResponder::instanceName(const MDNSResponder::hMDNSHost p_hMDNSHost) const -{ - return (_validateMDNSHostHandle(p_hMDNSHost) - ? (_NRH2Ptr(p_hMDNSHost)->instanceName()) - : 0); -} - -/* - MDNSResponder::addService - - Add service; using hostname if no name is explicitly provided for the service - The usual '_' underline, which is prepended to service and protocol, eg. _http, - may be given. If not, it is added automatically. - -*/ -MDNSResponder::hMDNSService MDNSResponder::addService(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcName, - const char* p_pcServiceType, - const char* p_pcProtocol, - uint16_t p_u16Port, - MDNSServiceProbeResultCallbackFn p_fnCallback /*= 0*/) -{ - hMDNSService hService = (_validateMDNSHostHandle(p_hMDNSHost) - ? (hMDNSService)_NRH2Ptr(p_hMDNSHost)->addService(p_pcName, p_pcServiceType, p_pcProtocol, p_u16Port) - : 0); - if ((p_fnCallback) && - (hService)) - { - setServiceProbeResultCallback(p_hMDNSHost, hService, p_fnCallback); - } - DEBUG_EX_ERR(if (!hService) DEBUG_OUTPUT.printf_P(PSTR("%s addService: FAILED for '%s._%s._%s.local'!\n"), _DH(p_hMDNSHost), (p_pcName ? : "-"), (p_pcServiceType ? : "-"), (p_pcProtocol ? : "-"));); - return hService; -} - -/* - MDNSResponder::removeService - - Unanounce a service (by sending a goodbye message) and remove it - from the MDNS responder - -*/ -bool MDNSResponder::removeService(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && - (_NRH2Ptr(p_hMDNSHost)->removeService(_SH2Ptr(p_hMDNSService)))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeService: FAILED!\n"), _DH(p_hMDNSHost));); - return bResult; -} - -/* - MDNSResponder::removeService -*/ -bool MDNSResponder::removeService(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcInstanceName, - const char* p_pcServiceType, - const char* p_pcProtocol) -{ - clsHost* pMDNSHost; - clsHost::stcService* pMDNSService; - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && - (pMDNSHost = (clsHost*)p_hMDNSHost) && - ((pMDNSService = _NRH2Ptr(p_hMDNSHost)->findService(p_pcInstanceName, p_pcServiceType, p_pcProtocol))) && - (_NRH2Ptr(p_hMDNSHost)->removeService(pMDNSService))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeService: FAILED for '%s._%s._%s.local'!\n"), _DH(p_hMDNSHost), (p_pcInstanceName ? : "-"), (p_pcServiceType ? : "-"), (p_pcProtocol ? : "-"));); - return bResult; -} - -/* - MDNSResponder::findService - - Find an existing service. - -*/ -MDNSResponder::hMDNSService MDNSResponder::findService(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcInstanceName, - const char* p_pcServiceType, - const char* p_pcProtocol) -{ - clsHost* pMDNSHost; - return (((_validateMDNSHostHandle(p_hMDNSHost)) && - (pMDNSHost = (clsHost*)p_hMDNSHost)) - ? _NRH2Ptr(p_hMDNSHost)->findService(p_pcInstanceName, p_pcServiceType, p_pcProtocol) - : 0); -} - -/* - MDNSResponder::setServiceName -*/ -bool MDNSResponder::setServiceName(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcInstanceName, - MDNSServiceProbeResultCallbackFn p_fnCallback /*= 0*/) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && - (_NRH2Ptr(p_hMDNSHost)->setServiceName(_SH2Ptr(p_hMDNSService), p_pcInstanceName)) && - (p_fnCallback ? setServiceProbeResultCallback(p_hMDNSHost, p_hMDNSService, p_fnCallback) : true)); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setServiceName: FAILED for '%s'!\n"), _DH(p_hMDNSHost), (p_pcInstanceName ? : "-"));); - return bResult; -} - -/* - MDNSResponder::serviceName -*/ -const char* MDNSResponder::serviceName(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const -{ - return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) - ? (_SH2Ptr(p_hMDNSService)->m_pcName) - : 0); -} - -/* - MDNSResponder::serviceType -*/ -const char* MDNSResponder::serviceType(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const -{ - return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) - ? (_SH2Ptr(p_hMDNSService)->m_pcServiceType) - : 0); -} - -/* - MDNSResponder::serviceProtocol -*/ -const char* MDNSResponder::serviceProtocol(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const -{ - return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) - ? (_SH2Ptr(p_hMDNSService)->m_pcProtocol) - : 0); -} - -/* - MDNSResponder::serviceProtocol -*/ -uint16_t MDNSResponder::servicePort(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const -{ - return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) - ? (_SH2Ptr(p_hMDNSService)->m_u16Port) - : 0); -} - -/* - MDNSResponder::setServiceProbeResultCallback - - Set a service specific callback for probe results. The callback is called, when probing - for the service domain failes or succeedes. - In the case of failure, the service name should be changed via 'setServiceName'. - When succeeded, the service domain will be announced by the MDNS responder. - -*/ -bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - MDNSResponder::MDNSServiceProbeResultCallbackFn p_fnCallback) -{ - bool bResult = false; - if ((bResult = _validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService))) - { - if (p_fnCallback) - { - _SH2Ptr(p_hMDNSService)->m_ProbeInformation.m_fnProbeResultCallback = [this, p_fnCallback](clsHost & p_rHost, - clsHost::stcService & p_rMDNSService, - const char* p_pcDomainName, - bool p_bProbeResult)->void - { - p_fnCallback(*this, (hMDNSHost)&p_rHost, (hMDNSService)&p_rMDNSService, p_pcDomainName, p_bProbeResult); - }; - } - else - { - _SH2Ptr(p_hMDNSService)->m_ProbeInformation.m_fnProbeResultCallback = 0; - } - } - return bResult; -} - -/* - MDNSResponder::serviceStatus -*/ -bool MDNSResponder::serviceStatus(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const -{ - return ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && - (_SH2Ptr(p_hMDNSService)->probeStatus())); -} - - -/* - SERVICE TXT -*/ - -/* - MDNSResponder::addServiceTxt - - Add a static service TXT item ('Key'='Value') to a service. - -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - const char* p_pcValue) -{ - hMDNSTxt hTxt = (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) - ? (hMDNSTxt)_NRH2Ptr(p_hMDNSHost)->addServiceTxt(_SH2Ptr(p_hMDNSService), p_pcKey, p_pcValue) - : 0); - DEBUG_EX_ERR(if (!hTxt) DEBUG_OUTPUT.printf_P(PSTR("%s addServiceTxt: FAILED for '%s=%s'!\n"), _DH(p_hMDNSHost), (p_pcKey ? : "-"), (p_pcValue ? : "-"));); - return hTxt; -} - -/* - MDNSRESPONDER_xxx_TO_CHAR - Formats: http://www.cplusplus.com/reference/cstdio/printf/ -*/ -#define MDNSRESPONDER_U32_TO_CHAR(BUFFERNAME, U32VALUE) \ - char BUFFERNAME[16]; /* 32-bit max 10 digits */ \ - *BUFFERNAME = 0; \ - sprintf(BUFFERNAME, "%u", U32VALUE); -#define MDNSRESPONDER_U16_TO_CHAR(BUFFERNAME, U16VALUE) \ - char BUFFERNAME[8]; /* 16-bit max 5 digits */ \ - *BUFFERNAME = 0; \ - sprintf(BUFFERNAME, "%hu", U16VALUE); -#define MDNSRESPONDER_U8_TO_CHAR(BUFFERNAME, U8VALUE) \ - char BUFFERNAME[8]; /* 8-bit max 3 digits */ \ - *BUFFERNAME = 0; \ - sprintf(BUFFERNAME, "%hhu", U8VALUE); -#define MDNSRESPONDER_I32_TO_CHAR(BUFFERNAME, I32VALUE) \ - char BUFFERNAME[16]; /* 32-bit max 10 digits */ \ - *BUFFERNAME = 0; \ - sprintf(BUFFERNAME, "%i", I32VALUE); -#define MDNSRESPONDER_I16_TO_CHAR(BUFFERNAME, I16VALUE) \ - char BUFFERNAME[8]; /* 16-bit max 5 digits */ \ - *BUFFERNAME = 0; \ - sprintf(BUFFERNAME, "%hi", I16VALUE); -#define MDNSRESPONDER_I8_TO_CHAR(BUFFERNAME, I8VALUE) \ - char BUFFERNAME[8]; /* 8-bit max 3 digits */ \ - *BUFFERNAME = 0; \ - sprintf(BUFFERNAME, "%hhi", I8VALUE); - -/* - MDNSResponder::addServiceTxt (uint32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - MDNSRESPONDER_U32_TO_CHAR(acBuffer, p_u32Value); - return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (uint16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - MDNSRESPONDER_U16_TO_CHAR(acBuffer, p_u16Value); - return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (uint8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - MDNSRESPONDER_U8_TO_CHAR(acBuffer, p_u8Value); - return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (int32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int32_t p_i32Value) -{ - MDNSRESPONDER_I32_TO_CHAR(acBuffer, p_i32Value); - return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (int16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int16_t p_i16Value) -{ - MDNSRESPONDER_I16_TO_CHAR(acBuffer, p_i16Value); - return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (int8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int8_t p_i8Value) -{ - MDNSRESPONDER_I8_TO_CHAR(acBuffer, p_i8Value); - return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::removeServiceTxt - - Remove a static service TXT item from a service. -*/ -bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const MDNSResponder::hMDNSTxt p_hTxt) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && - (p_hTxt) && - (_NRH2Ptr(p_hMDNSHost)->removeServiceTxt(_SH2Ptr(p_hMDNSService), (clsHost::stcServiceTxt*)p_hTxt))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeServiceTxt: FAILED!\n"), _DH(p_hMDNSHost));); - return bResult; -} - -/* - MDNSResponder::removeServiceTxt -*/ -bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && - (p_pcKey) && - (_NRH2Ptr(p_hMDNSHost)->removeServiceTxt(_SH2Ptr(p_hMDNSService), _NRH2Ptr(p_hMDNSHost)->findServiceTxt(_SH2Ptr(p_hMDNSService), p_pcKey)))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeServiceTxt: FAILED!\n"), _DH(p_hMDNSHost));); - return bResult; -} - -/* - MDNSResponder::setDynamicServiceTxtCallback (binding) - - Set a netif binding specific callback for dynamic service TXT items. The callback is called, whenever - service TXT items are needed for any service on the netif binding. - -*/ -bool MDNSResponder::setDynamicServiceTxtCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, - MDNSResponder::MDNSDynamicServiceTxtCallbackFn p_fnCallback) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && - ((!p_fnCallback) || - (_NRH2Ptr(p_hMDNSHost)->setDynamicServiceTxtCallback([this, p_fnCallback](clsHost & p_rHost, - clsHost::stcService & p_rMDNSService)->void - { - if (p_fnCallback) - { - p_fnCallback(*this, (hMDNSHost)&p_rHost, (hMDNSService)&p_rMDNSService); - } - })))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setDynamicServiceTxtCallback: FAILED!\n"), _DH(p_hMDNSHost));); - return bResult; -} - -/* - MDNSResponder::setDynamicServiceTxtCallback (service) - - Set a service specific callback for dynamic service TXT items. The callback is called, whenever - service TXT items are needed for the given service. -*/ -bool MDNSResponder::setDynamicServiceTxtCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - MDNSResponder::MDNSDynamicServiceTxtCallbackFn p_fnCallback) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && - ((!p_fnCallback) || - (_NRH2Ptr(p_hMDNSHost)->setDynamicServiceTxtCallback(_SH2Ptr(p_hMDNSService), [this, p_fnCallback](clsHost & p_rHost, - clsHost::stcService & p_rMDNSService)->void - { - if (p_fnCallback) - { - p_fnCallback(*this, (hMDNSHost)&p_rHost, (hMDNSService)&p_rMDNSService); - } - })))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setDynamicServiceTxtCallback: FAILED!\n"), _DH(p_hMDNSHost));); - return bResult; -} - -/* - MDNSResponder::addDynamicServiceTxt -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - const char* p_pcValue) -{ - hMDNSTxt hTxt = (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) - ? (hMDNSTxt)_NRH2Ptr(p_hMDNSHost)->addDynamicServiceTxt(_SH2Ptr(p_hMDNSService), p_pcKey, p_pcValue) - : 0); - DEBUG_EX_ERR(if (!hTxt) DEBUG_OUTPUT.printf_P(PSTR("%s addServiceTxt: FAILED for '%s=%s'!\n"), _DH(p_hMDNSHost), (p_pcKey ? : "-"), (p_pcValue ? : "-"));); - return hTxt; -} - -/* - MDNSResponder::addDynamicServiceTxt (uint32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - MDNSRESPONDER_U32_TO_CHAR(acBuffer, p_u32Value); - return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (uint16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - MDNSRESPONDER_U16_TO_CHAR(acBuffer, p_u16Value); - return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (uint8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - MDNSRESPONDER_U8_TO_CHAR(acBuffer, p_u8Value); - return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (int32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int32_t p_i32Value) -{ - MDNSRESPONDER_I32_TO_CHAR(acBuffer, p_i32Value); - return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (int16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int16_t p_i16Value) -{ - MDNSRESPONDER_I16_TO_CHAR(acBuffer, p_i16Value); - return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (int8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int8_t p_i8Value) -{ - MDNSRESPONDER_I8_TO_CHAR(acBuffer, p_i8Value); - return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer); -} - - -/** - QUERIES -*/ - - -/** - MDNSResponder::clsMDNSAnswerAccessor - -*/ - -/* - MDNSResponder::clsMDNSAnswerAccessor::clsMDNSAnswerAccessor constructor -*/ -MDNSResponder::clsMDNSAnswerAccessor::clsMDNSAnswerAccessor(const MDNSResponder::clsHost::stcQuery::stcAnswer* p_pAnswer) - : m_pAnswer(p_pAnswer) -{ - if ((m_pAnswer) && - (txtsAvailable())) - { - // Prepare m_TxtKeyValueMap - for (const clsHost::stcServiceTxt* pTxt = m_pAnswer->m_Txts.m_pTxts; pTxt; pTxt = pTxt->m_pNext) - { - m_TxtKeyValueMap.emplace(std::pair<const char*, const char*>(pTxt->m_pcKey, pTxt->m_pcValue)); - } - } -} - -/* - MDNSResponder::clsMDNSAnswerAccessor::~clsMDNSAnswerAccessor destructor -*/ -MDNSResponder::clsMDNSAnswerAccessor::~clsMDNSAnswerAccessor(void) -{ -} - -/** - MDNSResponder::clsMDNSAnswerAccessor::stcCompareTxtKey -*/ - -/* - MDNSResponder::clsMDNSAnswerAccessor::stcCompareTxtKey::operator() -*/ -bool MDNSResponder::clsMDNSAnswerAccessor::stcCompareTxtKey::operator()(char const* p_pA, - char const* p_pB) const -{ - return (0 > strcasecmp(p_pA, p_pB)); -} - -/* - MDNSResponder::clsMDNSAnswerAccessor::serviceDomainAvailable -*/ -bool MDNSResponder::clsMDNSAnswerAccessor::serviceDomainAvailable(void) const -{ - return ((m_pAnswer) && - (m_pAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::ServiceDomain))); -} - -/* - MDNSResponder::clsMDNSAnswerAccessor::serviceDomain -*/ -const char* MDNSResponder::clsMDNSAnswerAccessor::serviceDomain(void) const -{ - return ((m_pAnswer) - ? m_pAnswer->m_ServiceDomain.c_str() - : 0); -} - -/* - MDNSResponder::clsMDNSAnswerAccessor::hostDomainAvailable -*/ -bool MDNSResponder::clsMDNSAnswerAccessor::hostDomainAvailable(void) const -{ - return ((m_pAnswer) && - (m_pAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain))); -} - -/* - MDNSResponder::clsMDNSAnswerAccessor::hostDomain -*/ -const char* MDNSResponder::clsMDNSAnswerAccessor::hostDomain(void) const -{ - return ((m_pAnswer) - ? m_pAnswer->m_HostDomain.c_str() - : 0); -} - -/* - MDNSResponder::clsMDNSAnswerAccessor::hostPortAvailable -*/ -bool MDNSResponder::clsMDNSAnswerAccessor::hostPortAvailable(void) const -{ - return ((m_pAnswer) && - (m_pAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::Port))); -} - -/* - MDNSResponder::clsMDNSAnswerAccessor::hostPort -*/ -uint16_t MDNSResponder::clsMDNSAnswerAccessor::hostPort(void) const -{ - return ((m_pAnswer) - ? (m_pAnswer->m_u16Port) - : 0); -} - -#ifdef MDNS_IPV4_SUPPORT -/* - MDNSResponder::clsMDNSAnswerAccessor::IPv4AddressAvailable -*/ -bool MDNSResponder::clsMDNSAnswerAccessor::IPv4AddressAvailable(void) const -{ - return ((m_pAnswer) && - (m_pAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address))); -} - -/* - MDNSResponder::clsMDNSAnswerAccessor::IPv4Addresses -*/ -std::vector<IPAddress> MDNSResponder::clsMDNSAnswerAccessor::IPv4Addresses(void) const -{ - std::vector<IPAddress> internalIP; - if ((m_pAnswer) && - (IPv4AddressAvailable())) - { - for (uint32_t u = 0; u < m_pAnswer->IPv4AddressCount(); ++u) - { - const clsHost::stcQuery::stcAnswer::stcIPAddress* pIPAddr = m_pAnswer->IPv4AddressAtIndex(u); - if (pIPAddr) - { - internalIP.emplace_back(pIPAddr->m_IPAddress); - } - } - } - return internalIP; -} -#endif - -#ifdef MDNS_IPV6_SUPPORT -/* - MDNSResponder::clsMDNSAnswerAccessor::IPv6AddressAvailable -*/ -bool MDNSResponder::clsMDNSAnswerAccessor::IPv6AddressAvailable(void) const -{ - return ((m_pAnswer) && - (m_pAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address))); -} - -/* - MDNSResponder::clsMDNSAnswerAccessor::IPv6Addresses -*/ -std::vector<IPAddress> MDNSResponder::clsMDNSAnswerAccessor::IPv6Addresses(void) const -{ - std::vector<IPAddress> internalIP; - if ((m_pAnswer) && - (IPv6AddressAvailable())) - { - for (uint32_t u = 0; u < m_pAnswer->IPv6AddressCount(); ++u) - { - const clsHost::stcQuery::stcAnswer::stcIPAddress* pIPAddr = m_pAnswer->IPv6AddressAtIndex(u); - if (pIPAddr) - { - internalIP.emplace_back(pIPAddr->m_IPAddress); - } - } - } - return internalIP; -} -#endif - -/* - MDNSResponder::clsMDNSAnswerAccessor::txtsAvailable -*/ -bool MDNSResponder::clsMDNSAnswerAccessor::txtsAvailable(void) const -{ - return ((m_pAnswer) && - (m_pAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts))); -} - -/* - MDNSResponder::clsMDNSAnswerAccessor::txts - - Returns all TXT items for the given service as a ';'-separated string. - If not already existing; the string is alloced, filled and attached to the answer. -*/ -const char* MDNSResponder::clsMDNSAnswerAccessor::txts(void) const -{ - return ((m_pAnswer) - ? m_pAnswer->m_Txts.c_str() - : 0); -} - -/* - MDNSResponder::clsMDNSAnswerAccessor::txtKeyValues -*/ -const MDNSResponder::clsMDNSAnswerAccessor::clsTxtKeyValueMap& MDNSResponder::clsMDNSAnswerAccessor::txtKeyValues(void) const -{ - return m_TxtKeyValueMap; -} - -/* - MDNSResponder::clsMDNSAnswerAccessor::txtValue -*/ -const char* MDNSResponder::clsMDNSAnswerAccessor::txtValue(const char* p_pcKey) const -{ - char* pcResult = 0; - - if (m_pAnswer) - { - for (const clsHost::stcServiceTxt* pTxt = m_pAnswer->m_Txts.m_pTxts; pTxt; pTxt = pTxt->m_pNext) - { - if ((p_pcKey) && - (0 == strcasecmp(pTxt->m_pcKey, p_pcKey))) - { - pcResult = pTxt->m_pcValue; - break; - } - } - } - return pcResult; -} - -/* - MDNSResponder::clsMDNSAnswerAccessor::printTo - **/ -size_t MDNSResponder::clsMDNSAnswerAccessor::printTo(Print& p_Print) const -{ - size_t stLen = 0; - const char* cpcI = " * "; - const char* cpcS = " "; - - stLen += p_Print.println(" * * * * *"); - if (hostDomainAvailable()) - { - stLen += p_Print.print(cpcI); - stLen += p_Print.print("Host domain: "); - stLen += p_Print.println(hostDomain()); - } -#ifdef MDNS_IPV4_SUPPORT - if (IPv4AddressAvailable()) - { - stLen += p_Print.print(cpcI); - stLen += p_Print.println("IPv4 address(es):"); - for (const IPAddress& addr : IPv4Addresses()) - { - stLen += p_Print.print(cpcI); - stLen += p_Print.print(cpcS); - stLen += p_Print.println(addr); - } - } -#endif -#ifdef MDNS_IPV6_SUPPORT - if (IPv6AddressAvailable()) - { - stLen += p_Print.print(cpcI); - stLen += p_Print.println("IPv6 address(es):"); - for (const IPAddress& addr : IPv6Addresses()) - { - stLen += p_Print.print(cpcI); - stLen += p_Print.print(cpcS); - stLen += p_Print.println(addr); - } - } -#endif - if (serviceDomainAvailable()) - { - stLen += p_Print.print(cpcI); - stLen += p_Print.print("Service domain: "); - stLen += p_Print.println(serviceDomain()); - } - if (hostPortAvailable()) - { - stLen += p_Print.print(cpcI); - stLen += p_Print.print("Host port: "); - stLen += p_Print.println(hostPort()); - } - if (txtsAvailable()) - { - stLen += p_Print.print(cpcI); - stLen += p_Print.print("TXTs:"); - for (auto const& x : txtKeyValues()) - { - stLen += p_Print.print(cpcI); - stLen += p_Print.print(cpcS); - stLen += p_Print.print(x.first); - stLen += p_Print.print("="); - stLen += p_Print.println(x.second); - } - } - stLen += p_Print.println(" * * * * *"); - - return stLen; -} - -/** - STATIC QUERIES -*/ - -/* - MDNSResponder::queryService - - Perform a (blocking) static service query. - The arrived answers can be queried by calling: - - answerHostName (or 'hostname') - - answerIP (or 'IP') - - answerPort (or 'port') - -*/ -uint32_t MDNSResponder::queryService(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService '_%s._%s.local'\n"), _DH(p_hMDNSHost), p_pcService, p_pcProtocol);); - - uint32_t u32Result = ((_validateMDNSHostHandle(p_hMDNSHost)) - ? (_NRH2Ptr(p_hMDNSHost)->queryService(p_pcService, p_pcProtocol, p_u16Timeout)) - : 0); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService '_%s._%s.local' returned %u hits!\n"), _DH(p_hMDNSHost), p_pcService, p_pcProtocol, u32Result);); - return u32Result; -} - -/* - MDNSResponder::queryHost - - Perform a (blocking) static host query. - The arrived answers can be queried by calling: - - answerHostName (or 'hostname') - - answerIP (or 'IP') - - answerPort (or 'port') - -*/ -uint32_t MDNSResponder::queryHost(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcHostName, - const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost '%s.local'\n"), _DH(p_hMDNSHost), p_pcHostName);); - - uint32_t u32Result = ((_validateMDNSHostHandle(p_hMDNSHost)) - ? (_NRH2Ptr(p_hMDNSHost)->queryHost(p_pcHostName, p_u16Timeout)) - : 0); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost '%s.local' returned %u hits!\n"), _DH(p_hMDNSHost), p_pcHostName, u32Result);); - return u32Result; -} - -/* - MDNSResponder::removeQuery - - Remove the last static query (and all answers). - -*/ -bool MDNSResponder::removeQuery(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_NRH2Ptr(p_hMDNSHost)->removeQuery())); -} - -/* - MDNSResponder::hasQuery - - Return 'true', if a static query is currently installed - -*/ -bool MDNSResponder::hasQuery(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (0 != _NRH2Ptr(p_hMDNSHost)->hasQuery())); -} - -/* - MDNSResponder::getQuery - - Return handle to the last static query - -*/ -MDNSResponder::hMDNSQuery MDNSResponder::getQuery(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - return (_validateMDNSHostHandle(p_hMDNSHost) - ? (hMDNSQuery)_NRH2Ptr(p_hMDNSHost)->getQuery() - : 0); -} - - -/* - MDNSResponder::answerAccessors -*/ -MDNSResponder::clsMDNSAnswerAccessorVector MDNSResponder::answerAccessors(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - hMDNSQuery hLegacyQuery = getQuery(p_hMDNSHost); - return ((hLegacyQuery) - ? answerAccessors(p_hMDNSHost, hLegacyQuery) - : clsMDNSAnswerAccessorVector()); -} - -/* - MDNSResponder::answerCount -*/ -uint32_t MDNSResponder::answerCount(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - hMDNSQuery hLegacyQuery = getQuery(p_hMDNSHost); - return ((hLegacyQuery) - ? answerCount(p_hMDNSHost, hLegacyQuery) - : 0); -} - -/* - MDNSResponder::answerAccessor -*/ -MDNSResponder::clsMDNSAnswerAccessor MDNSResponder::answerAccessor(const MDNSResponder::hMDNSHost p_hMDNSHost, - uint32_t p_u32AnswerIndex) -{ - hMDNSQuery hLegacyQuery = getQuery(p_hMDNSHost); - return ((hLegacyQuery) - ? answerAccessor(p_hMDNSHost, hLegacyQuery, p_u32AnswerIndex) - : clsMDNSAnswerAccessor(0)); -} - - - -#ifdef NOTUSED - -/* - MDNSResponder::answerHostName -*/ -const char* MDNSResponder::answerHostName(const MDNSResponder::hMDNSHost p_hMDNSHost, - const uint32_t p_u32AnswerIndex) -{ - const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); - stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); - - if ((pSQAnswer) && - (pSQAnswer->m_HostDomain.m_u16NameLength) && - (!pSQAnswer->m_pcHostDomain)) - { - char* pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); - if (pcHostDomain) - { - pSQAnswer->m_HostDomain.c_str(pcHostDomain); - } - } - return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); -} - -#ifdef MDNS_IPV4_SUPPORT -/* - MDNSResponder::answerIPv4 -*/ -IPAddress MDNSResponder::answerIPv4(const MDNSResponder::hMDNSHost p_hMDNSHost, - const uint32_t p_u32AnswerIndex) -{ - const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); - const stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); - const stcQuery::stcAnswer::stcIPv4Address* pIPv4Address = (((pSQAnswer) && (pSQAnswer->m_pIPv4Addresses)) ? pSQAnswer->IPv4AddressAtIndex(0) : 0); - return (pIPv4Address ? pIPv4Address->m_IPAddress : IPAddress()); -} -#endif - -#ifdef MDNS_IPV6_SUPPORT -/* - MDNSResponder::answerIPv6 -*/ -IPAddress MDNSResponder::answerIPv6(const MDNSResponder::hMDNSHost p_hMDNSHost, - const uint32_t p_u32AnswerIndex) -{ - const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); - const stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); - const stcQuery::stcAnswer::stcIPv6Address* pIPv6Address = (((pSQAnswer) && (pSQAnswer->m_pIPv6Addresses)) ? pSQAnswer->IPv6AddressAtIndex(0) : 0); - return (pIPv6Address ? pIPv6Address->m_IPAddress : IPAddress()); -} -#endif - -/* - MDNSResponder::answerPort -*/ -uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSHost p_hMDNSHost, - const uint32_t p_u32AnswerIndex) -{ - const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); - const stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->m_u16Port : 0); -} - -#endif - - -/** - DYNAMIC SERVICE QUERY -*/ - -/* - MDNSResponder::installServiceQuery - - Add a dynamic service query and a corresponding callback to the MDNS responder. - The callback will be called for every answer update. - The answers can also be queried by calling: - - answerServiceDomain - - answerHostDomain - - answerIPv4Address/answerIPv6Address - - answerPort - - answerTxts - -*/ -MDNSResponder::hMDNSQuery MDNSResponder::installServiceQuery(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcService, - const char* p_pcProtocol, - MDNSResponder::MDNSQueryCallbackFn p_fnCallback) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService '_%s._%s.local'\n"), _DH(p_hMDNSHost), p_pcService, p_pcProtocol);); - - hMDNSQuery hResult = ((_validateMDNSHostHandle(p_hMDNSHost)) - ? (_NRH2Ptr(p_hMDNSHost)->installServiceQuery(p_pcService, p_pcProtocol, [this, p_fnCallback](clsHost & p_rHost, - const clsHost::stcQuery & p_Query, - const clsHost::stcQuery::stcAnswer & p_Answer, - clsHost::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item - bool p_bSetContent)->void - { - if (p_fnCallback) - { - p_fnCallback(*this, (hMDNSHost)&p_rHost, (hMDNSQuery)&p_Query, clsMDNSAnswerAccessor(&p_Answer), p_QueryAnswerTypeFlags, p_bSetContent); - } - })) - : 0); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s installServiceQuery: %s for '_%s._%s.local'!\n\n"), _DH(p_hMDNSHost), (hResult ? "Succeeded" : "FAILED"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); - DEBUG_EX_ERR(if (!hResult) DEBUG_OUTPUT.printf_P(PSTR("%s installServiceQuery: FAILED for '_%s._%s.local'!\n\n"), _DH(p_hMDNSHost), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); - return hResult; -} - -/* - MDNSResponder::installHostQuery -*/ -MDNSResponder::hMDNSQuery MDNSResponder::installHostQuery(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcHostName, - MDNSResponder::MDNSQueryCallbackFn p_fnCallback) -{ - hMDNSQuery hResult = ((_validateMDNSHostHandle(p_hMDNSHost)) - ? (_NRH2Ptr(p_hMDNSHost)->installHostQuery(p_pcHostName, [this, p_fnCallback](clsHost & p_rHost, - const clsHost::stcQuery & p_Query, - const clsHost::stcQuery::stcAnswer & p_Answer, - clsHost::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item - bool p_bSetContent)->void - { - if (p_fnCallback) - { - p_fnCallback(*this, (hMDNSHost)&p_rHost, (hMDNSQuery)&p_Query, clsMDNSAnswerAccessor(&p_Answer), p_QueryAnswerTypeFlags, p_bSetContent); - } - })) - : 0); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s installHostQuery: %s for '%s.local'!\n\n"), _DH(p_hMDNSHost), (hResult ? "Succeeded" : "FAILED"), (p_pcHostName ? : "-"));); - DEBUG_EX_ERR(if (!hResult) DEBUG_OUTPUT.printf_P(PSTR("%s installHostQuery: FAILED for '%s.local'!\n\n"), _DH(p_hMDNSHost), (p_pcHostName ? : "-"));); - return hResult; -} - -/* - MDNSResponder::removeQuery - - Remove a dynamic query (and all collected answers) from the MDNS responder - -*/ -bool MDNSResponder::removeQuery(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && - (p_hMDNSQuery) && - (_NRH2Ptr(p_hMDNSHost)->removeQuery((clsHost::stcQuery*)p_hMDNSQuery))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeQuery: FAILED!\n"), _DH(p_hMDNSHost));); - return bResult; -} - -/* - MDNSResponder::answerAccessors -*/ -MDNSResponder::clsMDNSAnswerAccessorVector MDNSResponder::answerAccessors(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery) -{ - clsMDNSAnswerAccessorVector tempVector; - for (uint32_t u = 0; u < answerCount(p_hMDNSHost, p_hMDNSQuery); ++u) - { - clsHost::stcQuery::stcAnswer* pAnswer = 0; - if ((_validateMDNSHostHandle(p_hMDNSHost)) && - (p_hMDNSQuery) && - ((pAnswer = ((clsHost::stcQuery*)p_hMDNSQuery)->answerAtIndex(u)))) - { - tempVector.emplace_back(clsMDNSAnswerAccessor(pAnswer)); - //tempVector.emplace_back(*pAnswer); - } - } - return tempVector; -} - -/* - MDNSResponder::answerCount -*/ -uint32_t MDNSResponder::answerCount(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery) -{ - _validateMDNSHostHandle(p_hMDNSHost); - return ((clsHost::stcQuery*)p_hMDNSQuery)->answerCount(); -} - -/* - MDNSResponder::answerAccessor -*/ -MDNSResponder::clsMDNSAnswerAccessor MDNSResponder::answerAccessor(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - uint32_t p_u32AnswerIndex) -{ - clsHost::stcQuery::stcAnswer* pAnswer = (((_validateMDNSHostHandle(p_hMDNSHost)) && - (p_hMDNSQuery)) - ? ((clsHost::stcQuery*)p_hMDNSQuery)->answerAtIndex(p_u32AnswerIndex) - : 0); - return MDNSResponder::clsMDNSAnswerAccessor(pAnswer); -} - -#ifdef LATER -/* - MDNSResponder::hasAnswerServiceDomain -*/ -bool MDNSResponder::hasAnswerServiceDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::ServiceDomain))); -} - - /* - MDNSResponder::answerServiceDomain - - Returns the domain for the given service. - If not already existing, the string is allocated, filled and attached to the answer. - - */ - const char* MDNSResponder::answerServiceDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcServiceDomain (if not already done) - if ((pSQAnswer) && - (pSQAnswer->m_ServiceDomain.m_u16NameLength) && - (!pSQAnswer->m_pcServiceDomain)) -{ - - pSQAnswer->m_pcServiceDomain = pSQAnswer->allocServiceDomain(pSQAnswer->m_ServiceDomain.c_strLength()); - if (pSQAnswer->m_pcServiceDomain) - { - pSQAnswer->m_ServiceDomain.c_str(pSQAnswer->m_pcServiceDomain); - } - } - return (pSQAnswer ? pSQAnswer->m_pcServiceDomain : 0); -} - -/* - MDNSResponder::hasAnswerHostDomain -*/ -bool MDNSResponder::hasAnswerHostDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain))); -} - - /* - MDNSResponder::answerHostDomain - - Returns the host domain for the given service. - If not already existing, the string is allocated, filled and attached to the answer. - - */ - const char* MDNSResponder::answerHostDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcHostDomain (if not already done) - if ((pSQAnswer) && - (pSQAnswer->m_HostDomain.m_u16NameLength) && - (!pSQAnswer->m_pcHostDomain)) -{ - - pSQAnswer->m_pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); - if (pSQAnswer->m_pcHostDomain) - { - pSQAnswer->m_HostDomain.c_str(pSQAnswer->m_pcHostDomain); - } - } - return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); -} - -#ifdef MDNS_IPV4_SUPPORT -/* - MDNSResponder::hasAnswerIPv4Address -*/ -bool MDNSResponder::hasAnswerIPv4Address(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address))); -} - - /* - MDNSResponder::answerIPv4AddressCount - */ - uint32_t MDNSResponder::answerIPv4AddressCount(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->IPv4AddressCount() : 0); -} - - /* - MDNSResponder::answerIPv4Address - */ - IPAddress MDNSResponder::answerIPv4Address(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - stcQuery::stcAnswer::stcIPv4Address* pIPv4Address = (pSQAnswer ? pSQAnswer->IPv4AddressAtIndex(p_u32AddressIndex) : 0); - return (pIPv4Address ? pIPv4Address->m_IPAddress : IPAddress()); -} -#endif - -#ifdef MDNS_IPV6_SUPPORT - /* - MDNSResponder::hasAnswerIPv6Address - */ - bool MDNSResponder::hasAnswerIPv6Address(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address))); -} - - /* - MDNSResponder::answerIPv6AddressCount - */ - uint32_t MDNSResponder::answerIPv6AddressCount(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->IPv6AddressCount() : 0); -} - - /* - MDNSResponder::answerIPv6Address - */ - IPAddress MDNSResponder::answerIPv6Address(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - stcQuery::stcAnswer::stcIPv6Address* pIPv6Address = (pSQAnswer ? pSQAnswer->IPv6AddressAtIndex(p_u32AddressIndex) : 0); - return (pIPv6Address ? pIPv6Address->m_IPAddress : IPAddress()); -} -#endif - - /* - MDNSResponder::hasAnswerPort - */ - bool MDNSResponder::hasAnswerPort(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::Port))); -} - - /* - MDNSResponder::answerPort - */ - uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->m_u16Port : 0); -} - - /* - MDNSResponder::hasAnswerTxts - */ - bool MDNSResponder::hasAnswerTxts(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts))); -} - - /* - MDNSResponder::answerTxts - - Returns all TXT items for the given service as a ';'-separated string. - If not already existing; the string is alloced, filled and attached to the answer. - - */ - const char* MDNSResponder::answerTxts(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcTxts (if not already done) - if ((pSQAnswer) && - (pSQAnswer->m_Txts.m_pTxts) && - (!pSQAnswer->m_pcTxts)) -{ - - pSQAnswer->m_pcTxts = pSQAnswer->allocTxts(pSQAnswer->m_Txts.c_strLength()); - if (pSQAnswer->m_pcTxts) - { - pSQAnswer->m_Txts.c_str(pSQAnswer->m_pcTxts); - } - } - return (pSQAnswer ? pSQAnswer->m_pcTxts : 0); -} - - -/* - PROBING -*/ - -/* - MDNSResponder::setHostProbeResultCallback - - Set a callback for probe results. The callback is called, when probing - for the host domain failes or succeedes. - In the case of failure, the domain name should be changed via 'setHostName' - When succeeded, the host domain will be announced by the MDNS responder. - -*/ -bool MDNSResponder::setHostProbeResultCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, - MDNSResponder::MDNSHostProbeResultCallbackFn p_fnCallback) -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (((clsHost*)p_hMDNSHost)->m_HostProbeInformation.m_fnProbeResultCallback = p_fnCallback, true)); -} - - -/* - MISC -*/ - -/* - MDNSResponder::notifyNetIfChange - - Should be called, whenever the AP for the MDNS responder changes. - A bit of this is caught by the event callbacks installed in the constructor. - -*/ -bool MDNSResponder::notifyNetIfChange(netif* p_pNetIf) -{ - clsHost* pMDNSHost; - return (((pMDNSHost = _findHost(p_pNetIf))) && - (_restart(*pMDNSHost))); -} - -/* - MDNSResponder::update - - Should be called in every 'loop'. - -*/ -bool MDNSResponder::update(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_process(*(clsHost*)p_hMDNSHost, true))); -} - -/* - MDNSResponder::update (convenience) -*/ -bool MDNSResponder::update(void) -{ - bool bResult = true; - for (clsHost*& pMDNSHost : m_HostList) - { - if (!_process(*it, true)) - { - bResult = false; - } - } - return bResult; -} - -/* - MDNSResponder::announce (convenience) - - Should be called, if the 'configuration' changes. Mainly this will be changes in the TXT items... -*/ -bool MDNSResponder::announce(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_announce(*(clsHost*)p_hMDNSHost, true, true))); -} - -/* - MDNSResponder::announce (convenience) -*/ -bool MDNSResponder::announce(void) -{ - bool bResult = true; - for (clsHost*& pMDNSHost : m_HostList) - { - if (!_announce(*it, true, true)) - { - bResult = false; - } - } - return bResult; -} - -/* - MDNSResponder::enableArduino - - Enable the OTA update service. - -*/ -MDNSResponder::hMDNSService MDNSResponder::enableArduino(const MDNSResponder::hMDNSHost p_hMDNSHost, - uint16_t p_u16Port, - bool p_bAuthUpload /*= false*/) -{ - hMDNSService hService = addService(p_hMDNSHost, 0, "arduino", "tcp", p_u16Port); - if (hService) - { - if ((!addServiceTxt(p_hMDNSHost, hService, "tcp_check", "no")) || - (!addServiceTxt(p_hMDNSHost, hService, "ssh_upload", "no")) || - (!addServiceTxt(p_hMDNSHost, hService, "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD))) || - (!addServiceTxt(p_hMDNSHost, hService, "auth_upload", (p_bAuthUpload) ? "yes" : "no"))) - { - - removeService(p_hMDNSHost, hService); - hService = 0; - } - } - return hService; -} -#endif // LATER - -#ifdef __MDNS_USE_LEGACY - -/** - INTERFACE -*/ - -/** - MDNSResponder::MDNSResponder -*/ -MDNSResponder::MDNSResponder(void) - : m_pUDPContext(0) -{ -} - -/* - MDNSResponder::~MDNSResponder -*/ -MDNSResponder::~MDNSResponder(void) -{ - close(); -} - - -/* - MDNSResponder::getHost (netif) -*/ -MDNSResponder::hMDNSHost MDNSResponder::getHost(netif* p_pNetIf) const -{ - return (hMDNSHost)(p_pNetIf ? _findHost(p_pNetIf) : 0); -} - -/* - MDNSResponder::getHost (WiFiMode) -*/ -MDNSResponder::hMDNSHost MDNSResponder::getHost(WiFiMode_t p_WiFiMode) const -{ - hMDNSHost hResult = 0; - - if (WIFI_STA == p_WiFiMode) - { - hResult = getHost(netif_get_by_index(WIFI_STA)); - } - else if (WIFI_AP == p_WiFiMode) - { - hResult = getHost(netif_get_by_index(WIFI_AP)); - } - return hResult; -} - -/* - MDNSResponder::begin (hostname, netif, probe_callback) -*/ -MDNSResponder::hMDNSHost MDNSResponder::begin(const char* p_pcHostName, - netif* p_pNetIf, - MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s, netif: %u)\n"), _DH(), (p_pcHostName ? : "_"), (p_pNetIf ? netif_get_index(p_pNetIf) : 0));); - - return (hMDNSHost)_begin(p_pcHostName, p_pNetIf, p_fnCallback); -} - -/* - MDNSResponder::begin (hostname, probe_callback) -*/ -bool MDNSResponder::begin(const char* p_pcHostName, - MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s)\n"), _DH(), (p_pcHostName ? : "_"));); - - return begin(p_pcHostName, (WiFiMode_t)wifi_get_opmode(), p_fnCallback); -} - -/* - MDNSResponder::begin (hostname, WiFiMode, probe_callback) -*/ -bool MDNSResponder::begin(const char* p_pcHostName, - WiFiMode_t p_WiFiMode, - MDNSHostProbeResultCallbackFn p_fnCallback /*= 0*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s, opmode: %u)\n"), _DH(), (p_pcHostName ? : "_"), (uint32_t)p_WiFiMode);); - - bool bResult = true; - - if ((bResult) && - (p_WiFiMode & WIFI_STA)) - { - bResult = (0 != _begin(p_pcHostName, netif_get_by_index(WIFI_STA), p_fnCallback)); - } - if ((bResult) && - (p_WiFiMode & WIFI_AP)) - { - bResult = (0 != _begin(p_pcHostName, netif_get_by_index(WIFI_AP), p_fnCallback)); - } - return bResult; -} - -/* - MDNSResponder::close -*/ -bool MDNSResponder::close(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_close(*(clsHost*)p_hMDNSHost))); -} - -/* - MDNSResponder::close (convenience) -*/ -bool MDNSResponder::close(void) -{ - clsHostList::iterator it(m_HostList.begin()); - while (m_HostList.end() != it) - { - _close(**it++); - } - - _releaseUDPContext(); - - return true; -} - -/* - MDNSResponder::end (ESP32) -*/ -bool MDNSResponder::end(void) -{ - return close(); -} - -/* - MDNSResponder::setHostName -*/ -bool MDNSResponder::setHostName(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcHostName) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_setHostName(*(clsHost*)p_hMDNSHost, p_pcHostName))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setHostName: FAILED for '%s'!\n"), _DH(), (p_pcHostName ? : "-"));); - return bResult; -} - -/* - MDNSResponder::setHostname (LEGACY 2) - - Set the host name in all netif bindings - -*/ -bool MDNSResponder::setHostname(const char* p_pcHostName) -{ - bool bResult = true; - for (clsHost*& pMDNSHost : m_HostList) - { - if (!setHostName((hMDNSHost)pMDNSHost, p_pcHostName)) - { - bResult = false; - } - } - return bResult; -} - -/* - MDNSResponder::setHostname (LEGACY) -*/ -bool MDNSResponder::setHostname(String p_strHostName) -{ - return setHostname(p_strHostName.c_str()); -} - -/* - MDNSResponder::hostName -*/ -const char* MDNSResponder::hostName(const MDNSResponder::hMDNSHost p_hMDNSHost) const -{ - return (_validateMDNSHostHandle(p_hMDNSHost) - ? (((clsHost*)p_hMDNSHost)->m_pcHostName) - : 0); -} - -/* - MDNSResponder::hostname (LEGACY 2) -*/ -const char* MDNSResponder::hostname(void) const -{ - return ((!m_HostList.empty()) - ? hostName((hMDNSHost)m_HostList.front()) - : 0); -} - -/* - MDNSResponder::status -*/ -bool MDNSResponder::status(const MDNSResponder::hMDNSHost p_hMDNSHost) const -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (enuProbingStatus::Done == ((clsHost*)p_hMDNSHost)->m_HostProbeInformation.m_ProbingStatus)); -} - -/* - MDNSResponder::status (LEGACY 2) -*/ -bool MDNSResponder::status(void) const -{ - bool bResult = true; - for (clsHost * const& pMDNSHost : m_HostList) - { - if (!((bResult = status((hMDNSHost)pMDNSHost)))) - { - break; - } - } - return bResult; -} - - -/* - SERVICES -*/ - -/* - MDNSResponder::setInstanceName -*/ -bool MDNSResponder::setInstanceName(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcInstanceName) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_setInstanceName(*(clsHost*)p_hMDNSHost, p_pcInstanceName))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setInstanceName: FAILED for '%s'!\n"), _DH(), (p_pcInstanceName ? : "-"));); - return bResult; -} - -/* - MDNSResponder::setInstanceName (LEGACY 2) - - Set the instance name in all netif bindings - -*/ -bool MDNSResponder::setInstanceName(const char* p_pcInstanceName) -{ - bool bResult = true; - for (clsHost*& pMDNSHost : m_HostList) - { - if (!setInstanceName((hMDNSHost)pMDNSHost, p_pcInstanceName)) - { - bResult = false; - } - } - return bResult; -} - -/* - MDNSResponder::setInstanceName (LEGACY 2) -*/ -bool MDNSResponder::setInstanceName(const String& p_strInstanceName) -{ - return setInstanceName(p_strInstanceName.c_str()); -} - -/* - MDNSResponder::addService - - Add service; using hostname if no name is explicitly provided for the service - The usual '_' underline, which is prepended to service and protocol, eg. _http, - may be given. If not, it is added automatically. - -*/ -MDNSResponder::hMDNSService MDNSResponder::addService(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port) -{ - hMDNSService hService = (_validateMDNSHostHandle(p_hMDNSHost) - ? (hMDNSService)_addService(*(clsHost*)p_hMDNSHost, p_pcName, p_pcService, p_pcProtocol, p_u16Port) - : 0); - DEBUG_EX_ERR(if (!hService) DEBUG_OUTPUT.printf_P(PSTR("%s addService: FAILED for '%s._%s._%s.local'!\n"), _DH((clsHost*)p_hMDNSHost), (p_pcName ? : "-"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); - return hService; -} - -/* - MDNSResponder::addService (LEGACY 2) - - Add a service to all netif bindings. - (Only) the first service (handle) is returned. - -*/ -MDNSResponder::hMDNSService MDNSResponder::addService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port) -{ - hMDNSService hResult = 0; - for (clsHost*& pMDNSHost : m_HostList) - { - hMDNSService hNewService = addService((hMDNSHost)pMDNSHost, p_pcName, p_pcService, p_pcProtocol, p_u16Port); - if (!hResult) - { - hResult = hNewService; - } - } - return hResult; -} - -/* - MDNSResponder::removeService - - Unanounce a service (by sending a goodbye message) and remove it - from the MDNS responder - -*/ -bool MDNSResponder::removeService(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && - (_removeService(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeService: FAILED!\n"), _DH((clsHost*)p_hMDNSHost));); - return bResult; -} - -/* - MDNSResponder::removeService (LEGACY 2) - - Find and remove the service from one netif binding -*/ -bool MDNSResponder::removeService(const MDNSResponder::hMDNSService p_hMDNSService) -{ - clsHost* pHost = 0; - return ((_validateMDNSHostHandle(p_hMDNSService, &pHost)) && - (removeService((hMDNSHost)pHost, p_hMDNSService))); -} - -/* - MDNSResponder::removeService -*/ -bool MDNSResponder::removeService(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol) -{ - clsHost* pMDNSHost; - stcService* pMDNSService; - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && - (pMDNSHost = (clsHost*)p_hMDNSHost) && - ((pMDNSService = _findService(*pMDNSHost, (p_pcName ? : (pMDNSHost->m_pcInstanceName ? : pMDNSHost->m_pcHostName)), p_pcService, p_pcProtocol))) && - (_removeService(*(clsHost*)p_hMDNSHost, *pMDNSService))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeService: FAILED for '%s._%s._%s.local'!\n"), _DH((clsHost*)p_hMDNSHost), (p_pcName ? : "-"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); - return bResult; -} - -/* - MDNSResponder::removeService (LEGACY 2) -*/ -bool MDNSResponder::removeService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol) -{ - bool bResult = true; - - for (clsHost*& pMDNSHost : m_HostList) - { - if (!removeService((hMDNSHost)pMDNSHost, p_pcName, p_pcService, p_pcProtocol)) - { - bResult = false; - } - } - return bResult; -} - -/* - MDNSResponder::addService (LEGACY) -*/ -bool MDNSResponder::addService(String p_strService, - String p_strProtocol, - uint16_t p_u16Port) -{ - return (0 != addService(0, p_strService.c_str(), p_strProtocol.c_str(), p_u16Port)); -} - -/* - MDNSResponder::findService - - Find an existing service. - -*/ -MDNSResponder::hMDNSService MDNSResponder::findService(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol) -{ - clsHost* pMDNSHost; - return (((_validateMDNSHostHandle(p_hMDNSHost)) && - (pMDNSHost = (clsHost*)p_hMDNSHost)) - ? _findService(*pMDNSHost, (p_pcName ? : (pMDNSHost->m_pcInstanceName ? : pMDNSHost->m_pcHostName)), p_pcService, p_pcProtocol) - : 0); -} - -/* - MDNSResponder::findService (LEGACY 2) - - (Only) the first service handle is returned. - -*/ -MDNSResponder::hMDNSService MDNSResponder::findService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol) -{ - hMDNSService hResult = 0; - for (clsHost*& pMDNSHost : m_HostList) - { - if ((hResult = findService((hMDNSHost)pMDNSHost, p_pcName, p_pcService, p_pcProtocol))) - { - break; - } - } - return hResult; -} - -/* - MDNSResponder::setServiceName -*/ -bool MDNSResponder::setServiceName(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcInstanceName) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && - (_setServiceName(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService, p_pcInstanceName))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setServiceName: FAILED for '%s'!\n"), _DH((clsHost*)p_hMDNSHost), (p_pcInstanceName ? : "-"));); - return bResult; -} - -/* - MDNSResponder::setServiceName (LEGACY 2) -*/ -bool MDNSResponder::setServiceName(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcInstanceName) -{ - clsHost* pHost = 0; - return ((_validateMDNSServiceHandle(p_hMDNSService, &pHost)) && - (setServiceName((hMDNSHost)pHost, p_hMDNSService, p_pcInstanceName))); -} - -/* - MDNSResponder::serviceName -*/ -const char* MDNSResponder::serviceName(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const -{ - return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) - ? ((stcService*)p_hMDNSService)->m_pcName - : 0); -} - -/* - MDNSResponder::serviceName (LEGACY 2) -*/ -const char* MDNSResponder::serviceName(const hMDNSService p_hMDNSService) const -{ - clsHost* pHost = 0; - return (_validateMDNSServiceHandle(p_hMDNSService, &pHost) - ? serviceName((hMDNSHost)pHost, p_hMDNSService) - : 0); -} - -/* - MDNSResponder::service -*/ -const char* MDNSResponder::service(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const -{ - return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) - ? ((stcService*)p_hMDNSService)->m_pcService - : 0); -} - -/* - MDNSResponder::service (LEGACY 2) -*/ -const char* MDNSResponder::service(const hMDNSService p_hMDNSService) const -{ - clsHost* pHost = 0; - return (_validateMDNSServiceHandle(p_hMDNSService, &pHost) - ? service((hMDNSHost)pHost, p_hMDNSService) - : 0); -} - -/* - MDNSResponder::serviceProtocol -*/ -const char* MDNSResponder::serviceProtocol(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const -{ - return (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) - ? ((stcService*)p_hMDNSService)->m_pcProtocol - : 0); -} - -/* - MDNSResponder::serviceProtocol (LEGACY) -*/ -const char* MDNSResponder::serviceProtocol(const hMDNSService p_hMDNSService) const -{ - clsHost* pHost = 0; - return (_validateMDNSServiceHandle(p_hMDNSService, &pHost) - ? serviceProtocol((hMDNSHost)pHost, p_hMDNSService) - : 0); -} - -/* - MDNSResponder::serviceStatus -*/ -bool MDNSResponder::serviceStatus(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const -{ - return ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && - (enuProbingStatus::Done == ((stcService*)p_hMDNSService)->m_ProbeInformation.m_ProbingStatus)); -} - -/* - MDNSResponder::serviceStatus (LEGACY 2) - - Returns 'true' if probing for the service 'hMDNSService' is done - -*/ -bool MDNSResponder::serviceStatus(const hMDNSService p_hMDNSService) const -{ - clsHost* pHost = 0; - return (_validateMDNSServiceHandle(p_hMDNSService, &pHost) - ? serviceStatus((hMDNSHost)pHost, p_hMDNSService) - : false); -} - - -/* - SERVICE TXT -*/ - -/* - MDNSResponder::addServiceTxt - - Add a static service TXT item ('Key'='Value') to a service. - -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - const char* p_pcValue) -{ - hMDNSTxt hTxt = (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) - ? (hMDNSTxt)_addServiceTxt((clsHost*)p_hMDNSHost, (stcService*)p_hMDNSService, p_pcKey, p_pcValue, false) - : 0); - DEBUG_EX_ERR(if (!hTxt) DEBUG_OUTPUT.printf_P(PSTR("%s addServiceTxt: FAILED for '%s=%s'!\n"), _DH(), (p_pcKey ? : "-"), (p_pcValue ? : "-"));); - return hTxt; -} - -/* - MDNSResponder::addServiceTxt (LEGACY 2) - - Add a static service TXT item ('Key'='Value') to a service. - -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - const char* p_pcValue) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_pcValue) - : 0); -} - -/* - MDNSRESPONDER_xxx_TO_CHAR - Formats: http://www.cplusplus.com/reference/cstdio/printf/ -*/ -#define MDNSRESPONDER_U32_TO_CHAR(BUFFERNAME, U32VALUE) \ - char BUFFERNAME[16]; /* 32-bit max 10 digits */ \ - *BUFFERNAME = 0; \ - sprintf(BUFFERNAME, "%u", U32VALUE); -#define MDNSRESPONDER_U16_TO_CHAR(BUFFERNAME, U16VALUE) \ - char BUFFERNAME[8]; /* 16-bit max 5 digits */ \ - *BUFFERNAME = 0; \ - sprintf(BUFFERNAME, "%hu", U16VALUE); -#define MDNSRESPONDER_U8_TO_CHAR(BUFFERNAME, U8VALUE) \ - char BUFFERNAME[8]; /* 8-bit max 3 digits */ \ - *BUFFERNAME = 0; \ - sprintf(BUFFERNAME, "%hhu", U8VALUE); -#define MDNSRESPONDER_I32_TO_CHAR(BUFFERNAME, I32VALUE) \ - char BUFFERNAME[16]; /* 32-bit max 10 digits */ \ - *BUFFERNAME = 0; \ - sprintf(BUFFERNAME, "%i", I32VALUE); -#define MDNSRESPONDER_I16_TO_CHAR(BUFFERNAME, I16VALUE) \ - char BUFFERNAME[8]; /* 16-bit max 5 digits */ \ - *BUFFERNAME = 0; \ - sprintf(BUFFERNAME, "%hi", I16VALUE); -#define MDNSRESPONDER_I8_TO_CHAR(BUFFERNAME, I8VALUE) \ - char BUFFERNAME[8]; /* 8-bit max 3 digits */ \ - *BUFFERNAME = 0; \ - sprintf(BUFFERNAME, "%hhi", I8VALUE); - - -/* - MDNSResponder::addServiceTxt (uint32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - MDNSRESPONDER_U32_TO_CHAR(acBuffer, p_u32Value); - return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): - } - - /* - MDNSResponder::addServiceTxt (uint32_t) (LEGACY 2) - */ - MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_u32Value) - : 0); -} - -/* - MDNSResponder::addServiceTxt (uint16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - MDNSRESPONDER_U16_TO_CHAR(acBuffer, p_u16Value); - return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): - } - - /* - MDNSResponder::addServiceTxt (uint16_t) (LEGACY 2) - */ - MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_u16Value) - : 0); -} - -/* - MDNSResponder::addServiceTxt (uint8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - MDNSRESPONDER_U8_TO_CHAR(acBuffer, p_u8Value); - return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): - } - - /* - MDNSResponder::addServiceTxt (uint8_t) (LEGACY 2) - */ - MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_u8Value) - : 0); -} - -/* - MDNSResponder::addServiceTxt (int32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int32_t p_i32Value) -{ - MDNSRESPONDER_I32_TO_CHAR(acBuffer, p_i32Value); - return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): - } - - /* - MDNSResponder::addServiceTxt (int32_t) (LEGACY 2) - */ - MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int32_t p_i32Value) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_i32Value) - : 0); -} - -/* - MDNSResponder::addServiceTxt (int16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int16_t p_i16Value) -{ - MDNSRESPONDER_I16_TO_CHAR(acBuffer, p_i16Value); - return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): - } - - /* - MDNSResponder::addServiceTxt (int16_t) (LEGACY 2) - */ - MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int16_t p_i16Value) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_i16Value) - : 0); -} - -/* - MDNSResponder::addServiceTxt (int8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int8_t p_i8Value) -{ - MDNSRESPONDER_I8_TO_CHAR(acBuffer, p_i8Value); - return addServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): - } - - /* - MDNSResponder::addServiceTxt (int8_t) (LEGACY 2) - */ - MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int8_t p_i8Value) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_i8Value) - : 0); -} - -/* - MDNSResponder::removeServiceTxt - - Remove a static service TXT item from a service. -*/ -bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const MDNSResponder::hMDNSTxt p_hTxt) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && - (p_hTxt) && - (_findServiceTxt(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService, p_hTxt)) && - (_releaseServiceTxt(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService, (stcServiceTxt*)p_hTxt))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeServiceTxt: FAILED!\n"), _DH((clsHost*)p_hMDNSHost));); - return bResult; -} - -/* - MDNSResponder::removeServiceTxt (LEGACY 2) -*/ -bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const MDNSResponder::hMDNSTxt p_hTxt) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? removeServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_hTxt) - : false); -} - -/* - MDNSResponder::removeServiceTxt -*/ -bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey) -{ - stcServiceTxt* pTxt; - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && - (p_pcKey) && - ((pTxt = _findServiceTxt(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService, p_pcKey))) && - (_releaseServiceTxt(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService, pTxt))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeServiceTxt: FAILED!\n"), _DH((clsHost*)p_hMDNSHost));); - return bResult; -} - -/* - MDNSResponder::removeServiceTxt (LEGACY 2) -*/ -bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? removeServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey) - : false); -} - -/* - MDNSResponder::removeServiceTxt (LEGACY) -*/ -bool MDNSResponder::removeServiceTxt(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - const char* p_pcKey) -{ - hMDNSService hService; - return (((hService = findService(p_pcName, p_pcService, p_pcProtocol))) - ? removeServiceTxt(hService, p_pcKey) - : false); -} - -/* - MDNSResponder::addServiceTxt (LEGACY) -*/ -bool MDNSResponder::addServiceTxt(const char* p_pcService, - const char* p_pcProtocol, - const char* p_pcKey, - const char* p_pcValue) -{ - hMDNSService hService; - return (((hService = findService(p_pcName, p_pcService, p_pcProtocol))) - ? addServiceTxt(hService, p_pcKey, p_pcValue) - : false); -} - -/* - MDNSResponder::addServiceTxt (LEGACY) -*/ -bool MDNSResponder::addServiceTxt(String p_strService, - String p_strProtocol, - String p_strKey, - String p_strValue) -{ - return addServiceTxt(p_strService.c_str(), p_strProtocol.c_str(), p_strKey.c_str(), p_strValue.c_str()); -} - -/* - MDNSResponder::setDynamicServiceTxtCallback (binding) - - Set a netif binding specific callback for dynamic service TXT items. The callback is called, whenever - service TXT items are needed for any service on the netif binding. - -*/ -bool MDNSResponder::setDynamicServiceTxtCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, - MDNSResponder::MDNSDynamicServiceTxtCallbackFn p_fnCallback) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && - ((!p_fnCallback) || - ((((clsHost*)p_hMDNSHost)->m_fnServiceTxtCallback = p_fnCallback)))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setDynamicServiceTxtCallback: FAILED!\n"), _DH((clsHost*)p_hMDNSHost));); - return bResult; -} - -/* - MDNSResponder::setDynamicServiceTxtCallback (service) - - Set a service specific callback for dynamic service TXT items. The callback is called, whenever - service TXT items are needed for the given service. -*/ -bool MDNSResponder::setDynamicServiceTxtCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - MDNSResponder::MDNSDynamicServiceTxtCallbackFn p_fnCallback) -{ - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && - ((!p_fnCallback) || - ((((stcService*)p_hMDNSService)->m_fnServiceTxtCallback = p_fnCallback)))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s setDynamicServiceTxtCallback: FAILED!\n"), _DH((clsHost*)p_hMDNSHost));); - return bResult; -} - -/* - MDNSResponder::setDynamicServiceTxtCallback (global) (LEGACY 2) - - Set a global callback for dynamic service TXT items. The callback is called, whenever - service TXT items are needed. - -*/ -bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::MDNSDynamicServiceTxtCallbackFn1 p_fnCallback) -{ - for (clsHostList : .iterator it : m_HostList) - { - setDynamicServiceTxtCallback((hMDNSHost)it, p_fnCallback); - } - return true; -} - -/* - MDNSResponder::setDynamicServiceTxtCallback (global) (LEGACY 2 (Fn2)) -*/ -bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::MDNSDynamicServiceTxtCallbackFn2 p_fnCallback) -{ - return setDynamicServiceTxtCallback([p_fnCallback](MDNSResponder*, const hMDNSService p_hMDNSService) - { - if (p_fnCallback) - { - p_fnCallback(p_hMDNSService); - } - }); -} - -/* - MDNSResponder::setDynamicServiceTxtCallback (service) (LEGACY 2) -*/ -bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::hMDNSService p_hMDNSService, - MDNSResponder::MDNSDynamicServiceTxtCallbackFn1 p_fnCallback) -{ - clsHost* pHost; - return ((_validateMDNSHostHandle(p_hMDNSService, &pHost)) && - (setDynamicServiceTxtCallback((hMDNSHost)pHost, hMDNSService, p_fnCallback))); -} - -/* - MDNSResponder::setDynamicServiceTxtCallback (service) (LEGACY 2 (Fn2)) -*/ -bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::hMDNSService p_hMDNSService, - MDNSResponder::MDNSDynamicServiceTxtCallbackFn2 p_fnCallback) -{ - return setDynamicServiceTxtCallback(p_hMDNSService, [p_fnCallback](MDNSResponder*, const hMDNSService p_hMDNSService) - { - if (p_fnCallback) - { - p_fnCallback(p_hMDNSService); - } - }); -} - -/* - MDNSResponder::addDynamicServiceTxt -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - const char* p_pcValue) -{ - hMDNSTxt hTxt = (_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService) - ? _addServiceTxt(*(clsHost*)p_hMDNSHost, *(stcService*)p_hMDNSService, p_pcKey, p_pcValue, true) - : 0); - DEBUG_EX_ERR(if (!hTxt) DEBUG_OUTPUT.printf_P(PSTR("%s addDynamicServiceTxt: FAILED for '%s=%s'!\n"), _DH(), (p_pcKey ? : "-"), (p_pcValue ? : "-"));); - return hTxt; -} - -/* - MDNSResponder::addDynamicServiceTxt (LEGACY 2) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - const char* p_pcValue) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_pcValue) - : 0); -} - -/* - MDNSResponder::addDynamicServiceTxt (uint32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - MDNSRESPONDER_U32_TO_CHAR(acBuffer, p_u32Value); - return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): - } - - /* - MDNSResponder::addDynamicServiceTxt (uint32_t) (LEGACY 2) - */ - MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_u32Value) - : 0); -} - -/* - MDNSResponder::addDynamicServiceTxt (uint16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - MDNSRESPONDER_U16_TO_CHAR(acBuffer, p_u16Value); - return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): - } - - /* - MDNSResponder::addDynamicServiceTxt (uint16_t) (LEGACY 2) - */ - MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_u16Value) - : 0); -} - -/* - MDNSResponder::addDynamicServiceTxt (uint8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - MDNSRESPONDER_U8_TO_CHAR(acBuffer, p_u8Value); - return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): - } - - /* - MDNSResponder::addDynamicServiceTxt (uint8_t) (LEGACY 2) - */ - MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_u8Value) - : 0); -} - -/* - MDNSResponder::addDynamicServiceTxt (int32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int32_t p_i32Value) -{ - MDNSRESPONDER_I32_TO_CHAR(acBuffer, p_i32Value); - return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): - } - - /* - MDNSResponder::addDynamicServiceTxt (int32_t) (LEGACY 2) - */ - MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint32_t p_i32Value) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_i32Value) - : 0); -} - -/* - MDNSResponder::addDynamicServiceTxt (int16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int16_t p_i16Value) -{ - MDNSRESPONDER_I16_TO_CHAR(acBuffer, p_i16Value); - return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): - } - - /* - MDNSResponder::addDynamicServiceTxt (int16_t) (LEGACY 2) - */ - MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint16_t p_i16Value) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_i16Value) - : 0); -} - -/* - MDNSResponder::addDynamicServiceTxt (int8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - int8_t p_i8Value) -{ - MDNSRESPONDER_I8_TO_CHAR(acBuffer, p_i8Value); - return addDynamicServiceTxt(p_hMDNSHost, p_hMDNSService, p_pcKey, acBuffer): - } - - /* - MDNSResponder::addDynamicServiceTxt (int8_t) (LEGACY 2) - */ - MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(const MDNSResponder::hMDNSService p_hMDNSService, - const char* p_pcKey, - uint8_t p_i8Value) -{ - clsHost* pHost = 0; - return (_validateMDNSHostHandle(p_hMDNSService, &pHost) - ? addDynamicServiceTxt((hMDNSHost)pHost, p_hMDNSService, p_pcKey, p_i8Value) - : 0); -} - - -/** - STATIC QUERIES -*/ - -/* - MDNSResponder::queryService - - Perform a (blocking) static service query. - The arrived answers can be queried by calling: - - answerHostName (or 'hostname') - - answerIP (or 'IP') - - answerPort (or 'port') - -*/ -uint32_t MDNSResponder::queryService(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService '%s.%s'\n"), _DH(), p_pcService, p_pcProtocol);); - - uint32_t u32Result = 0; - - stcQuery* pMDNSQuery = 0; - if ((_validateMDNSHostHandle(p_hMDNSHost)) && - (p_pcService) && - (os_strlen(p_pcService)) && - (p_pcProtocol) && - (os_strlen(p_pcProtocol)) && - (p_u16Timeout) && - (_removeLegacyQuery()) && - ((pMDNSQuery = _allocQuery(*(clsHost*)p_hMDNSHost, stcQuery::enuQueryType::Service))) && - (_buildDomainForService(p_pcService, p_pcProtocol, pMDNSQuery->m_Domain))) - { - pMDNSQuery->m_bLegacyQuery = true; - - if (_sendMDNSQuery(*(clsHost*)p_hMDNSHost, *pMDNSQuery)) - { - // Wait for answers to arrive - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); - delay(p_u16Timeout); - - // All answers should have arrived by now -> stop adding new answers - pMDNSQuery->m_bAwaitingAnswers = false; - u32Result = pMDNSQuery->answerCount(); - } - else // FAILED to send query - { - _removeQuery(*(clsHost*)p_hMDNSHost, pMDNSQuery); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: INVALID input data!\n"), _DH());); - } - return u32Result; -} - -/* - MDNSResponder::queryService (LEGACY 2) -*/ -uint32_t MDNSResponder::queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) -{ - return ((!m_HostList.empty()) - ? queryService((hMDNSHost)m_HostList.front(), p_pcService, p_pcProtocol, p_u16Timeout) - : 0); -} - -/* - MDNSResponder::queryService (LEGACY) -*/ -uint32_t MDNSResponder::queryService(const String& p_strService, - const String& p_strProtocol) -{ - return queryService(p_strService.c_str(), p_strProtocol.c_str()); -} - -/* - MDNSResponder::queryHost - - Perform a (blocking) static host query. - The arrived answers can be queried by calling: - - answerHostName (or 'hostname') - - answerIP (or 'IP') - - answerPort (or 'port') - -*/ -uint32_t MDNSResponder::queryHost(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcHostName, - const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost '%s.local'\n"), _DH(), p_pcHostName);); - - uint32_t u32Result = 0; - - stcQuery* pHostQuery = 0; - if ((_validateMDNSHostHandle(p_hMDNSHost)) && - (p_pcHostName) && - (os_strlen(p_pcHostName)) && - (p_u16Timeout) && - (_removeLegacyQuery()) && - ((pHostQuery = _allocQuery(*(clsHost*)p_hMDNSHost, stcQuery::enuQueryType::Host))) && - (_buildDomainForHost(p_pcHostName, pHostQuery->m_Domain))) - { - - pHostQuery->m_bLegacyQuery = true; - - if (_sendMDNSQuery(*(clsHost*)p_hMDNSHost, *pHostQuery)) - { - // Wait for answers to arrive - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); - delay(p_u16Timeout); - - // All answers should have arrived by now -> stop adding new answers - pHostQuery->m_bAwaitingAnswers = false; - u32Result = pHostQuery->answerCount(); - } - else // FAILED to send query - { - _removeQuery(*(clsHost*)p_hMDNSHost, pHostQuery); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: INVALID input data!\n"), _DH());); - } - return u32Result; -} - -/* - queryHost (LEGACY 2) -*/ -uint32_t MDNSResponder::queryHost(const char* p_pcHostName, - const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) -{ - return ((!m_HostList.empty()) - ? queryHost((hMDNSHost)m_HostList.front(), p_pcService, p_pcProtocol, p_u16Timeout) - : 0); -} - -/* - MDNSResponder::removeQuery - - Remove the last static query (and all answers). - -*/ -bool MDNSResponder::removeQuery(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_removeLegacyQuery(*(clsHost*)p_hMDNSHost))); -} - -/* - MDNSResponder::removeQuery (LEGACY 2) -*/ -bool MDNSResponder::removeQuery(void) -{ - return ((!m_HostList.empty()) - ? removeQuery((hMDNSHost)m_HostList.front()) - : false); -} - -/* - MDNSResponder::hasQuery - - Return 'true', if a static query is currently installed - -*/ -bool MDNSResponder::hasQuery(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (0 != _findLegacyQuery(*(clsHost*)p_hMDNSHost))); -} - -/* - MDNSResponder::hasQuery (LEGACY 2) -*/ -bool MDNSResponder::hasQuery(void) -{ - return ((!m_HostList.empty()) - ? hasQuery((hMDNSHost)m_HostList.front()) - : false); -} - -/* - MDNSResponder::getQuery - - Return handle to the last static query - -*/ -MDNSResponder::hMDNSQuery MDNSResponder::getQuery(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - return (_validateMDNSHostHandle(p_hMDNSHost) - ? (hMDNSQuery)_findLegacyQuery() - : 0); -} - -/* - MDNSResponder::getQuery (LEGACY 2) -*/ -MDNSResponder::hMDNSQuery MDNSResponder::getQuery(void) -{ - return ((!m_HostList.empty()) - ? getQuery((hMDNSHost)m_HostList.front()) - : false); -} - -/* - MDNSResponder::answerHostName -*/ -const char* MDNSResponder::answerHostName(const MDNSResponder::hMDNSHost p_hMDNSHost, - const uint32_t p_u32AnswerIndex) -{ - const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); - stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); - - if ((pSQAnswer) && - (pSQAnswer->m_HostDomain.m_u16NameLength) && - (!pSQAnswer->m_pcHostDomain)) - { - char* pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); - if (pcHostDomain) - { - pSQAnswer->m_HostDomain.c_str(pcHostDomain); - } - } - return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); -} - -/* - MDNSResponder::answerHostName (LEGACY 2) -*/ -const char* MDNSResponder::answerHostName(const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? answerHostName((hMDNSHost)m_HostList.front(), p_u32AnswerIndex) - : 0); -} - -/* - MDNSResponder::hostname (LEGACY) -*/ -String MDNSResponder::hostname(const uint32_t p_u32AnswerIndex) -{ - return String(answerHostName(p_u32AnswerIndex)); -} - -#ifdef MDNS_IPV4_SUPPORT -/* - MDNSResponder::answerIPv4 -*/ -IPAddress MDNSResponder::answerIPv4(const MDNSResponder::hMDNSHost p_hMDNSHost, - const uint32_t p_u32AnswerIndex) -{ - const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); - const stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); - const stcQuery::stcAnswer::stcIPv4Address* pIPv4Address = (((pSQAnswer) && (pSQAnswer->m_pIPv4Addresses)) ? pSQAnswer->IPv4AddressAtIndex(0) : 0); - return (pIPv4Address ? pIPv4Address->m_IPAddress : IPAddress()); -} - -/* - MDNSResponder::answerIPv4 (LEGACY 2) -*/ -IPAddress MDNSResponder::answerIPv4(const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? answerIPv4((hMDNSHost)m_HostList.front(), p_u32AnswerIndex) - : IPAddress()); -} - -/* - MDNSResponder::answerIP (LEGACY 2) -*/ -IPAddress MDNSResponder::answerIP(const uint32_t p_u32AnswerIndex) -{ - return answerIPv4(p_u32AnswerIndex); -} - -/* - MDNSResponder::IP (LEGACY) -*/ -IPAddress MDNSResponder::IP(const uint32_t p_u32AnswerIndex) -{ - return answerIPv4(p_u32AnswerIndex); -} -#endif - -#ifdef MDNS_IPV6_SUPPORT -/* - MDNSResponder::answerIPv6 -*/ -IPAddress MDNSResponder::answerIPv6(const MDNSResponder::hMDNSHost p_hMDNSHost, - const uint32_t p_u32AnswerIndex) -{ - const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); - const stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); - const stcQuery::stcAnswer::stcIPv6Address* pIPv6Address = (((pSQAnswer) && (pSQAnswer->m_pIPv6Addresses)) ? pSQAnswer->IPv6AddressAtIndex(0) : 0); - return (pIPv6Address ? pIPv6Address->m_IPAddress : IPAddress()); -} - -/* - MDNSResponder::answerIPv6 (LEGACY 2) -*/ -IPAddress MDNSResponder::answerIPv6(const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? answerIPv6((hMDNSHost)m_HostList.front(), p_u32AnswerIndex) - : IPAddress()); -} -#endif - -/* - MDNSResponder::answerPort -*/ -uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSHost p_hMDNSHost, - const uint32_t p_u32AnswerIndex) -{ - const stcQuery* pQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findLegacyQuery(*(clsHost*)p_hMDNSHost) : 0); - const stcQuery::stcAnswer* pSQAnswer = (pQuery ? pQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->m_u16Port : 0); -} - -/* - MDNSResponder::answerPort (LEGACY 2) -*/ -uint16_t MDNSResponder::answerPort(const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? answerPort((hMDNSHost)m_HostList.front(), p_u32AnswerIndex) - : 0); -} - -/* - MDNSResponder::port (LEGACY) -*/ -uint16_t MDNSResponder::port(const uint32_t p_u32AnswerIndex) -{ - return answerPort(p_u32AnswerIndex); -} - - -/** - DYNAMIC SERVICE QUERY -*/ - -/* - MDNSResponder::installServiceQuery - - Add a dynamic service query and a corresponding callback to the MDNS responder. - The callback will be called for every answer update. - The answers can also be queried by calling: - - answerServiceDomain - - answerHostDomain - - answerIPv4Address/answerIPv6Address - - answerPort - - answerTxts - -*/ -MDNSResponder::hMDNSQuery MDNSResponder::installServiceQuery(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcService, - const char* p_pcProtocol, - MDNSResponder::MDNSQueryCallbackFn p_fnCallback) -{ - hMDNSQuery hResult = 0; - - stcQuery* pMDNSQuery = 0; - if ((_validateMDNSHostHandle(p_hMDNSHost)) && - (p_pcService) && - (os_strlen(p_pcService)) && - (p_pcProtocol) && - (os_strlen(p_pcProtocol)) && - (p_fnCallback) && - ((pMDNSQuery = _allocQuery(*(clsHost*)p_hMDNSHost, stcQuery::enuQueryType::Service))) && - (_buildDomainForService(p_pcService, p_pcProtocol, pMDNSQuery->m_Domain))) - { - - pMDNSQuery->m_fnCallback = p_fnCallback; - pMDNSQuery->m_bLegacyQuery = false; - - if (_sendMDNSQuery(*(clsHost*)p_hMDNSHost, *pMDNSQuery)) - { - pMDNSQuery->m_u8SentCount = 1; - pMDNSQuery->m_ResendTimeout.reset(MDNS_DYNAMIC_QUERY_RESEND_DELAY); - - hResult = (hMDNSQuery)pMDNSQuery; - } - else - { - _removeQuery(*(clsHost*)p_hMDNSHost, pMDNSQuery); - } - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s installServiceQuery: %s for '%s.%s'!\n\n"), _DH(), (hResult ? "Succeeded" : "FAILED"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); - DEBUG_EX_ERR(if (!hResult) DEBUG_OUTPUT.printf_P(PSTR("%s installServiceQuery: FAILED for '%s.%s'!\n\n"), _DH(), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); - return hResult; -} - -/* - MDNSResponder::installServiceQuery (LEGACY 2) -*/ -MDNSResponder::hMDNSQuery MDNSResponder::installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - MDNSResponder::MDNSQueryCallbackFn1 p_fnCallback) -{ - return ((!m_HostList.empty()) - ? installServiceQuery((hMDNSHost)m_HostList.front(), p_pcService, p_pcProtocol, [p_fnCallback])(MDNSResponder * p_pMDNSResponder, - MDNSResponder::hMDNSHost, - const stcAnswerAccessor & p_MDNSAnswerAccessor, - typeQueryAnswerType p_QueryAnswerTypeFlags, - bool p_bSetContent) - { - if (p_fnCallback) - { - p_fnCallback(p_pMDNSResponder, p_MDNSAnswerAccessor, p_QueryAnswerTypeFlags, p_bSetContent); - } - }) - : 0); - } - - /* - MDNSResponder::installServiceQuery (LEGACY 2) - */ - MDNSResponder::hMDNSQuery MDNSResponder::installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - MDNSResponder::MDNSQueryCallbackFn2 p_fnCallback) -{ - return ((!m_HostList.empty()) - ? installServiceQuery((hMDNSHost)m_HostList.front(), p_pcService, p_pcProtocol, [p_fnCallback])(MDNSResponder*, - MDNSResponder::hMDNSHost, - const stcAnswerAccessor & p_MDNSAnswerAccessor, - typeQueryAnswerType p_QueryAnswerTypeFlags, - bool p_bSetContent) - { - if (p_fnCallback) - { - p_fnCallback(p_MDNSAnswerAccessor, p_QueryAnswerTypeFlags, p_bSetContent); - } - }) - : 0); - } - - /* - MDNSResponder::installHostQuery - */ - MDNSResponder::hMDNSQuery MDNSResponder::installHostQuery(const MDNSResponder::hMDNSHost p_hMDNSHost, - const char* p_pcHostName, - MDNSResponder::MDNSQueryCallbackFn p_fnCallback) -{ - hMDNSQuery hResult = 0; - - if ((_validateMDNSHostHandle(p_hMDNSHost)) && - (p_pcHostName) && - (os_strlen(p_pcHostName))) - { - stcRRDomain domain; - hResult = ((_buildDomainForHost(p_pcHostName, domain)) - ? _installDomainQuery(*(clsHost*)p_hMDNSHost, domain, stcQuery::enuQueryType::Host, p_fnCallback) - : 0); - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s installHostQuery: %s for '%s.local'!\n\n"), _DH(), (hResult ? "Succeeded" : "FAILED"), (p_pcHostName ? : "-"));); - DEBUG_EX_ERR(if (!hResult) DEBUG_OUTPUT.printf_P(PSTR("%s installHostQuery: FAILED for '%s.local'!\n\n"), _DH(), (p_pcHostName ? : "-"));); - return hResult; -} - -/* - MDNSResponder::installHostQuery (LEGACY 2) -*/ -MDNSResponder::hMDNSQuery MDNSResponder::installHostQuery(const char* p_pcHostName, - MDNSResponder::MDNSQueryCallbackFn1 p_fnCallback) -{ - return installHostQuery(p_pcHostName, [p_fnCallback](MDNSResponder * p_pMDNSResponder, - hMDNSHost, - const stcAnswerAccessor & p_MDNSAnswerAccessor, - typeQueryAnswerType p_QueryAnswerTypeFlags, - bool p_bSetContent) - { - if (p_fnCallback) - { - p_fnCallback(p_pMDNSResponder, p_MDNSAnswerAccessor, p_QueryAnswerTypeFlags, p_bSetContent); - } - }); -} - -/* - MDNSResponder::installHostQuery (LEGACY 2) -*/ -MDNSResponder::hMDNSQuery MDNSResponder::installHostQuery(const char* p_pcHostName, - MDNSResponder::MDNSQueryCallbackFn2 p_fnCallback) -{ - return installHostQuery(p_pcHostName, [p_fnCallback](MDNSResponder*, - hMDNSHost, - const stcAnswerAccessor & p_MDNSAnswerAccessor, - typeQueryAnswerType p_QueryAnswerTypeFlags, - bool p_bSetContent) - { - if (p_fnCallback) - { - p_fnCallback(p_MDNSAnswerAccessor, p_QueryAnswerTypeFlags, p_bSetContent); - } - }); -} - -/* - MDNSResponder::removeQuery - - Remove a dynamic query (and all collected answers) from the MDNS responder - -*/ -bool MDNSResponder::removeQuery(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery) -{ - stcQuery* pMDNSQuery = 0; - bool bResult = ((_validateMDNSHostHandle(p_hMDNSHost)) && - ((pMDNSQuery = _findQuery(*(clsHost*)p_hMDNSHost, p_hQuery))) && - (_removeQuery(*(clsHost*)p_hMDNSHost, pMDNSQuery))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeQuery: FAILED!\n"), _DH());); - return bResult; -} - -/* - MDNSResponder::removeQuery (LEGACY 2) -*/ -bool MDNSResponder::removeQuery(const MDNSResponder::hMDNSQuery p_hMDNSQuery) -{ - return ((!m_HostList.empty()) - ? removeQuery((hMDNSHost)m_HostList.front(), p_hMDNSQuery) - : false); -} - -/* - MDNSResponder::answerAccessors -*/ -MDNSResponder::clsMDNSAnswerAccessorVector MDNSResponder::answerAccessors(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery) -{ - MDNSResponder::clsMDNSAnswerAccessorVector tempVector; - for (uint32_t u = 0; u < answerCount(p_hMDNSHost, p_hMDNSQuery); ++u) - { - tempVector.emplace_back(*this, p_hMDNSQuery, u); - } - return tempVector; -} - -/* - MDNSResponder::answerAccessors (LEGACY 2) -*/ -MDNSResponder::clsMDNSAnswerAccessorVector MDNSResponder::answerAccessors(const MDNSResponder::hMDNSQuery p_hMDNSQuery) -{ - return ((!m_HostList.empty()) - ? answerAccessors((hMDNSHost)m_HostList.front(), p_hMDNSQuery) - : MDNSResponder::clsMDNSAnswerAccessorVector()); -} - -/* - MDNSResponder::answerCount -*/ -uint32_t MDNSResponder::answerCount(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery) : 0); - return (pMDNSQuery ? pMDNSQuery->answerCount() : 0); -} - -/* - MDNSResponder::answerCount (LEGACY 2) -*/ -uint32_t MDNSResponder::answerCount(const MDNSResponder::hMDNSQuery p_hMDNSQuery) -{ - return ((!m_HostList.empty()) - ? answerCount((hMDNSHost)m_HostList.front(), p_hMDNSQuery) - : 0); -} - -/* - MDNSResponder::hasAnswerServiceDomain -*/ -bool MDNSResponder::hasAnswerServiceDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::ServiceDomain))); -} - - /* - MDNSResponder::hasAnswerServiceDomain (LEGACY 2) - */ - bool MDNSResponder::hasAnswerServiceDomain(const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? hasAnswerServiceDomain((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) - : false); -} - -/* - MDNSResponder::answerServiceDomain - - Returns the domain for the given service. - If not already existing, the string is allocated, filled and attached to the answer. - -*/ -const char* MDNSResponder::answerServiceDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcServiceDomain (if not already done) - if ((pSQAnswer) && - (pSQAnswer->m_ServiceDomain.m_u16NameLength) && - (!pSQAnswer->m_pcServiceDomain)) -{ - - pSQAnswer->m_pcServiceDomain = pSQAnswer->allocServiceDomain(pSQAnswer->m_ServiceDomain.c_strLength()); - if (pSQAnswer->m_pcServiceDomain) - { - pSQAnswer->m_ServiceDomain.c_str(pSQAnswer->m_pcServiceDomain); - } - } - return (pSQAnswer ? pSQAnswer->m_pcServiceDomain : 0); -} - -/* - MDNSResponder::answerServiceDomain (LEGACY 2) -*/ -const char* MDNSResponder::answerServiceDomain(const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? answerServiceDomain((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) - : 0); -} - -/* - MDNSResponder::hasAnswerHostDomain -*/ -bool MDNSResponder::hasAnswerHostDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::HostDomain))); -} - - /* - MDNSResponder::hasAnswerHostDomain (LEGACY 2) - */ - bool MDNSResponder::hasAnswerHostDomain(const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? hasAnswerHostDomain((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) - : false); -} - -/* - MDNSResponder::answerHostDomain - - Returns the host domain for the given service. - If not already existing, the string is allocated, filled and attached to the answer. - -*/ -const char* MDNSResponder::answerHostDomain(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcHostDomain (if not already done) - if ((pSQAnswer) && - (pSQAnswer->m_HostDomain.m_u16NameLength) && - (!pSQAnswer->m_pcHostDomain)) -{ - - pSQAnswer->m_pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); - if (pSQAnswer->m_pcHostDomain) - { - pSQAnswer->m_HostDomain.c_str(pSQAnswer->m_pcHostDomain); - } - } - return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); -} - -/* - MDNSResponder::answerHostDomain (LEGACY 2) -*/ -const char* MDNSResponder::answerHostDomain(const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? answerHostDomain((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) - : 0); -} - -#ifdef MDNS_IPV4_SUPPORT -/* - MDNSResponder::hasAnswerIPv4Address -*/ -bool MDNSResponder::hasAnswerIPv4Address(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv4Address))); -} - - /* - MDNSResponder::hasAnswerIPv4Address (LEGACY 2) - */ - bool MDNSResponder::hasAnswerIPv4Address(const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? hasAnswerIPv4Address((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) - : false); -} - -/* - MDNSResponder::answerIPv4AddressCount -*/ -uint32_t MDNSResponder::answerIPv4AddressCount(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->IPv4AddressCount() : 0); -} - - /* - MDNSResponder::answerIPv4AddressCount (LEGACY 2) - */ - uint32_t MDNSResponder::answerIPv4AddressCount(const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? answerIPv4AddressCount((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) - : 0); -} - -/* - MDNSResponder::answerIPv4Address -*/ -IPAddress MDNSResponder::answerIPv4Address(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - stcQuery::stcAnswer::stcIPv4Address* pIPv4Address = (pSQAnswer ? pSQAnswer->IPv4AddressAtIndex(p_u32AddressIndex) : 0); - return (pIPv4Address ? pIPv4Address->m_IPAddress : IPAddress()); -} - - /* - MDNSResponder::answerIPv4Address (LEGACY 2) - */ - IPAddress MDNSResponder::answerIPv4Address(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - return ((!m_HostList.empty()) - ? answerIPv4Address((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex, p_u32AddressIndex) - : IPAddress()); -} -#endif - -#ifdef MDNS_IPV6_SUPPORT -/* - MDNSResponder::hasAnswerIPv6Address -*/ -bool MDNSResponder::hasAnswerIPv6Address(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::IPv6Address))); -} - - /* - MDNSResponder::hasAnswerIPv6Address (LEGACY 2) - */ - bool MDNSResponder::hasAnswerIPv6Address(const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? hasAnswerIPv6Address((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) - : false); -} - -/* - MDNSResponder::answerIPv6AddressCount -*/ -uint32_t MDNSResponder::answerIPv6AddressCount(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->IPv6AddressCount() : 0); -} - - /* - MDNSResponder::answerIPv6AddressCount (LEGACY 2) - */ - uint32_t MDNSResponder::answerIPv6AddressCount(const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? answerIPv6AddressCount((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) - : 0); -} - -/* - MDNSResponder::answerIPv6Address -*/ -IPAddress MDNSResponder::answerIPv6Address(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - stcQuery::stcAnswer::stcIPv6Address* pIPv6Address = (pSQAnswer ? pSQAnswer->IPv6AddressAtIndex(p_u32AddressIndex) : 0); - return (pIPv6Address ? pIPv6Address->m_IPAddress : IPAddress()); -} - - /* - MDNSResponder::answerIPv6Address (LEGACY 2) - */ - IPAddress MDNSResponder::answerIPv6Address(const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - return ((!m_HostList.empty()) - ? answerIPv6Address((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) - : IPAddress()); -} -#endif - -/* - MDNSResponder::hasAnswerPort -*/ -bool MDNSResponder::hasAnswerPort(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::Port))); -} - - /* - MDNSResponder::hasAnswerPort (LEGACY 2) - */ - bool MDNSResponder::hasAnswerPort(const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? hasAnswerPort((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) - : false); -} - -/* - MDNSResponder::answerPort -*/ -uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->m_u16Port : 0); -} - - /* - MDNSResponder::answerPort (LEGACY 2) - */ - uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? answerPort((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) - : 0); -} - -/* - MDNSResponder::hasAnswerTxts -*/ -bool MDNSResponder::hasAnswerTxts(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_QueryAnswerFlags & static_cast<typeQueryAnswerType>(enuQueryAnswerType::Txts))); -} - - /* - MDNSResponder::hasAnswerTxts (LEGACY 2) - */ - bool MDNSResponder::hasAnswerTxts(const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? hasAnswerTxts((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) - : false); -} - -/* - MDNSResponder::answerTxts - - Returns all TXT items for the given service as a ';'-separated string. - If not already existing; the string is alloced, filled and attached to the answer. - -*/ -const char* MDNSResponder::answerTxts(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - stcQuery* pMDNSQuery = (_validateMDNSHostHandle(p_hMDNSHost) ? _findQuery(*(clsHost*)p_hMDNSHost, p_hMDNSQuery); - stcQuery::stcAnswer* pSQAnswer = (pMDNSQuery ? pMDNSQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcTxts (if not already done) - if ((pSQAnswer) && - (pSQAnswer->m_Txts.m_pTxts) && - (!pSQAnswer->m_pcTxts)) -{ - - pSQAnswer->m_pcTxts = pSQAnswer->allocTxts(pSQAnswer->m_Txts.c_strLength()); - if (pSQAnswer->m_pcTxts) - { - pSQAnswer->m_Txts.c_str(pSQAnswer->m_pcTxts); - } - } - return (pSQAnswer ? pSQAnswer->m_pcTxts : 0); -} - -/* - MDNSResponder::answerTxts (LEGACY 2) -*/ -const char* MDNSResponder::answerTxts(const MDNSResponder::hMDNSQuery p_hMDNSQuery, - const uint32_t p_u32AnswerIndex) -{ - return ((!m_HostList.empty()) - ? answerTxts((hMDNSHost)m_HostList.front(), p_hMDNSQuery, p_u32AnswerIndex) - : 0); -} - - -/* - PROBING -*/ - -/* - MDNSResponder::setHostProbeResultCallback - - Set a callback for probe results. The callback is called, when probing - for the host domain failes or succeedes. - In the case of failure, the domain name should be changed via 'setHostName' - When succeeded, the host domain will be announced by the MDNS responder. - -*/ -bool MDNSResponder::setHostProbeResultCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, - MDNSResponder::MDNSHostProbeResultCallbackFn p_fnCallback) -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (((clsHost*)p_hMDNSHost)->m_HostProbeInformation.m_fnProbeResultCallback = p_fnCallback, true)); -} - -/* - MDNSResponder::setHostProbeResultCallback (LEGACY 2) -*/ -bool MDNSResponder::setHostProbeResultCallback(MDNSResponder::MDNSHostProbeResultCallbackFn1 p_fnCallback) -{ - return setHostProbeResultCallback([p_fnCallback](MDNSResponder * p_pMDNSResponder, - hMDNSHost, - const char* p_pcDomainName, - bool p_bProbeResult) - { - if (p_fnCallback) - { - p_fnCallback(p_pMDNSResponder, p_pcDomainName, p_bProbeResult); - } - }); -} - -/* - MDNSResponder::setHostProbeResultCallback (LEGACY 2) -*/ -bool MDNSResponder::setHostProbeResultCallback(MDNSResponder::MDNSHostProbeResultCallbackFn2 p_fnCallback) -{ - return setHostProbeResultCallback([p_fnCallback](MDNSResponder*, - hMDNSHost, - const char* p_pcDomainName, - bool p_bProbeResult) - { - if (p_fnCallback) - { - p_fnCallback(p_pcDomainName, p_bProbeResult); - } - }); -} - -/* - MDNSResponder::setServiceProbeResultCallback - - Set a service specific callback for probe results. The callback is called, when probing - for the service domain failes or succeedes. - In the case of failure, the service name should be changed via 'setServiceName'. - When succeeded, the service domain will be announced by the MDNS responder. - -*/ -bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSHost p_hMDNSHost, - const MDNSResponder::hMDNSService p_hMDNSService, - MDNSResponder::MDNSServiceProbeResultCallbackFn p_fnCallback) -{ - return ((_validateMDNSHostHandle(p_hMDNSHost, p_hMDNSService)) && - (((stcService*)p_hMDNSService)->m_ProbeInformation.m_fnProbeResultCallback = p_fnCallback, true)); -} - -/* - MDNSResponder::setServiceProbeResultCallback (LEGACY 2) -*/ -bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hMDNSService, - MDNSResponder::MDNSServiceProbeResultCallbackFn1 p_fnCallback) -{ - return setServiceProbeResultCallback(p_hMDNSService, [p_fnCallback](MDNSResponder * p_pMDNSResponder, - hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcServiceName, - bool p_bProbeResult) - { - if (p_fnCallback) - { - p_fnCallback(p_pMDNSResponder, p_hMDNSService, p_pcServiceName, p_bProbeResult); - } - }); -} - -/* - MDNSResponder::setServiceProbeResultCallback (LEGACY 2) -*/ -bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hMDNSService, - MDNSResponder::MDNSServiceProbeResultCallbackFn2 p_fnCallback) -{ - return setServiceProbeResultCallback(p_hMDNSService, [p_fnCallback](MDNSResponder*, - hMDNSHost, - const hMDNSService p_hMDNSService, - const char* p_pcServiceName, - bool p_bProbeResult) - { - if (p_fnCallback) - { - p_fnCallback(p_hMDNSService, p_pcServiceName, p_bProbeResult); - } - }); -} -#endif - -/* - MISC -*/ - -/* - MDNSResponder::notifyNetIfChange - - Should be called, whenever the AP for the MDNS responder changes. - A bit of this is caught by the event callbacks installed in the constructor. - -*/ -bool MDNSResponder::notifyNetIfChange(netif* p_pNetIf) -{ - clsHost* pMDNSHost; - return (((pMDNSHost = _findHost(p_pNetIf))) && - (pMDNSHost->restart())); -} - -/* - MDNSResponder::update - - Should be called in every 'loop'. - -*/ -bool MDNSResponder::update(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_NRH2Ptr(p_hMDNSHost)->update())); -} - -/* - MDNSResponder::update (convenience) -*/ -bool MDNSResponder::update(void) -{ - bool bResult = true; - for (clsHost* pMDNSHost : m_HostList) - { - if (!pMDNSHost->update()) - { - bResult = false; - } - } - return bResult; -} - -/* - MDNSResponder::announce - - Should be called, if the 'configuration' changes. Mainly this will be changes in the TXT items... -*/ -bool MDNSResponder::announce(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_NRH2Ptr(p_hMDNSHost)->announce(true, true))); -} - -/* - MDNSResponder::announce (convenience) -*/ -bool MDNSResponder::announce(void) -{ - bool bResult = true; - for (clsHost* pMDNSHost : m_HostList) - { - if (!pMDNSHost->announce(true, true)) - { - bResult = false; - } - } - return bResult; -} - -/* - MDNSResponder::enableArduino - - Enable the OTA update service. - -*/ -MDNSResponder::hMDNSService MDNSResponder::enableArduino(const MDNSResponder::hMDNSHost p_hMDNSHost, - uint16_t p_u16Port, - bool p_bAuthUpload /*= false*/) -{ - hMDNSService hService = addService(p_hMDNSHost, 0, "arduino", "tcp", p_u16Port); - if (hService) - { - if ((!addServiceTxt(p_hMDNSHost, hService, "tcp_check", "no")) || - (!addServiceTxt(p_hMDNSHost, hService, "ssh_upload", "no")) || - (!addServiceTxt(p_hMDNSHost, hService, "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD))) || - (!addServiceTxt(p_hMDNSHost, hService, "auth_upload", (p_bAuthUpload) ? "yes" : "no"))) - { - - removeService(p_hMDNSHost, hService); - hService = 0; - } - } - return hService; -} - -#ifdef LATER - -/* - MDNSResponder::enableArduino (LEGACY 2) -*/ -MDNSResponder::hMDNSService MDNSResponder::enableArduino(uint16_t p_u16Port, - bool p_bAuthUpload /*= false*/) -{ - hMDNSService hMDNSService = 0; - for (clsHost*& pMDNSHost : m_HostList) - { - hMDNSService hLastMDNSService = enableArduino((hMDNSHost)it, p_u16Port, p_bAuthUpload); - if ((hLastMDNSService) && - (!hMDNSService)) - { - hMDNSService = hLastMDNSService; - } - } - return hMDNSService; -} - -#endif - -} //namespace MDNSImplementation - -} //namespace esp8266 - - diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_APIHelpers.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_APIHelpers.cpp deleted file mode 100755 index 7c144499e4..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_APIHelpers.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/* - LEAmDNS2_APIHelpers.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#include <arch/cc.h> -#include <sys/time.h> -#include <HardwareSerial.h> -#include <IPAddress.h> -#include <lwip/ip_addr.h> -#include <WString.h> -#include <cstdint> - -/* - ESP8266mDNS Control.cpp -*/ - -extern "C" { -#include "user_interface.h" -} - -#include "LEAmDNS2_lwIPdefs.h" -#include "LEAmDNS2_Priv.h" - -namespace esp8266 -{ -/* - LEAmDNS -*/ -namespace experimental -{ - -/* - MDNSResponder::_allocUDPContext -*/ -bool MDNSResponder::_allocUDPContext(void) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext\n"), _DH());); - if (_releaseUDPContext()) - { - m_pUDPContext = new UdpContext; - if (m_pUDPContext) - { - m_pUDPContext->ref(); - - ip_set_option(m_pUDPContext->pcb(), SOF_REUSEADDR); - //udp_bind_netif(m_pUDPContext->pcb(), m_pNetIf); - - if (m_pUDPContext->listen(IP_ANY_TYPE, DNS_MQUERY_PORT)) - { - //m_pUDPContext->setMulticastInterface(m_pNetIf); - m_pUDPContext->setMulticastTTL(MDNS_MULTICAST_TTL); - m_pUDPContext->onRx(std::bind(&MDNSResponder::_processUDPInput, this)); - m_pUDPContext->connect(IP_ANY_TYPE, DNS_MQUERY_PORT); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: Succeeded to alloc UDPContext!\n"), _DH());); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: FAILED to make UDPContext listening!\n"), _DH());); - _releaseUDPContext(); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: FAILED to alloc UDPContext!\n"), _DH());); - } - } - DEBUG_EX_ERR(if (!m_pUDPContext) DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: FAILED!\n"), _DH());); - return (0 != m_pUDPContext); -} - -/* - MDNSResponder::_releaseUDPContext -*/ -bool MDNSResponder::_releaseUDPContext(void) -{ - if (m_pUDPContext) - { - m_pUDPContext->unref(); - m_pUDPContext = 0; - } - return true; -} - -/* - MDNSResponder::_processUDPInput - - Called in SYS context! - -*/ -bool MDNSResponder::_processUDPInput(void) -{ - //DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput\n"), _DH());); - - if (m_pUDPContext->next()) - { - netif* pNetIf = ip_current_input_netif(); - MDNSResponder::clsHost* pHost = 0; - if ((pNetIf) && - ((pHost = _findHost(pNetIf)))) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: netif:%u,src:%s,dest:%s\n"), _DH(), netif_get_index(pNetIf), IPAddress(ip_current_src_addr()).toString().c_str(), IPAddress(ip_current_dest_addr()).toString().c_str());); - pHost->processUDPInput(/*IPAddress(ip_current_src_addr()), IPAddress(ip_current_dest_addr())*/); - } - else - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Received UDP datagramm for unused netif at index: %u\n"), _DH(), (pNetIf ? netif_get_index(pNetIf) : (-1)));); - } - m_pUDPContext->flush(); - } - return true; -} - -/* - MDNSResponder::_createHost -*/ -MDNSResponder::clsHost* MDNSResponder::_createHost(netif* p_pNetIf) -{ - clsHost* pHost = 0; - - if ((p_pNetIf) && - (!((pHost = _findHost(p_pNetIf)))) && - (m_pUDPContext) && - ((pHost = new clsHost(*p_pNetIf, *m_pUDPContext)))) - { - if (pHost->init()) - { - //pHost->setHostProbeResultCallback(_defaultHostProbeResultCallback); - m_HostList.push_back(pHost); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: FAILED!\n"), _DH());); - _releaseHost(pHost); - pHost = 0; - } - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: Attaching to netif %s!\n"), _DH(), (pHost ? "succeeded" : "FAILED"));); - return pHost; -} - -/* - MDNSResponder::_releaseHost -*/ -bool MDNSResponder::_releaseHost(MDNSResponder::clsHost* p_pHost) -{ - bool bResult = false; - - if ((p_pHost) && - (m_HostList.end() != std::find(m_HostList.begin(), m_HostList.end(), p_pHost))) - { - // Delete and remove Responder object - delete p_pHost; - m_HostList.remove(p_pHost); - bResult = true; - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _releaseHost: %s to release netif Responder!\n"), _DH(), (bResult ? "Succeeded" : "FAILED"));); - return bResult; -} - -/* - MDNSResponder::_findHost -*/ -const MDNSResponder::clsHost* MDNSResponder::_findHost(netif* p_pNetIf) const -{ - const clsHost* pResult = 0; - for (const clsHost* pHost : m_HostList) - { - if ((p_pNetIf) && - (&(pHost->m_rNetIf) == p_pNetIf)) - { - pResult = pHost; - break; - } - } - return pResult; -} - -/* - MDNSResponder::_findHost -*/ -MDNSResponder::clsHost* MDNSResponder::_findHost(netif* p_pNetIf) -{ - return (clsHost*)(((const MDNSResponder*)this)->_findHost(p_pNetIf)); -} - -/* - MDNSResponder::_findHost -*/ -const MDNSResponder::clsHost* MDNSResponder::_findHost(const MDNSResponder::hMDNSHost p_hMDNSHost) const -{ - clsHostList::const_iterator it(std::find(m_HostList.begin(), m_HostList.end(), _NRH2Ptr(p_hMDNSHost))); - return ((m_HostList.end() != it) ? *it : 0); -} - -/* - MDNSResponder::_findHost -*/ -MDNSResponder::clsHost* MDNSResponder::_findHost(const MDNSResponder::hMDNSHost p_hMDNSHost) -{ - return (clsHost*)(((const MDNSResponder*)this)->_findHost(p_hMDNSHost)); -} - - -/* - HANDLE HELPERS -*/ - -/* - MDNSResponder::_validateMDNSHostHandle -*/ -bool MDNSResponder::_validateMDNSHostHandle(const hMDNSHost p_hMDNSHost) const -{ - return (0 != _findHost(_NRH2Ptr(p_hMDNSHost))); -} - -/* - MDNSResponder::_validateMDNSHostHandle -*/ -bool MDNSResponder::_validateMDNSHostHandle(const hMDNSHost p_hMDNSHost, - const hMDNSService p_hMDNSService) const -{ - return ((_validateMDNSHostHandle(p_hMDNSHost)) && - (_NRH2Ptr(p_hMDNSHost)->validateService(_SH2Ptr(p_hMDNSService)))); -} - -/* - MDNSResponder::_NRH2Ptr -*/ -MDNSResponder::clsHost* MDNSResponder::_NRH2Ptr(const hMDNSHost p_hMDNSHost) -{ - return (clsHost*)p_hMDNSHost; -} - -/* - MDNSResponder::_NRH2Ptr -*/ -const MDNSResponder::clsHost* MDNSResponder::_NRH2Ptr(const hMDNSHost p_hMDNSHost) const -{ - return (const clsHost*)p_hMDNSHost; -} - -/* - MDNSResponder::_SH2Ptr -*/ -MDNSResponder::clsHost::stcService* MDNSResponder::_SH2Ptr(const hMDNSService p_hMDNSService) -{ - return (clsHost::stcService*)p_hMDNSService; -} - -/* - MDNSResponder::_SH2Ptr -*/ -const MDNSResponder::clsHost::stcService* MDNSResponder::_SH2Ptr(const hMDNSService p_hMDNSService) const -{ - return (const clsHost::stcService*)p_hMDNSService; -} - -/* - MDNSResponder::_begin - - Creates a new netif responder (adding the netif to the multicast groups), - sets up the instance data (hostname, ...) and starts the probing process - -*/ -MDNSResponder::clsHost* MDNSResponder::_begin(const char* p_pcHostName, - netif* p_pNetIf, - MDNSHostProbeResultCallbackFn p_fnCallback) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _begin(%s, netif: %u)\n"), _DH(), (p_pcHostName ?: "_"), (p_pNetIf ? netif_get_index(p_pNetIf) : 0));); - - clsHost* pHost = 0; - if ((!m_pUDPContext) || - (!p_pNetIf) || - (!((pHost = _createHost(p_pNetIf)))) || - (p_fnCallback ? !setHostProbeResultCallback((hMDNSHost)pHost, p_fnCallback) : false) || - (!pHost->setHostName(p_pcHostName)) || - (!pHost->restart())) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _begin: FAILED for '%s'!\n"), _DH(), (p_pcHostName ? : "-"));); - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _begin: %s to init netif with hostname %s!\n"), _DH(), (pHost ? "Succeeded" : "FAILED"), (p_pcHostName ? : "-"));); - return pHost; -} - -/* - MDNSResponder::_close - - The announced host and services are unannounced (by multicasting a goodbye message) - All connected objects and finally the netif Responder is removed. - -*/ -bool MDNSResponder::_close(MDNSResponder::clsHost& p_rHost) -{ - _releaseHost(&p_rHost); // Will call 'delete' on the pHost object! - - return true; -} - - -/* - MISC -*/ - -#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER - -/* - MDNSResponder::_DH -*/ -const char* MDNSResponder::_DH(const hMDNSHost p_hMDNSHost /*= 0*/) const -{ - static char acBuffer[64]; - - *acBuffer = 0; - if (p_hMDNSHost) - { - sprintf_P(acBuffer, PSTR("[MDNSResponder %s]"), ((WIFI_STA == netif_get_index(&((clsHost*)p_hMDNSHost)->m_rNetIf)) - ? "STA" - : ((WIFI_AP == netif_get_index(&((clsHost*)p_hMDNSHost)->m_rNetIf)) - ? "AP" - : "??"))); - } - else - { - sprintf_P(acBuffer, PSTR("[MDNSResponder]")); - } - return acBuffer; -} - -#endif - - -} // namespace MDNSImplementation - -} // namespace esp8266 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp new file mode 100644 index 0000000000..1f5f0422d4 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -0,0 +1,339 @@ +/* + LEAmDNS2_Backbone.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#include "LEAmDNS2Host.h" + + +namespace esp8266 +{ + + +namespace experimental +{ + + +/* + clsLEAmDNS2_Host::clsBackbone::clsBackbone constructor + +*/ +clsLEAMDNSHost::clsBackbone::clsBackbone(void) + : m_pUDPContext(0), + m_bDelayUDPProcessing(false), + m_u32DelayedDatagrams(0) +{ +} + +/* + clsLEAmDNS2_Host::clsBackbone::clsBackbone destructor + +*/ +clsLEAMDNSHost::clsBackbone::~clsBackbone(void) +{ + _releaseUDPContext(); +} + +/* + clsLEAmDNS2_Host::clsBackbone::init + +*/ +bool clsLEAMDNSHost::clsBackbone::init(void) +{ + return _allocUDPContext(); +} + +/* + clsLEAmDNS2_Host::clsBackbone::addHost + +*/ +UdpContext* clsLEAMDNSHost::clsBackbone::addHost(clsLEAMDNSHost* p_pHost) +{ + UdpContext* pUDPContext = 0; + + if ((m_pUDPContext) && + (p_pHost)) + { + m_HostList.push_back(p_pHost); + pUDPContext = m_pUDPContext; + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s addHost: %s to add host!\n"), _DH(), (pUDPContext ? "Succeeded" : "FAILED"));); + return pUDPContext; +} + +/* + clsLEAmDNS2_Host::clsBackbone::removeHost + +*/ +bool clsLEAMDNSHost::clsBackbone::removeHost(clsLEAMDNSHost* p_pHost) +{ + bool bResult = false; + + if ((p_pHost) && + (m_HostList.end() != std::find(m_HostList.begin(), m_HostList.end(), p_pHost))) + { + // Remove host object + m_HostList.remove(p_pHost); + bResult = true; + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s removeHost: %s to remove host!\n"), _DH(), (bResult ? "Succeeded" : "FAILED"));); + return bResult; +} + + +/* + clsLEAmDNS2_Host::clsBackbone::hostCount + +*/ +size_t clsLEAMDNSHost::clsBackbone::hostCount(void) const +{ + return m_HostList.size(); +} + +/* + clsLEAMDNSHost::clsBackbone::::setDelayUDPProcessing + + When executing _sendMessage, with multiple or larger messages, sometimes the ESP IP stack seems + to need a small delay to get the job done. To allow for this delay, a 'delay' was added after one + send operation. However, while 'taking' this delay, sometimes a UDP datagram is received and + processed (which might cause another send operation or change global states). + To avoid 're-entry-like' problems, UDP processing might be blocked for a short period of time. + +*/ +bool clsLEAMDNSHost::clsBackbone::setDelayUDPProcessing(bool p_bDelayUDPProcessing) +{ + if (m_bDelayUDPProcessing != p_bDelayUDPProcessing) + { + m_bDelayUDPProcessing = p_bDelayUDPProcessing; + + if ((!m_bDelayUDPProcessing) && + (m_u32DelayedDatagrams)) + { + DEBUG_EX_INFO2(if (6 <= m_u32DelayedDatagrams) DEBUG_OUTPUT.printf_P(PSTR("%s setDelayUDPProcessing: Processing %u delayed datagram(s)\n"), _DH(), m_u32DelayedDatagrams);); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s setDelayUDPProcessing: Processing %u delayed datagram(s)\n"), _DH(), m_u32DelayedDatagrams);); + _processUDPInput(); + } + m_u32DelayedDatagrams = 0; + } + return true; +} + +/* + clsLEAmDNS2_Host::clsBackbone::_allocUDPContext + +*/ +bool clsLEAMDNSHost::clsBackbone::_allocUDPContext(void) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext\n"), _DH());); + if (_releaseUDPContext()) + { + m_pUDPContext = new UdpContext; + if (m_pUDPContext) + { + m_pUDPContext->ref(); + + //ip_set_option(m_pUDPContext->pcb(), SOF_REUSEADDR); + //udp_bind_netif(m_pUDPContext->pcb(), m_pNetIf); + + if (m_pUDPContext->listen(IP_ANY_TYPE, DNS_MQUERY_PORT)) + { + // This is NOT the TTL (Time-To-Live) for MDNS records, but the subnet level distance MDNS records should travel. + // 1 sets the subnet distance to 'local', which is default for MDNS. + // (Btw.: 255 would set it to 'as far as possible' -> internet), however, RFC 3171 seems to force 255 instead + const uint8_t c_u8MulticastTTL = 255;//1;//255; + + m_pUDPContext->setMulticastTTL(c_u8MulticastTTL); + m_pUDPContext->onRx(std::bind(&clsLEAMDNSHost::clsBackbone::_processUDPInput, this)); + /* m_pUDPContext->onRx([&](void)->void + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext::onRx Received data!\n"), _DH());); + });*/ + m_pUDPContext->connect(IP_ANY_TYPE, DNS_MQUERY_PORT); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: Succeeded to alloc UDPContext!\n"), _DH());); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: FAILED to make UDPContext listening!\n"), _DH());); + _releaseUDPContext(); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: FAILED to alloc UDPContext!\n"), _DH());); + } + } + DEBUG_EX_ERR(if (!m_pUDPContext) DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: FAILED!\n"), _DH());); + return (0 != m_pUDPContext); +} + +/* + clsLEAmDNS2_Host::clsBackbone::_releaseUDPContext + +*/ +bool clsLEAMDNSHost::clsBackbone::_releaseUDPContext(void) +{ + if (m_pUDPContext) + { + m_pUDPContext->unref(); + m_pUDPContext = 0; + } + return true; +} + +/* + clsLEAmDNS2_Host::clsBackbone::_processUDPInput + + Called in SYS context! + +*/ +bool clsLEAMDNSHost::clsBackbone::_processUDPInput(void) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput\n"), _DH());); + + bool bResult = true; + + if (!m_bDelayUDPProcessing) + { + DEBUG_EX_INFO(uint32_t u32LoopCounter = 0; IPAddress remoteIPAddr;); + while ((m_pUDPContext) && + (m_pUDPContext->next())) + { + netif* pNetIf = m_pUDPContext->getInputNetif();//ip_current_input_netif(); // Probably changed inbetween!!!! + clsLEAMDNSHost* pHost = 0; + if ((pNetIf) && + ((pHost = _findHost(pNetIf)))) + { + DEBUG_EX_INFO( + if (u32LoopCounter++) + { + DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Multi-Loop (%u)!\n"), _DH(), u32LoopCounter); + if ((remoteIPAddr.isSet()) && + (remoteIPAddr != m_pUDPContext->getRemoteAddress())) + { + DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Changed IP address %s->%s!\n"), _DH(), remoteIPAddr.toString().c_str(), m_pUDPContext->getRemoteAddress().toString().c_str()); + } + } + remoteIPAddr = m_pUDPContext->getRemoteAddress(); + ); + bResult = pHost->_processUDPInput(); + DEBUG_EX_INFO2(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: FAILED to process UDP input!\n"), _DH());); + + DEBUG_EX_ERR(if ((-1) != m_pUDPContext->peek()) DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: !!!! CONTENT LEFT IN UDP BUFFER !!!!\n"), _DH());); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Received UDP datagramm for unused netif at index: %u\n"), _DH(), (pNetIf ? netif_get_index(pNetIf) : (-1)));); + } + m_pUDPContext->flush(); + } + } + else + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Delaying datagram!\n"), _DH());); + ++m_u32DelayedDatagrams; + } + return bResult; +} + +/* + clsLEAmDNS2_Host::clsBackbone::_findHost +*/ +const clsLEAMDNSHost* clsLEAMDNSHost::clsBackbone::_findHost(netif* p_pNetIf) const +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _findHost\n"), _DH());); + const clsLEAMDNSHost* pResult = 0; + for (const clsLEAMDNSHost* pHost : m_HostList) + { + if ((p_pNetIf) && + (pHost->m_pNetIf == p_pNetIf)) + { + pResult = pHost; + break; + } + } + return pResult; +} + +/* + MDNSResponder::_findHost +*/ +clsLEAMDNSHost* clsLEAMDNSHost::clsBackbone::_findHost(netif* p_pNetIf) +{ + return (clsLEAMDNSHost*)(((const clsLEAMDNSHost::clsBackbone*)this)->_findHost(p_pNetIf)); +} + + +/* + MISC +*/ + +#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER + +/* + clsLEAmDNS2_Host::clsBackbone::_DH +*/ +const char* clsLEAMDNSHost::clsBackbone::_DH(void) const +{ + static char acBuffer[24]; + + *acBuffer = 0; + sprintf_P(acBuffer, PSTR("[mDNS::backbone]")); + + return acBuffer; +} + +#endif + +#if LWIP_VERSION_MAJOR == 1 + +/* + netif_get_by_index + + Extracted (and slightly changed) from: https://github.com/yarrick/lwip/blob/master/src/core/netif.c +*/ +struct netif* netif_get_by_index(u8_t idx) +{ + struct netif *netif; + + //LWIP_ASSERT_CORE_LOCKED(); + + if (idx != 0) // <- NETIF_NO_INDEX + { + for ((netif) = netif_list; (netif) != NULL; (netif) = (netif)->next) // <- NETIF_FOREACH(netif) + { + if (idx == netif_get_index(netif)) + { + return netif; /* found! */ + } + } + } + + return NULL; +} + +#endif // LWIP_VERSION_MAJOR == 1 + + +} // namespace MDNSImplementation + + +} // namespace esp8266 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Host.cpp deleted file mode 100755 index b9df26ce8f..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Host.cpp +++ /dev/null @@ -1,1336 +0,0 @@ -/* - LEAmDNS2_Host.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#include <arch/cc.h> -#include <sys/time.h> -#include <HardwareSerial.h> -#include <IPAddress.h> -#include <lwip/ip_addr.h> -#include <lwip/netif.h> -#include <WString.h> -#include <cstdint> - -/* - ESP8266mDNS Control.cpp -*/ - -extern "C" { -#include "user_interface.h" -} - -#include "LEAmDNS2_lwIPdefs.h" -#include "LEAmDNS2_Priv.h" - -#ifdef MDNS_IPV4_SUPPORT -#include <lwip/igmp.h> -#endif -#ifdef MDNS_IPV6_SUPPORT -#include <lwip/mld6.h> -#endif - - -namespace esp8266 -{ - -/* - LEAmDNS -*/ -namespace experimental -{ - -/* - MDNSResponder::clsHost::clsHost constructor -*/ -MDNSResponder::clsHost::clsHost(netif& p_rNetIf, - UdpContext& p_rUDPContext) - : m_rNetIf(p_rNetIf), - m_NetIfState(static_cast<typeNetIfState>(enuNetIfState::None)), - m_rUDPContext(p_rUDPContext), - m_pcHostName(0), - m_pcInstanceName(0), - m_pServices(0), - m_pQueries(0), - m_fnServiceTxtCallback(0), - m_HostProbeInformation() -{ -} - -/* - MDNSResponder::clsHost::~clsHost destructor -*/ -MDNSResponder::clsHost::~clsHost(void) -{ - _close(); -} - -/* - MDNSResponder::clsHost::init -*/ -bool MDNSResponder::clsHost::init(void) -{ - bool bResult = true; - - // Join multicast group(s) -#ifdef MDNS_IPV4_SUPPORT - ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; - if (!(m_rNetIf.flags & NETIF_FLAG_IGMP)) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: Setting flag: flags & NETIF_FLAG_IGMP\n"), _DH());); - m_rNetIf.flags |= NETIF_FLAG_IGMP; - - if (ERR_OK != igmp_start(&m_rNetIf)) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: igmp_start FAILED!\n"), _DH());); - } - } - - bResult = ((bResult) && - (ERR_OK == igmp_joingroup_netif(&m_rNetIf, ip_2_ip4(&multicast_addr_V4)))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: igmp_joingroup_netif(%s) FAILED!\n"), _DH(), IPAddress(multicast_addr_V4).toString().c_str());); -#endif - -#ifdef MDNS_IPV6_SUPPORT - ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; - bResult = ((bResult) && - (ERR_OK == mld6_joingroup_netif(&m_rNetIf, ip_2_ip6(&multicast_addr_V6)))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: mld6_joingroup_netif FAILED!\n"), _DH());); -#endif - return bResult; -} - -/* - MDNSResponder::clsHost::setHostName -*/ -bool MDNSResponder::clsHost::setHostName(const char* p_pcHostName) -{ - bool bResult; - if ((bResult = _allocHostName(p_pcHostName))) - { - m_HostProbeInformation.m_ProbingStatus = enuProbingStatus::ReadyToStart; - - // Replace 'auto-set' service names - for (stcService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) - { - if ((pService->m_bAutoName) && - (!m_pcInstanceName)) - { - bResult = pService->setName(p_pcHostName); - pService->m_ProbeInformation.m_ProbingStatus = enuProbingStatus::ReadyToStart; - } - } - } - return bResult; -} - -/* - MDNSResponder::clsHost::setHostName -*/ -const char* MDNSResponder::clsHost::hostName(void) const -{ - return m_pcHostName; -} - -/* - MDNSResponder::clsHost::setHostProbeResultCallback -*/ -bool MDNSResponder::clsHost::setHostProbeResultCallback(HostProbeResultCallbackFn p_fnCallback) -{ - m_HostProbeInformation.m_fnProbeResultCallback = p_fnCallback; - return true; -} - -/* - MDNSResponder::clsHost::probeStatus -*/ -bool MDNSResponder::clsHost::probeStatus(void) const -{ - return (enuProbingStatus::Done == m_HostProbeInformation.m_ProbingStatus); -} - - -/* - SERVICE -*/ - -/* - MDNSResponder::clsHost::setInstanceName -*/ -bool MDNSResponder::clsHost::setInstanceName(const char* p_pcInstanceName) -{ - bool bResult; - if ((bResult = _allocInstanceName(p_pcInstanceName))) - { - // Replace 'auto-set' service names - for (stcService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) - { - if (pService->m_bAutoName) - { - bResult = pService->setName(p_pcInstanceName); - pService->m_ProbeInformation.m_ProbingStatus = enuProbingStatus::ReadyToStart; - } - } - } - return bResult; -} - -/* - MDNSResponder::clsHost::instanceName -*/ -const char* MDNSResponder::clsHost::instanceName(void) const -{ - return m_pcInstanceName; -} - -/* - MDNSResponder::clsHost::addService -*/ -MDNSResponder::clsHost::stcService* MDNSResponder::clsHost::addService(const char* p_pcInstanceName, - const char* p_pcServiceType, - const char* p_pcProtocol, - uint16_t p_u16Port) -{ - stcService* pService = 0; - - if (((!p_pcInstanceName) || // NO name OR - (MDNS_DOMAIN_LABEL_MAXLENGTH >= os_strlen(p_pcInstanceName))) && // Fitting name - (p_pcServiceType) && - (MDNS_SERVICE_NAME_LENGTH >= os_strlen(p_pcServiceType)) && - (p_pcProtocol) && - ((MDNS_SERVICE_PROTOCOL_LENGTH - 1) != os_strlen(p_pcProtocol)) && - (p_u16Port)) - { - if (!((pService = findService((p_pcInstanceName ? : (m_pcInstanceName ? : m_pcHostName)), p_pcServiceType, p_pcProtocol, p_u16Port)))) // Not already used - { - if (0 != (pService = _allocService(p_pcInstanceName, p_pcServiceType, p_pcProtocol, p_u16Port))) - { - // Init probing - pService->m_ProbeInformation.m_ProbingStatus = enuProbingStatus::ReadyToStart; - } - } - } // else: bad arguments - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s addService: %s to add service '%s.%s.%s.local'!\n"), _DH(pService), (pService ? "Succeeded" : "FAILED"), (p_pcInstanceName ? : (m_pcInstanceName ? : (m_pcHostName ? : "-"))), (p_pcServiceType ? : ""), (p_pcProtocol ? : ""));); - DEBUG_EX_ERR(if (!pService) DEBUG_OUTPUT.printf_P(PSTR("%s addService: FAILED to add service '%s.%s.%s.local'!\n"), _DH(pService), (p_pcInstanceName ? : (m_pcInstanceName ? : (m_pcHostName ? : "-"))), (p_pcServiceType ? : ""), (p_pcProtocol ? : ""));); - return pService; -} - -/* - MDNSResponder::clsHost::removeService -*/ -bool MDNSResponder::clsHost::removeService(MDNSResponder::clsHost::stcService* p_pMDNSService) -{ - bool bResult = ((p_pMDNSService) && - (_announceService(*p_pMDNSService, false)) && - (_releaseService(p_pMDNSService))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _removeService: FAILED!\n"), _DH(p_pMDNSService));); - return bResult; -} - -/* - MDNSResponder::clsHost::findService (const) -*/ -const MDNSResponder::clsHost::stcService* MDNSResponder::clsHost::findService(const char* p_pcInstanceName, - const char* p_pcServiceType, - const char* p_pcProtocol, - uint16_t p_u16Port /*= 0*/) const -{ - stcService* pService = m_pServices; - while (pService) - { - if ((0 == strcmp(pService->m_pcName, p_pcInstanceName)) && - (0 == strcmp(pService->m_pcServiceType, p_pcServiceType)) && - (0 == strcmp(pService->m_pcProtocol, p_pcProtocol)) && - ((!p_u16Port) || - (p_u16Port == pService->m_u16Port))) - { - - break; - } - pService = pService->m_pNext; - } - return pService; -} - -/* - MDNSResponder::clsHost::findService -*/ -MDNSResponder::clsHost::stcService* MDNSResponder::clsHost::findService(const char* p_pcInstanceName, - const char* p_pcServiceType, - const char* p_pcProtocol, - uint16_t p_u16Port /*= 0*/) -{ - return (stcService*)((const clsHost*)this)->findService(p_pcInstanceName, p_pcServiceType, p_pcProtocol, p_u16Port); -} - -/* - MDNSResponder::clsHost::validateService -*/ -bool MDNSResponder::clsHost::validateService(const MDNSResponder::clsHost::stcService* p_pService) const -{ - const stcService* pService = m_pServices; - while (pService) - { - if (pService == p_pService) - { - break; - } - pService = pService->m_pNext; - } - return (0 != pService); -} - -/* - MDNSResponder::clsHost::setServiceName -*/ -bool MDNSResponder::clsHost::setServiceName(MDNSResponder::clsHost::stcService* p_pMDNSService, - const char* p_pcInstanceName) -{ - p_pcInstanceName = p_pcInstanceName ? : m_pcInstanceName; - - bool bResult = ((p_pMDNSService) && - ((!p_pcInstanceName) || - (MDNS_DOMAIN_LABEL_MAXLENGTH >= os_strlen(p_pcInstanceName))) && - (p_pMDNSService->setName(p_pcInstanceName)) && - ((p_pMDNSService->m_ProbeInformation.m_ProbingStatus = enuProbingStatus::ReadyToStart), true)); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _setServiceName: FAILED for '%s'!\n"), _DH(p_pMDNSService), (p_pcInstanceName ? : "-"));); - return bResult; -} - -/* - MDNSResponder::clsHost::setServiceName -*/ -const char* MDNSResponder::clsHost::serviceName(const stcService* p_pMDNSService) const -{ - return ((p_pMDNSService) - ? (p_pMDNSService->m_pcName) - : 0); -} - -/* - MDNSResponder::clsHost::serviceType -*/ -const char* MDNSResponder::clsHost::serviceType(const stcService* p_pMDNSService) const -{ - return ((p_pMDNSService) - ? (p_pMDNSService->m_pcServiceType) - : 0); -} - -/* - MDNSResponder::clsHost::serviceProtocol -*/ -const char* MDNSResponder::clsHost::serviceProtocol(const stcService* p_pMDNSService) const -{ - return ((p_pMDNSService) - ? (p_pMDNSService->m_pcProtocol) - : 0); -} - -/* - MDNSResponder::clsHost::servicePort -*/ -uint16_t MDNSResponder::clsHost::servicePort(const stcService* p_pMDNSService) const -{ - return ((p_pMDNSService) - ? (p_pMDNSService->m_u16Port) - : 0); -} - - -/* - MDNSResponder::clsHost::setServiceProbeResultCallback -*/ -bool MDNSResponder::clsHost::setServiceProbeResultCallback(stcService* p_pMDNSService, - ServiceProbeResultCallbackFn p_fnCallback) -{ - return ((p_pMDNSService) - ? ((p_pMDNSService->m_ProbeInformation.m_fnProbeResultCallback = p_fnCallback), true) - : false); -} - -/* - MDNSResponder::clsHost::setServiceName -*/ -bool MDNSResponder::clsHost::serviceProbeStatus(const stcService* p_pMDNSService) const -{ - return ((p_pMDNSService) && - (enuProbingStatus::Done == p_pMDNSService->m_ProbeInformation.m_ProbingStatus)); -} - - -/* - SERVICE TXT -*/ - -/* - MDNSResponder::clsHost::addServiceTxt -*/ -MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::addServiceTxt(stcService* p_pMDNSService, - const char* p_pcKey, - const char* p_pcValue) -{ - return _addServiceTxt(p_pMDNSService, p_pcKey, p_pcValue, false); -} - -/* - MDNSResponder::clsHost::removeServiceTxt -*/ -bool MDNSResponder::clsHost::removeServiceTxt(stcService* p_pMDNSService, - stcServiceTxt* p_pTxt) -{ - bool bResult = ((p_pMDNSService) && - (p_pTxt) && - (_releaseServiceTxt(p_pMDNSService, p_pTxt))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeServiceTxt: FAILED!\n"), _DH(p_pMDNSService));); - return bResult; -} - -/* - MDNSResponder::clsHost::findServiceTxt (const) -*/ -const MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::findServiceTxt(MDNSResponder::clsHost::stcService* p_pMDNSService, - const char* p_pcKey) const -{ - return (const stcServiceTxt*)((const clsHost*)this)->findServiceTxt(p_pMDNSService, p_pcKey); -} - -/* - MDNSResponder::clsHost::findServiceTxt -*/ -MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::findServiceTxt(MDNSResponder::clsHost::stcService* p_pMDNSService, - const char* p_pcKey) -{ - return _findServiceTxt(p_pMDNSService, p_pcKey); -} - -/* - MDNSResponder::clsHost::setDynamicServiceTxtCallback -*/ -bool MDNSResponder::clsHost::setDynamicServiceTxtCallback(DynamicServiceTxtCallbackFn p_fnCallback) -{ - m_fnServiceTxtCallback = p_fnCallback; - return true; -} - -/* - MDNSResponder::clsHost::setDynamicServiceTxtCallback -*/ -bool MDNSResponder::clsHost::setDynamicServiceTxtCallback(stcService* p_pMDNSService, - DynamicServiceTxtCallbackFn p_fnCallback) -{ - return ((p_pMDNSService) - ? ((p_pMDNSService->m_fnTxtCallback = p_fnCallback), true) - : false); -} - -/* - MDNSResponder::clsHost::addDynamicServiceTxt - - Add a (dynamic) MDNS TXT item ('key' = 'value') to the service - Dynamic TXT items are removed right after one-time use. So they need to be added - every time the value s needed (via callback). -*/ -MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::addDynamicServiceTxt(stcService* p_pMDNSService, - const char* p_pcKey, - const char* p_pcValue) -{ - return _addServiceTxt(p_pMDNSService, p_pcKey, p_pcValue, true); -} - - -/* - QUERIES -*/ -/* - MDNSResponder::clsHost::queryService -*/ -uint32_t MDNSResponder::clsHost::queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService '_%s._%s.local'\n"), _DH(), p_pcService, p_pcProtocol);); - - stcQuery* pMDNSQuery = 0; - if ((p_pcService) && (*p_pcService) && - (p_pcProtocol) && (*p_pcProtocol) && - (p_u16Timeout) && - ((pMDNSQuery = _allocQuery(stcQuery::enuQueryType::Service))) && - (_buildDomainForService(p_pcService, p_pcProtocol, pMDNSQuery->m_Domain))) - { - if ((_removeLegacyQuery()) && - ((pMDNSQuery->m_bLegacyQuery = true)) && - (_sendMDNSQuery(*pMDNSQuery))) - { - // Wait for answers to arrive - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); - delay(p_u16Timeout); - - // All answers should have arrived by now -> stop adding new answers - pMDNSQuery->m_bAwaitingAnswers = false; - } - else // FAILED to send query - { - _removeQuery(pMDNSQuery); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: INVALID input data!\n"), _DH());); - } - return ((pMDNSQuery) - ? pMDNSQuery->answerCount() - : 0); -} - -/* - MDNSResponder::clsHost::queryHost -*/ -uint32_t MDNSResponder::clsHost::queryHost(const char* p_pcHostName, - const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost '%s.local'\n"), _DH(), p_pcHostName);); - - stcQuery* pMDNSQuery = 0; - if ((p_pcHostName) && (*p_pcHostName) && - (p_u16Timeout) && - ((pMDNSQuery = _allocQuery(stcQuery::enuQueryType::Host))) && - (_buildDomainForHost(p_pcHostName, pMDNSQuery->m_Domain))) - { - if ((_removeLegacyQuery()) && - ((pMDNSQuery->m_bLegacyQuery = true)) && - (_sendMDNSQuery(*pMDNSQuery))) - { - // Wait for answers to arrive - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); - delay(p_u16Timeout); - - // All answers should have arrived by now -> stop adding new answers - pMDNSQuery->m_bAwaitingAnswers = false; - } - else // FAILED to send query - { - _removeQuery(pMDNSQuery); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: INVALID input data!\n"), _DH());); - } - return ((pMDNSQuery) - ? pMDNSQuery->answerCount() - : 0); -} - -/* - MDNSResponder::clsHost::removeQuery -*/ -bool MDNSResponder::clsHost::removeQuery(void) -{ - return _removeLegacyQuery(); -} - -/* - MDNSResponder::clsHost::hasQuery -*/ -bool MDNSResponder::clsHost::hasQuery(void) -{ - return (0 != _findLegacyQuery()); -} - -/* - MDNSResponder::clsHost::getQuery -*/ -MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::getQuery(void) -{ - return _findLegacyQuery(); -} - -/* - MDNSResponder::clsHost::installServiceQuery -*/ -MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - MDNSResponder::clsHost::QueryCallbackFn p_fnCallback) -{ - stcQuery* pMDNSQuery = 0; - if ((p_pcService) && (*p_pcService) && - (p_pcProtocol) && (*p_pcProtocol) && - (p_fnCallback) && - ((pMDNSQuery = _allocQuery(stcQuery::enuQueryType::Service))) && - (_buildDomainForService(p_pcService, p_pcProtocol, pMDNSQuery->m_Domain))) - { - - pMDNSQuery->m_fnCallback = p_fnCallback; - pMDNSQuery->m_bLegacyQuery = false; - - if (_sendMDNSQuery(*pMDNSQuery)) - { - pMDNSQuery->m_u8SentCount = 1; - pMDNSQuery->m_ResendTimeout.reset(MDNS_DYNAMIC_QUERY_RESEND_DELAY); - } - else - { - _removeQuery(pMDNSQuery); - } - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s installServiceQuery: %s for '_%s._%s.local'!\n\n"), _DH(), (pMDNSQuery ? "Succeeded" : "FAILED"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); - DEBUG_EX_ERR(if (!pMDNSQuery) DEBUG_OUTPUT.printf_P(PSTR("%s installServiceQuery: FAILED for '_%s._%s.local'!\n\n"), _DH(), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); - return pMDNSQuery; -} - -/* - MDNSResponder::clsHost::installHostQuery -*/ -MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::installHostQuery(const char* p_pcHostName, - MDNSResponder::clsHost::QueryCallbackFn p_fnCallback) -{ - stcQuery* pMDNSQuery = 0; - if ((p_pcHostName) && (*p_pcHostName)) - { - stcRRDomain domain; - pMDNSQuery = ((_buildDomainForHost(p_pcHostName, domain)) - ? _installDomainQuery(domain, stcQuery::enuQueryType::Host, p_fnCallback) - : 0); - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s installHostQuery: %s for '%s.local'!\n\n"), _DH(), (pMDNSQuery ? "Succeeded" : "FAILED"), (p_pcHostName ? : "-"));); - DEBUG_EX_ERR(if (!pMDNSQuery) DEBUG_OUTPUT.printf_P(PSTR("%s installHostQuery: FAILED for '%s.local'!\n\n"), _DH(), (p_pcHostName ? : "-"));); - return pMDNSQuery; -} - -/* - MDNSResponder::clsHost::removeQuery -*/ -bool MDNSResponder::clsHost::removeQuery(MDNSResponder::clsHost::stcQuery* p_pMDNSQuery) -{ - bool bResult = ((p_pMDNSQuery) && - (_removeQuery(p_pMDNSQuery))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeQuery: FAILED!\n"), _DH());); - return bResult; -} - - -/* - PROCESSING -*/ - -/* - MDNSResponder::clsHost::processUDPInput -*/ -bool MDNSResponder::clsHost::processUDPInput() -{ - bool bResult = false; - - bResult = ((_checkNetIfState()) && // Any changes in the netif state? - (_parseMessage())); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR(""));); - - return bResult; -} - -/* - MDNSResponder::clsHost::update -*/ -bool MDNSResponder::clsHost::update(void) -{ - return ((_checkNetIfState()) && // Any changes in the netif state? - (_updateProbeStatus()) && // Probing - (_checkQueryCache())); -} - -/* - MDNSResponder::clsHost::restart -*/ -bool MDNSResponder::clsHost::restart(void) -{ - return (_resetProbeStatus(true)); // Stop and restart probing -} - - - - - -/* - P R O T E C T E D -*/ - -/* - MDNSResponder::clsHost::_close -*/ -bool MDNSResponder::clsHost::_close(void) -{ - /* _resetProbeStatus(false); // Stop probing - - _releaseQueries(); - _releaseServices(); - _releaseHostName();*/ - - // Leave multicast group(s) -#ifdef MDNS_IPV4_SUPPORT - ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; - if (ERR_OK != igmp_leavegroup_netif(&m_rNetIf, ip_2_ip4(&multicast_addr_V4)/*(const struct ip4_addr *)&multicast_addr_V4.u_addr.ip4*/)) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); - } -#endif -#ifdef MDNS_IPV6_SUPPORT - ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; - if (ERR_OK != mld6_leavegroup_netif(&m_rNetIf, ip_2_ip6(&multicast_addr_V6)/*&(multicast_addr_V6.u_addr.ip6)*/)) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); - } -#endif - return true; -} - - -/* - NETIF -*/ - -/* - MDNSResponder::clsHost::_getNetIfState - - Returns the current netif state. - -*/ -MDNSResponder::clsHost::typeNetIfState MDNSResponder::clsHost::_getNetIfState(void) const -{ - typeNetIfState curNetIfState = static_cast<typeNetIfState>(enuNetIfState::None); - - if (netif_is_up(&m_rNetIf)) - { - curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::IsUp); - - // Check if netif link is up - if ((netif_is_link_up(&m_rNetIf)) && - ((&m_rNetIf != netif_get_by_index(WIFI_STA)) || - (STATION_GOT_IP == wifi_station_get_connect_status()))) - { - curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::LinkIsUp); - } - - // Check for IPv4 address - if (_getResponderIPAddress(enuIPProtocolType::V4).isSet()) - { - curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::IPv4); - } - // Check for IPv6 address - if (_getResponderIPAddress(enuIPProtocolType::V6).isSet()) - { - curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::IPv6); - } - } - return curNetIfState; -} - -/* - MDNSResponder::clsHost::_checkNetIfState - - Checks the netif state. - If eg. a new address appears, the announcing is restarted. - -*/ -bool MDNSResponder::clsHost::_checkNetIfState(void) -{ - typeNetIfState curNetIfState; - if (m_NetIfState != ((curNetIfState = _getNetIfState()))) - { - // Some state change happened - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: DID CHANGE NETIF STATE\n\n"), _DH());); - DEBUG_EX_INFO( - if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IsUp)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IsUp))) - { - DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Netif is up: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IsUp)) ? "YES" : "NO")); - } - if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp))) - { - DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Netif link is up: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp)) ? "YES" : "NO")); - } - if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4))) - { - DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv4 address is set: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4)) ? "YES" : "NO")); - if (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4)) - { - DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv4 address: %s\n"), _DH(), _getResponderIPAddress(enuIPProtocolType::V4).toString().c_str()); - } - } - if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6))) - { - DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv6 address is set: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6)) ? "YES" : "NO")); - if (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6)) - { - DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv6 address: %s\n"), _DH(), _getResponderIPAddress(enuIPProtocolType::V6).toString().c_str()); - } - } - ); - - if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask))) - { - // Link came up (restart() will alloc a m_pUDPContext, ...) or down (_restart() will remove an existing m_pUDPContext, ...) - restart(); - } - else if (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp)) - { - // Link is up (unchanged) - if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask))) - { - // IP state changed - // TODO: If just a new IP address was added, a simple re-announcement should be enough - restart(); - } - } - /* if (enuProbingStatus::Done == m_HostProbeInformation.m_ProbingStatus) { - // Probing is done, prepare to (re)announce host - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Preparing to (re)announce host.\n"));); - //m_HostProbeInformation.m_ProbingStatus = enuProbingStatus::Done; - m_HostProbeInformation.m_u8SentCount = 0; - m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); - }*/ - m_NetIfState = curNetIfState; - } - - bool bResult = ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask)) && // Continue if Link is UP - (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask))); // AND has any IP - //DEBUG_EX_INFO(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Link is DOWN or NO IP address!\n"), _DH());); - return bResult; -} - - -/* - DOMAIN NAMES -*/ - -/* - MDNSResponder::clsHost::_allocDomainName -*/ -bool MDNSResponder::clsHost::_allocDomainName(const char* p_pcNewDomainName, - char*& p_rpcDomainName) -{ - bool bResult = false; - - _releaseDomainName(p_rpcDomainName); - - size_t stLength = 0; - if ((p_pcNewDomainName) && - (MDNS_DOMAIN_LABEL_MAXLENGTH >= (stLength = strlen(p_pcNewDomainName)))) // char max size for a single label - { - // Copy in hostname characters as lowercase - if ((bResult = (0 != (p_rpcDomainName = new char[stLength + 1])))) - { -#ifdef MDNS_FORCE_LOWERCASE_HOSTNAME - size_t i = 0; - for (; i < stLength; ++i) - { - p_rpcDomainName[i] = (isupper(p_pcNewDomainName[i]) ? tolower(p_pcNewDomainName[i]) : p_pcNewDomainName[i]); - } - p_rpcDomainName[i] = 0; -#else - strncpy(p_rpcDomainName, p_pcNewDomainName, (stLength + 1)); -#endif - } - } - return bResult; -} - -/* - MDNSResponder::clsHost::_releaseDomainName -*/ -bool MDNSResponder::clsHost::_releaseDomainName(char*& p_rpcDomainName) -{ - bool bResult; - if ((bResult = (0 != p_rpcDomainName))) - { - delete[] p_rpcDomainName; - p_rpcDomainName = 0; - } - return bResult; -} - -/* - MDNSResponder::clsHost::_allocHostName -*/ -bool MDNSResponder::clsHost::_allocHostName(const char* p_pcHostName) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocHostName (%s)\n"), _DH(), p_pcHostName);); - return _allocDomainName(p_pcHostName, m_pcHostName); -} - -/* - MDNSResponder::clsHost::_releaseHostName -*/ -bool MDNSResponder::clsHost::_releaseHostName(void) -{ - return _releaseDomainName(m_pcHostName); -} - -/* - MDNSResponder::clsHost::_allocInstanceName -*/ -bool MDNSResponder::clsHost::_allocInstanceName(const char* p_pcInstanceName) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocInstanceName (%s)\n"), _DH(), p_pcHostName);); - return _allocDomainName(p_pcInstanceName, m_pcInstanceName); -} - -/* - MDNSResponder::clsHost::_releaseInstanceName -*/ -bool MDNSResponder::clsHost::_releaseInstanceName(void) -{ - return _releaseDomainName(m_pcInstanceName); -} - - -/* - SERVICE -*/ - -/* - MDNSResponder::clsHost::_allocService -*/ -MDNSResponder::clsHost::stcService* MDNSResponder::clsHost::_allocService(const char* p_pcName, - const char* p_pcServiceType, - const char* p_pcProtocol, - uint16_t p_u16Port) -{ - stcService* pService = 0; - if (((!p_pcName) || - (MDNS_DOMAIN_LABEL_MAXLENGTH >= strlen(p_pcName))) && - (p_pcServiceType) && - (MDNS_SERVICE_NAME_LENGTH >= strlen(p_pcServiceType)) && - (p_pcProtocol) && - (MDNS_SERVICE_PROTOCOL_LENGTH >= strlen(p_pcProtocol)) && - (p_u16Port) && - (0 != ((pService = new stcService))) && - (pService->setName(p_pcName ? : (m_pcInstanceName ? : m_pcHostName))) && - (pService->setServiceType(p_pcServiceType)) && - (pService->setProtocol(p_pcProtocol))) - { - pService->m_bAutoName = (0 == p_pcName); - pService->m_u16Port = p_u16Port; - - // Add to list (or start list) - pService->m_pNext = m_pServices; - m_pServices = pService; - } - return pService; -} - -/* - MDNSResponder::clsHost::_releaseService -*/ -bool MDNSResponder::clsHost::_releaseService(MDNSResponder::clsHost::stcService* p_pService) -{ - bool bResult = false; - - if (p_pService) - { - stcService* pPred = m_pServices; - while ((pPred) && - (pPred->m_pNext != p_pService)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pService->m_pNext; - delete p_pService; - bResult = true; - } - else // No predecesor - { - if (m_pServices == p_pService) - { - m_pServices = p_pService->m_pNext; - delete p_pService; - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _releaseService: INVALID service!"), _DH(p_pService));); - } - } - } - return bResult; -} - - -/* - SERVICE TXT -*/ - -/* - MDNSResponder::clsHost::_allocServiceTxt -*/ -MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::_allocServiceTxt(MDNSResponder::clsHost::stcService* p_pService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp) -{ - stcServiceTxt* pTxt = 0; - - if ((p_pService) && - (p_pcKey) && - (MDNS_SERVICE_TXT_MAXLENGTH > (p_pService->m_Txts.length() + - 1 + // Length byte - (p_pcKey ? strlen(p_pcKey) : 0) + - 1 + // '=' - (p_pcValue ? strlen(p_pcValue) : 0)))) - { - - pTxt = new stcServiceTxt; - if (pTxt) - { - size_t stLength = (p_pcKey ? strlen(p_pcKey) : 0); - pTxt->m_pcKey = new char[stLength + 1]; - if (pTxt->m_pcKey) - { - strncpy(pTxt->m_pcKey, p_pcKey, stLength); pTxt->m_pcKey[stLength] = 0; - } - - if (p_pcValue) - { - stLength = (p_pcValue ? strlen(p_pcValue) : 0); - pTxt->m_pcValue = new char[stLength + 1]; - if (pTxt->m_pcValue) - { - strncpy(pTxt->m_pcValue, p_pcValue, stLength); pTxt->m_pcValue[stLength] = 0; - } - } - pTxt->m_bTemp = p_bTemp; - - // Add to list (or start list) - p_pService->m_Txts.add(pTxt); - } - } - return pTxt; -} - -/* - MDNSResponder::clsHost::_releaseServiceTxt -*/ -bool MDNSResponder::clsHost::_releaseServiceTxt(MDNSResponder::clsHost::stcService* p_pService, - MDNSResponder::clsHost::stcServiceTxt* p_pTxt) -{ - return ((p_pService) && - (p_pTxt) && - (p_pService->m_Txts.remove(p_pTxt))); -} - -/* - MDNSResponder::clsHost::_updateServiceTxt -*/ -MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::_updateServiceTxt(MDNSResponder::clsHost::stcService* p_pService, - MDNSResponder::clsHost::stcServiceTxt* p_pTxt, - const char* p_pcValue, - bool p_bTemp) -{ - if ((p_pService) && - (p_pTxt) && - (MDNS_SERVICE_TXT_MAXLENGTH > (p_pService->m_Txts.length() - - (p_pTxt->m_pcValue ? strlen(p_pTxt->m_pcValue) : 0) + - (p_pcValue ? strlen(p_pcValue) : 0)))) - { - p_pTxt->update(p_pcValue); - p_pTxt->m_bTemp = p_bTemp; - } - return p_pTxt; -} - -/* - MDNSResponder::clsHost::_findServiceTxt -*/ -MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::_findServiceTxt(MDNSResponder::clsHost::stcService* p_pService, - const char* p_pcKey) -{ - return (p_pService ? p_pService->m_Txts.find(p_pcKey) : 0); -} - -/* - MDNSResponder::clsHost::_addServiceTxt -*/ -MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::_addServiceTxt(MDNSResponder::clsHost::stcService* p_pService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp) -{ - stcServiceTxt* pResult = 0; - - if ((p_pService) && - (p_pcKey) && - (strlen(p_pcKey))) - { - - stcServiceTxt* pTxt = p_pService->m_Txts.find(p_pcKey); - if (pTxt) - { - pResult = _updateServiceTxt(p_pService, pTxt, p_pcValue, p_bTemp); - } - else - { - pResult = _allocServiceTxt(p_pService, p_pcKey, p_pcValue, p_bTemp); - } - } - return pResult; -} - -/* - MDNSResponder::clsHost::_answerKeyValue - / - MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::_answerKeyValue(const MDNSResponder::clsHost::stcQuery p_pQuery, - const uint32_t p_u32AnswerIndex) - { - stcQuery::stcAnswer* pSQAnswer = (p_pQuery ? p_pQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcTxts (if not already done) - return (pSQAnswer) ? pSQAnswer->m_Txts.m_pTxts : 0; - }*/ - -/* - MDNSResponder::clsHost::_collectServiceTxts -*/ -bool MDNSResponder::clsHost::_collectServiceTxts(MDNSResponder::clsHost::stcService& p_rService) -{ - if (m_fnServiceTxtCallback) - { - //m_fnServiceTxtCallback(*this, p_pService); - } - if (p_rService.m_fnTxtCallback) - { - //p_pService->m_fnTxtCallback(*this, p_pService); - } - return true; -} - -/* - MDNSResponder::clsHost::_releaseTempServiceTxts -*/ -bool MDNSResponder::clsHost::_releaseTempServiceTxts(MDNSResponder::clsHost::stcService& p_rService) -{ - return (p_rService.m_Txts.removeTempTxts()); -} - - -/* - QUERIES -*/ - -/* - MDNSResponder::_allocQuery -*/ -MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::_allocQuery(MDNSResponder::clsHost::stcQuery::enuQueryType p_QueryType) -{ - stcQuery* pQuery = new stcQuery(p_QueryType); - if (pQuery) - { - // Link to query list - pQuery->m_pNext = m_pQueries; - m_pQueries = pQuery; - } - return m_pQueries; -} - -/* - MDNSResponder:clsHost:::_removeQuery -*/ -bool MDNSResponder::clsHost::_removeQuery(MDNSResponder::clsHost::stcQuery* p_pQuery) -{ - bool bResult = false; - - if (p_pQuery) - { - stcQuery* pPred = m_pQueries; - while ((pPred) && - (pPred->m_pNext != p_pQuery)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pQuery->m_pNext; - delete p_pQuery; - bResult = true; - } - else // No predecesor - { - if (m_pQueries == p_pQuery) - { - m_pQueries = p_pQuery->m_pNext; - delete p_pQuery; - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _releaseQuery: INVALID query!"), _DH());); - } - } - } - return bResult; -} - -/* - MDNSResponder::clsHost::_removeLegacyQuery -*/ -bool MDNSResponder::clsHost::_removeLegacyQuery(void) -{ - stcQuery* pLegacyQuery = 0; - return (((pLegacyQuery = _findLegacyQuery())) - ? _removeQuery(pLegacyQuery) - : false); -} - -/* - MDNSResponder::clsHost::_findLegacyQuery -*/ -MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::_findLegacyQuery(void) -{ - stcQuery* pLegacyQuery = m_pQueries; - while (pLegacyQuery) - { - if (pLegacyQuery->m_bLegacyQuery) - { - break; - } - pLegacyQuery = pLegacyQuery->m_pNext; - } - return pLegacyQuery; -} - -/* - MDNSResponder::clsHost::_releaseQueries -*/ -bool MDNSResponder::clsHost::_releaseQueries(void) -{ - while (m_pQueries) - { - stcQuery* pNext = m_pQueries->m_pNext; - delete m_pQueries; - m_pQueries = pNext; - } - return true; -} - -/* - MDNSResponder::clsHost::_findNextQueryByDomain -*/ -MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::_findNextQueryByDomain(const MDNSResponder::clsHost::stcRRDomain& p_Domain, - const MDNSResponder::clsHost::stcQuery::enuQueryType p_QueryType, - const stcQuery* p_pPrevQuery) -{ - stcQuery* pMatchingQuery = 0; - - stcQuery* pQuery = (p_pPrevQuery ? p_pPrevQuery->m_pNext : m_pQueries); - while (pQuery) - { - if (((stcQuery::enuQueryType::None == p_QueryType) || - (pQuery->m_QueryType == p_QueryType)) && - (p_Domain == pQuery->m_Domain)) - { - - pMatchingQuery = pQuery; - break; - } - pQuery = pQuery->m_pNext; - } - return pMatchingQuery; -} - -/* - MDNSResponder::clsHost::_installDomainQuery -*/ -MDNSResponder::clsHost::stcQuery* MDNSResponder::clsHost::_installDomainQuery(MDNSResponder::clsHost::stcRRDomain& p_Domain, - MDNSResponder::clsHost::stcQuery::enuQueryType p_QueryType, - MDNSResponder::clsHost::QueryCallbackFn p_fnCallback) -{ - stcQuery* pQuery = 0; - - if ((p_fnCallback) && - ((pQuery = _allocQuery(p_QueryType)))) - { - pQuery->m_Domain = p_Domain; - pQuery->m_fnCallback = p_fnCallback; - pQuery->m_bLegacyQuery = false; - - if (_sendMDNSQuery(*pQuery)) - { - pQuery->m_u8SentCount = 1; - pQuery->m_ResendTimeout.reset(MDNS_DYNAMIC_QUERY_RESEND_DELAY); - } - else - { - _removeQuery(pQuery); - } - } - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("%s _installDomainQuery: %s for "), (pQuery ? "Succeeded" : "FAILED"), _DH()); - _printRRDomain(p_Domain); - DEBUG_OUTPUT.println(); - ); - DEBUG_EX_ERR( - if (!pQuery) -{ - DEBUG_OUTPUT.printf_P(PSTR("%s _installDomainQuery: FAILED for "), _DH()); - _printRRDomain(p_Domain); - DEBUG_OUTPUT.println(); - } - ); - return pQuery; -} - -/* - MDNSResponder::clsHost::_hasQueriesWaitingForAnswers -*/ -bool MDNSResponder::clsHost::_hasQueriesWaitingForAnswers(void) const -{ - bool bOpenQueries = false; - - for (stcQuery* pQuery = m_pQueries; pQuery; pQuery = pQuery->m_pNext) - { - if (pQuery->m_bAwaitingAnswers) - { - bOpenQueries = true; - break; - } - } - return bOpenQueries; -} - -/* - MDNSResponder::clsHost::_executeQueryCallback -*/ -bool MDNSResponder::clsHost::_executeQueryCallback(const stcQuery& p_Query, - const stcQuery::stcAnswer& p_Answer, - typeQueryAnswerType p_QueryAnswerTypeFlags, - bool p_bSetContent) -{ - if (p_Query.m_fnCallback) - { - p_Query.m_fnCallback(*this, p_Query, p_Answer, p_QueryAnswerTypeFlags, p_bSetContent); - } - return true; -} - - - -} // namespace MDNSImplementation - -} // namespace esp8266 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Host.hpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Host.hpp deleted file mode 100755 index 4a5ff6f39d..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Host.hpp +++ /dev/null @@ -1,1177 +0,0 @@ -/* - LEAmDNS2_Host.hpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -/** - clsHost & clsHostList -*/ -class clsHost -{ -public: - - // File: ..._Host_Structs - /** - typeIPProtocolType & enuIPProtocolType - */ - using typeIPProtocolType = uint8_t; - enum class enuIPProtocolType : typeIPProtocolType - { -#ifdef MDNS_IPV4_SUPPORT - V4 = 0x01, -#endif -#ifdef MDNS_IPV6_SUPPORT - V6 = 0x02, -#endif - }; - - /** - typeNetIfState & enuNetIfState - */ - using typeNetIfState = uint8_t; - enum class enuNetIfState : typeNetIfState - { - None = 0x00, - - IsUp = 0x01, - UpMask = (IsUp), - - LinkIsUp = 0x02, - LinkMask = (LinkIsUp), - - IPv4 = 0x04, - IPv6 = 0x08, - IPMask = (IPv4 | IPv6), - }; - - /** - stcServiceTxt - */ - struct stcServiceTxt - { - stcServiceTxt* m_pNext; - char* m_pcKey; - char* m_pcValue; - bool m_bTemp; - - stcServiceTxt(const char* p_pcKey = 0, - const char* p_pcValue = 0, - bool p_bTemp = false); - stcServiceTxt(const stcServiceTxt& p_Other); - ~stcServiceTxt(void); - - stcServiceTxt& operator=(const stcServiceTxt& p_Other); - bool clear(void); - - char* allocKey(size_t p_stLength); - bool setKey(const char* p_pcKey, - size_t p_stLength); - bool setKey(const char* p_pcKey); - bool releaseKey(void); - - char* allocValue(size_t p_stLength); - bool setValue(const char* p_pcValue, - size_t p_stLength); - bool setValue(const char* p_pcValue); - bool releaseValue(void); - - bool set(const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp = false); - - bool update(const char* p_pcValue); - - size_t length(void) const; - }; - - /** - stcServiceTxts - */ - struct stcServiceTxts - { - stcServiceTxt* m_pTxts; - char* m_pcCache; - - stcServiceTxts(void); - stcServiceTxts(const stcServiceTxts& p_Other); - ~stcServiceTxts(void); - - stcServiceTxts& operator=(const stcServiceTxts& p_Other); - - bool clear(void); - bool clearCache(void); - - bool add(stcServiceTxt* p_pTxt); - bool remove(stcServiceTxt* p_pTxt); - - bool removeTempTxts(void); - - stcServiceTxt* find(const char* p_pcKey); - const stcServiceTxt* find(const char* p_pcKey) const; - stcServiceTxt* find(const stcServiceTxt* p_pTxt); - - uint16_t length(void) const; - - size_t c_strLength(void) const; - bool c_str(char* p_pcBuffer); - const char* c_str(void) const; - - size_t bufferLength(void) const; - bool buffer(char* p_pcBuffer); - - bool compare(const stcServiceTxts& p_Other) const; - bool operator==(const stcServiceTxts& p_Other) const; - bool operator!=(const stcServiceTxts& p_Other) const; - }; - - /** - typeProbingStatus & enuProbingStatus - */ - using typeProbingStatus = uint8_t; - enum class enuProbingStatus : typeProbingStatus - { - WaitingForData, - ReadyToStart, - InProgress, - Done - }; - - /** - stcProbeInformation_Base - */ - struct stcProbeInformation_Base - { - enuProbingStatus m_ProbingStatus; - uint8_t m_u8SentCount; // Used for probes and announcements - esp8266::polledTimeout::oneShot m_Timeout; // Used for probes and announcements - bool m_bConflict; - bool m_bTiebreakNeeded; - - stcProbeInformation_Base(void); - - bool clear(void); // No 'virtual' needed, no polymorphic use (save 4 bytes) - }; - - /** - HostProbeResultCallbackFn - Callback function for host domain probe results - */ - using HostProbeResultCallbackFn = std::function<void(clsHost& p_rHost, - const char* p_pcDomainName, - bool p_bProbeResult)>; - /** - MDNSServiceProbeResultCallbackFn - Callback function for service domain probe results - */ - struct stcService; - using ServiceProbeResultCallbackFn = std::function<void(clsHost& p_rHost, - stcService& p_rMDNSService, - const char* p_pcDomainName, - bool p_bProbeResult)>; - - /** - stcProbeInformation_Host - */ - struct stcProbeInformation_Host : public stcProbeInformation_Base - { - HostProbeResultCallbackFn m_fnProbeResultCallback; - - stcProbeInformation_Host(void); - - bool clear(bool p_bClearUserdata = false); - }; - - /** - stcProbeInformation_Service - */ - struct stcProbeInformation_Service : public stcProbeInformation_Base - { - ServiceProbeResultCallbackFn m_fnProbeResultCallback; - - stcProbeInformation_Service(void); - - bool clear(bool p_bClearUserdata = false); - }; - - /** - DynamicServiceTxtCallbackFn - Callback function for dynamic MDNS TXT items - */ - struct stcService; - using DynamicServiceTxtCallbackFn = std::function<void(clsHost& p_rHost, - stcService& p_rMDNSService)>; - - /** - stcService - */ - struct stcService - { - stcService* m_pNext; - char* m_pcName; - bool m_bAutoName; // Name was set automatically to hostname (if no name was supplied) - char* m_pcServiceType; - char* m_pcProtocol; - uint16_t m_u16Port; - uint32_t m_u32ReplyMask; - stcServiceTxts m_Txts; - DynamicServiceTxtCallbackFn m_fnTxtCallback; - stcProbeInformation_Service m_ProbeInformation; - - stcService(const char* p_pcName = 0, - const char* p_pcServiceType = 0, - const char* p_pcProtocol = 0); - ~stcService(void); - - bool setName(const char* p_pcName); - bool releaseName(void); - - bool setServiceType(const char* p_pcService); - bool releaseServiceType(void); - - bool setProtocol(const char* p_pcProtocol); - bool releaseProtocol(void); - - bool probeStatus(void) const; - }; - - /** - typeContentFlag & enuContentFlag - */ - using typeContentFlag = uint16_t; - enum class enuContentFlag : typeContentFlag - { - // Host - A = 0x0001, - PTR_IPv4 = 0x0002, - PTR_IPv6 = 0x0004, - AAAA = 0x0008, - // Service - PTR_TYPE = 0x0010, - PTR_NAME = 0x0020, - TXT = 0x0040, - SRV = 0x0080, - // DNSSEC - NSEC = 0x0100, - - PTR = (PTR_IPv4 | PTR_IPv6 | PTR_TYPE | PTR_NAME) - }; - - /** - stcMsgHeader - */ - struct stcMsgHeader - { - uint16_t m_u16ID; // Identifier - bool m_1bQR : 1; // Query/Response flag - uint8_t m_4bOpcode : 4; // Operation code - bool m_1bAA : 1; // Authoritative Answer flag - bool m_1bTC : 1; // Truncation flag - bool m_1bRD : 1; // Recursion desired - bool m_1bRA : 1; // Recursion available - uint8_t m_3bZ : 3; // Zero - uint8_t m_4bRCode : 4; // Response code - uint16_t m_u16QDCount; // Question count - uint16_t m_u16ANCount; // Answer count - uint16_t m_u16NSCount; // Authority Record count - uint16_t m_u16ARCount; // Additional Record count - - stcMsgHeader(uint16_t p_u16ID = 0, - bool p_bQR = false, - uint8_t p_u8Opcode = 0, - bool p_bAA = false, - bool p_bTC = false, - bool p_bRD = false, - bool p_bRA = false, - uint8_t p_u8RCode = 0, - uint16_t p_u16QDCount = 0, - uint16_t p_u16ANCount = 0, - uint16_t p_u16NSCount = 0, - uint16_t p_u16ARCount = 0); - }; - - /** - stcRRDomain - */ - struct stcRRDomain - { - char m_acName[MDNS_DOMAIN_MAXLENGTH]; // Encoded domain name - uint16_t m_u16NameLength; // Length (incl. '\0') - char* m_pcDecodedName; - - stcRRDomain(void); - stcRRDomain(const stcRRDomain& p_Other); - ~stcRRDomain(void); - - stcRRDomain& operator=(const stcRRDomain& p_Other); - - bool clear(void); - bool clearNameCache(void); - - bool addLabel(const char* p_pcLabel, - bool p_bPrependUnderline = false); - - bool compare(const stcRRDomain& p_Other) const; - bool operator==(const stcRRDomain& p_Other) const; - bool operator!=(const stcRRDomain& p_Other) const; - bool operator>(const stcRRDomain& p_Other) const; - - size_t c_strLength(void) const; - bool c_str(char* p_pcBuffer) const; - const char* c_str(void) const; - }; - - /** - stcRRAttributes - */ - struct stcRRAttributes - { - uint16_t m_u16Type; // Type - uint16_t m_u16Class; // Class, nearly always 'IN' - - stcRRAttributes(uint16_t p_u16Type = 0, - uint16_t p_u16Class = 1 /*DNS_RRCLASS_IN Internet*/); - stcRRAttributes(const stcRRAttributes& p_Other); - - stcRRAttributes& operator=(const stcRRAttributes& p_Other); - }; - - /** - stcRRHeader - */ - struct stcRRHeader - { - stcRRDomain m_Domain; - stcRRAttributes m_Attributes; - - stcRRHeader(void); - stcRRHeader(const stcRRHeader& p_Other); - - stcRRHeader& operator=(const stcRRHeader& p_Other); - - bool clear(void); - }; - - /** - stcRRQuestion - */ - struct stcRRQuestion - { - stcRRQuestion* m_pNext; - stcRRHeader m_Header; - bool m_bUnicast; // Unicast reply requested - - stcRRQuestion(void); - }; - - /** - stcNSECBitmap - */ - struct stcNSECBitmap - { - uint8_t m_au8BitmapData[6]; // 6 bytes data - - stcNSECBitmap(void); - - bool clear(void); - uint16_t length(void) const; - bool setBit(uint16_t p_u16Bit); - bool getBit(uint16_t p_u16Bit) const; - }; - - /** - typeAnswerType & enuAnswerType - */ - using typeAnswerType = uint8_t; - enum class enuAnswerType : typeAnswerType - { - A, - PTR, - TXT, - AAAA, - SRV, - //NSEC, - Generic - }; - - /** - stcRRAnswer - */ - struct stcRRAnswer - { - stcRRAnswer* m_pNext; - const enuAnswerType m_AnswerType; - stcRRHeader m_Header; - bool m_bCacheFlush; // Cache flush command bit - uint32_t m_u32TTL; // Validity time in seconds - - virtual ~stcRRAnswer(void); - - enuAnswerType answerType(void) const; - - bool clear(void); - - protected: - stcRRAnswer(enuAnswerType p_AnswerType, - const stcRRHeader& p_Header, - uint32_t p_u32TTL); - }; - -#ifdef MDNS_IPV4_SUPPORT - /** - stcRRAnswerA - */ - struct stcRRAnswerA : public stcRRAnswer - { - IPAddress m_IPAddress; - - stcRRAnswerA(const stcRRHeader& p_Header, - uint32_t p_u32TTL); - ~stcRRAnswerA(void); - - bool clear(void); - }; -#endif - - /** - stcRRAnswerPTR - */ - struct stcRRAnswerPTR : public stcRRAnswer - { - stcRRDomain m_PTRDomain; - - stcRRAnswerPTR(const stcRRHeader& p_Header, - uint32_t p_u32TTL); - ~stcRRAnswerPTR(void); - - bool clear(void); - }; - - /** - stcRRAnswerTXT - */ - struct stcRRAnswerTXT : public stcRRAnswer - { - stcServiceTxts m_Txts; - - stcRRAnswerTXT(const stcRRHeader& p_Header, - uint32_t p_u32TTL); - ~stcRRAnswerTXT(void); - - bool clear(void); - }; - -#ifdef MDNS_IPV6_SUPPORT - /** - stcRRAnswerAAAA - */ - struct stcRRAnswerAAAA : public stcRRAnswer - { - IPAddress m_IPAddress; - - stcRRAnswerAAAA(const stcRRHeader& p_Header, - uint32_t p_u32TTL); - ~stcRRAnswerAAAA(void); - - bool clear(void); - }; -#endif - - /** - stcRRAnswerSRV - */ - struct stcRRAnswerSRV : public stcRRAnswer - { - uint16_t m_u16Priority; - uint16_t m_u16Weight; - uint16_t m_u16Port; - stcRRDomain m_SRVDomain; - - stcRRAnswerSRV(const stcRRHeader& p_Header, - uint32_t p_u32TTL); - ~stcRRAnswerSRV(void); - - bool clear(void); - }; - - /** - stcRRAnswerGeneric - */ - struct stcRRAnswerGeneric : public stcRRAnswer - { - uint16_t m_u16RDLength; // Length of variable answer - uint8_t* m_pu8RDData; // Offset of start of variable answer in packet - - stcRRAnswerGeneric(const stcRRHeader& p_Header, - uint32_t p_u32TTL); - ~stcRRAnswerGeneric(void); - - bool clear(void); - }; - - - /** - stcSendParameter - */ - struct stcSendParameter - { - protected: - /** - stcDomainCacheItem - */ - struct stcDomainCacheItem - { - stcDomainCacheItem* m_pNext; - const void* m_pHostNameOrService; // Opaque id for host or service domain (pointer) - bool m_bAdditionalData; // Opaque flag for special info (service domain included) - uint16_t m_u16Offset; // Offset in UDP output buffer - - stcDomainCacheItem(const void* p_pHostNameOrService, - bool p_bAdditionalData, - uint32_t p_u16Offset); - }; - - public: - /** - typeResponseType & enuResponseType - */ - using typeResponseType = uint8_t; - enum class enuResponseType : typeResponseType - { - None, - Response, - Unsolicited - }; - - uint16_t m_u16ID; // Query ID (used only in lagacy queries) - stcRRQuestion* m_pQuestions; // A list of queries - uint32_t m_u32HostReplyMask; // Flags for reply components/answers - bool m_bLegacyQuery; // Flag: Legacy query - enuResponseType m_Response; // Enum: Response to a query - bool m_bAuthorative; // Flag: Authorative (owner) response - bool m_bCacheFlush; // Flag: Clients should flush their caches - bool m_bUnicast; // Flag: Unicast response - bool m_bUnannounce; // Flag: Unannounce service - - // Temp content; created while processing _prepareMessage - uint16_t m_u16Offset; // Current offset in UDP write buffer (mainly for domain cache) - stcDomainCacheItem* m_pDomainCacheItems; // Cached host and service domains - - stcSendParameter(void); - ~stcSendParameter(void); - - bool clear(void); - bool flushQuestions(void); - bool flushDomainCache(void); - bool flushTempContent(void); - - bool shiftOffset(uint16_t p_u16Shift); - - bool addDomainCacheItem(const void* p_pHostNameOrService, - bool p_bAdditionalData, - uint16_t p_u16Offset); - uint16_t findCachedDomainOffset(const void* p_pHostNameOrService, - bool p_bAdditionalData) const; - }; - - - // QUERIES & ANSWERS - /** - typeQueryAnswerType & enuQueryAnswerType - */ - using typeQueryAnswerType = uint8_t; - enum class enuQueryAnswerType : typeQueryAnswerType - { - Unknown = 0x00, - ServiceDomain = 0x01, // Service domain - HostDomain = 0x02, // Host domain - Port = 0x04, // Port - Txts = 0x08, // TXT items -#ifdef MDNS_IPV4_SUPPORT - IPv4Address = 0x10, // IPv4 address -#endif -#ifdef MDNS_IPV6_SUPPORT - IPv6Address = 0x20, // IPv6 address -#endif - }; - - /** - stcQuery - */ - struct stcQuery - { - /** - stcAnswer - */ - struct stcAnswer - { - /** - stcTTL - */ - struct stcTTL - { - /** - typeTimeoutLevel & enuTimeoutLevel - */ - using typeTimeoutLevel = uint8_t; - enum class enuTimeoutLevel : typeTimeoutLevel - { - None = 0, - Base = 80, - Interval = 5, - Final = 100 - }; - - uint32_t m_u32TTL; - esp8266::polledTimeout::oneShot m_TTLTimeout; - typeTimeoutLevel m_TimeoutLevel; - - stcTTL(void); - bool set(uint32_t p_u32TTL); - - bool flagged(void) const; - bool restart(void); - - bool prepareDeletion(void); - bool finalTimeoutLevel(void) const; - - unsigned long timeout(void) const; - }; - /** - stcIPAddress - */ - struct stcIPAddress - { - stcIPAddress* m_pNext; - IPAddress m_IPAddress; - stcTTL m_TTL; - - stcIPAddress(IPAddress p_IPAddress, - uint32_t p_u32TTL = 0); - }; - - stcAnswer* m_pNext; - // The service domain is the first 'answer' (from PTR answer, using service and protocol) to be set - // Defines the key for additional answer, like host domain, etc. - stcRRDomain m_ServiceDomain; // 1. level answer (PTR), eg. MyESP._http._tcp.local - stcTTL m_TTLServiceDomain; - stcRRDomain m_HostDomain; // 2. level answer (SRV, using service domain), eg. esp8266.local - uint16_t m_u16Port; // 2. level answer (SRV, using service domain), eg. 5000 - stcTTL m_TTLHostDomainAndPort; - stcServiceTxts m_Txts; // 2. level answer (TXT, using service domain), eg. c#=1 - stcTTL m_TTLTxts; -#ifdef MDNS_IPV4_SUPPORT - stcIPAddress* m_pIPv4Addresses; // 3. level answer (A, using host domain), eg. 123.456.789.012 -#endif -#ifdef MDNS_IPV6_SUPPORT - stcIPAddress* m_pIPv6Addresses; // 3. level answer (AAAA, using host domain), eg. 1234::09 -#endif - typeQueryAnswerType m_QueryAnswerFlags; // enuQueryAnswerType - - stcAnswer(void); - ~stcAnswer(void); - - bool clear(void); - -#ifdef MDNS_IPV4_SUPPORT - bool releaseIPv4Addresses(void); - bool addIPv4Address(stcIPAddress* p_pIPAddress); - bool removeIPv4Address(stcIPAddress* p_pIPAddress); - const stcIPAddress* findIPv4Address(const IPAddress& p_IPAddress) const; - stcIPAddress* findIPv4Address(const IPAddress& p_IPAddress); - uint32_t IPv4AddressCount(void) const; - const stcIPAddress* IPv4AddressAtIndex(uint32_t p_u32Index) const; - stcIPAddress* IPv4AddressAtIndex(uint32_t p_u32Index); -#endif -#ifdef MDNS_IPV6_SUPPORT - bool releaseIPv6Addresses(void); - bool addIPv6Address(stcIPAddress* p_pIPAddress); - bool removeIPv6Address(stcIPAddress* p_pIPAddress); - const stcIPAddress* findIPv6Address(const IPAddress& p_IPAddress) const; - stcIPAddress* findIPv6Address(const IPAddress& p_IPAddress); - uint32_t IPv6AddressCount(void) const; - const stcIPAddress* IPv6AddressAtIndex(uint32_t p_u32Index) const; - stcIPAddress* IPv6AddressAtIndex(uint32_t p_u32Index); -#endif - }; //stcAnswer - - /** - typeQueryType & enuQueryType - */ - using typeQueryType = uint8_t; - enum class enuQueryType : typeQueryType - { - None, - Service, - Host - }; - using _QueryCallbackFn = std::function<void(clsHost& p_rHost, - const stcQuery& p_Query, - const stcAnswer& p_Answer, - typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item - bool p_bSetContent)>; // true: Answer component set, false: component deleted - - stcQuery* m_pNext; - enuQueryType m_QueryType; - stcRRDomain m_Domain; // Type:Service -> _http._tcp.local; Type:Host -> esp8266.local - _QueryCallbackFn m_fnCallback; - bool m_bLegacyQuery; - uint8_t m_u8SentCount; - esp8266::polledTimeout::oneShot m_ResendTimeout; - bool m_bAwaitingAnswers; - stcAnswer* m_pAnswers; - - stcQuery(const enuQueryType p_QueryType); - ~stcQuery(void); - - bool clear(void); - - uint32_t answerCount(void) const; - const stcAnswer* answerAtIndex(uint32_t p_u32Index) const; - stcAnswer* answerAtIndex(uint32_t p_u32Index); - uint32_t indexOfAnswer(const stcAnswer* p_pAnswer) const; - - bool addAnswer(stcAnswer* p_pAnswer); - bool removeAnswer(stcAnswer* p_pAnswer); - - stcAnswer* findAnswerForServiceDomain(const stcRRDomain& p_ServiceDomain); - stcAnswer* findAnswerForHostDomain(const stcRRDomain& p_HostDomain); - }; - /** - QueryCallbackFn - - Callback function for received answers for dynamic queries - */ - using QueryCallbackFn = stcQuery::_QueryCallbackFn; - -public: - clsHost(netif& p_rNetIf, - UdpContext& p_rUDPContext); - ~clsHost(void); - - bool init(void); - - // HOST - bool setHostName(const char* p_pcHostName); - const char* hostName(void) const; - - bool setHostProbeResultCallback(HostProbeResultCallbackFn p_fnCallback); - - // Returns 'true' is host domain probing is done - bool probeStatus(void) const; - - // SERVICE - bool setInstanceName(const char* p_pcInstanceName); - const char* instanceName(void) const; - - stcService* addService(const char* p_pcInstanceName, - const char* p_pcServiceType, - const char* p_pcProtocol, - uint16_t p_u16Port); - bool removeService(stcService* p_pMDNSService); - - const stcService* findService(const char* p_pcInstanceName, - const char* p_pcServiceType, - const char* p_pcProtocol, - uint16_t p_u16Port = 0) const; - stcService* findService(const char* p_pcInstanceName, - const char* p_pcServiceType, - const char* p_pcProtocol, - uint16_t p_u16Port = 0); - bool validateService(const stcService* p_pService) const; - - bool setServiceName(stcService* p_pMDNSService, - const char* p_pcInstanceName); - const char* serviceName(const stcService* p_pMDNSService) const; - const char* serviceType(const stcService* p_pMDNSService) const; - const char* serviceProtocol(const stcService* p_pMDNSService) const; - uint16_t servicePort(const stcService* p_pMDNSService) const; - - // Set a service specific probe result callcack - bool setServiceProbeResultCallback(stcService* p_pMDNSService, - ServiceProbeResultCallbackFn p_fnCallback); - - bool serviceProbeStatus(const stcService* p_pMDNSService) const; - - // SERVICE TXT - // Add a (static) MDNS TXT item ('key' = 'value') to the service - stcServiceTxt* addServiceTxt(stcService* p_pMDNSService, - const char* p_pcKey, - const char* p_pcValue); - bool removeServiceTxt(stcService* p_pMDNSService, - stcServiceTxt* p_pTxt); - const stcServiceTxt* findServiceTxt(stcService* p_pMDNSService, - const char* p_pcKey) const; - stcServiceTxt* findServiceTxt(stcService* p_pMDNSService, - const char* p_pcKey); - - bool setDynamicServiceTxtCallback(DynamicServiceTxtCallbackFn p_fnCallback); - bool setDynamicServiceTxtCallback(stcService* p_pMDNSService, - DynamicServiceTxtCallbackFn p_fnCallback); - - // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service - // Dynamic TXT items are removed right after one-time use. So they need to be added - // every time the value s needed (via callback). - stcServiceTxt* addDynamicServiceTxt(stcService* p_pMDNSService, - const char* p_pcKey, - const char* p_pcValue); - - // QUERIES - - // - STATIC - // Perform a (static) service/host query. The function returns after p_u16Timeout milliseconds - // The answers (the number of received answers is returned) can be retrieved by calling - // - answerHostName (or hostname) - // - answerIP (or IP) - // - answerPort (or port) - uint32_t queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); - uint32_t queryHost(const char* p_pcHostName, - const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); - bool removeQuery(void); - bool hasQuery(void); - stcQuery* getQuery(void); - - // - DYNAMIC - // Install a dynamic service/host query. For every received answer (part) the given callback - // function is called. The query will be updated every time, the TTL for an answer - // has timed-out. - // The answers can also be retrieved by calling - // - answerCount service/host (for host queries, this should never be >1) - // - answerServiceDomain service - // - hasAnswerHostDomain/answerHostDomain service/host - // - hasAnswerIPv4Address/answerIPv4Address service/host - // - hasAnswerIPv6Address/answerIPv6Address service/host - // - hasAnswerPort/answerPort service - // - hasAnswerTxts/answerTxts service - stcQuery* installServiceQuery(const char* p_pcServiceType, - const char* p_pcProtocol, - QueryCallbackFn p_fnCallback); - stcQuery* installHostQuery(const char* p_pcHostName, - QueryCallbackFn p_fnCallback); - // Remove a dynamic service query - bool removeQuery(stcQuery* p_pMDNSQuery); - - - - - - // PROCESSING - bool processUDPInput(void); - bool update(void); - - bool announce(bool p_bAnnounce, - bool p_bIncludeServices); - bool announceService(stcService* p_pService, - bool p_bAnnounce = true); - - bool restart(void); - -protected: - // File: ..._Host - bool _close(void); - - // NETIF - typeNetIfState _getNetIfState(void) const; - bool _checkNetIfState(void); - - // DOMAIN NAMES - bool _allocDomainName(const char* p_pcNewDomainName, - char*& p_rpcDomainName); - bool _releaseDomainName(char*& p_rpcDomainName); - bool _allocHostName(const char* p_pcHostName); - bool _releaseHostName(void); - bool _allocInstanceName(const char* p_pcInstanceName); - bool _releaseInstanceName(void); - - // SERVICE - stcService* _allocService(const char* p_pcName, - const char* p_pcServiceType, - const char* p_pcProtocol, - uint16_t p_u16Port); - bool _releaseService(stcService* p_pService); - - // SERVICE TXT - stcServiceTxt* _allocServiceTxt(stcService* p_pService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp); - bool _releaseServiceTxt(stcService* p_pService, - stcServiceTxt* p_pTxt); - stcServiceTxt* _updateServiceTxt(stcService* p_pService, - stcServiceTxt* p_pTxt, - const char* p_pcValue, - bool p_bTemp); - stcServiceTxt* _findServiceTxt(stcService* p_pService, - const char* p_pcKey); - stcServiceTxt* _addServiceTxt(stcService* p_pService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp); - stcServiceTxt* _answerKeyValue(const stcQuery p_pQuery, - const uint32_t p_u32AnswerIndex); - bool _collectServiceTxts(stcService& p_rService); - bool _releaseTempServiceTxts(stcService& p_rService); - - // QUERIES - stcQuery* _allocQuery(stcQuery::enuQueryType p_QueryType); - bool _removeQuery(stcQuery* p_pQuery); - bool _removeLegacyQuery(void); - stcQuery* _findLegacyQuery(void); - bool _releaseQueries(void); - stcQuery* _findNextQueryByDomain(const stcRRDomain& p_Domain, - const stcQuery::enuQueryType p_QueryType, - const stcQuery* p_pPrevQuery); - stcQuery* _installDomainQuery(stcRRDomain& p_Domain, - stcQuery::enuQueryType p_QueryType, - QueryCallbackFn p_fnCallback); - bool _hasQueriesWaitingForAnswers(void) const; - bool _executeQueryCallback(const stcQuery& p_Query, - const stcQuery::stcAnswer& p_Answer, - typeQueryAnswerType p_QueryAnswerTypeFlags, - bool p_SetContent); - - - // File: ..._Host_Control - // RECEIVING - bool _parseMessage(void); - bool _parseQuery(const stcMsgHeader& p_Header); - - bool _parseResponse(const stcMsgHeader& p_Header); - bool _processAnswers(const stcRRAnswer* p_pPTRAnswers); - bool _processPTRAnswer(const stcRRAnswerPTR* p_pPTRAnswer, - bool& p_rbFoundNewKeyAnswer); - bool _processSRVAnswer(const stcRRAnswerSRV* p_pSRVAnswer, - bool& p_rbFoundNewKeyAnswer); - bool _processTXTAnswer(const stcRRAnswerTXT* p_pTXTAnswer); -#ifdef MDNS_IPV4_SUPPORT - bool _processAAnswer(const stcRRAnswerA* p_pAAnswer); -#endif -#ifdef MDNS_IPV6_SUPPORT - bool _processAAAAAnswer(const stcRRAnswerAAAA* p_pAAAAAnswer); -#endif - - // PROBING - bool _updateProbeStatus(void); - bool _resetProbeStatus(bool p_bRestart = true); - bool _hasProbesWaitingForAnswers(void) const; - bool _sendHostProbe(void); - bool _sendServiceProbe(stcService& p_rService); - bool _cancelProbingForHost(void); - bool _cancelProbingForService(stcService& p_rService); - bool _callHostProbeResultCallback(bool p_bResult); - bool _callServiceProbeResultCallback(stcService& p_rService, - bool p_bResult); - - // ANNOUNCE - bool _announce(bool p_bAnnounce, - bool p_bIncludeServices); - bool _announceService(stcService& p_pService, - bool p_bAnnounce = true); - - // QUERY CACHE - bool _checkQueryCache(void); - - uint32_t _replyMaskForHost(const stcRRHeader& p_RRHeader, - bool* p_pbFullNameMatch = 0) const; - uint32_t _replyMaskForService(const stcRRHeader& p_RRHeader, - const stcService& p_Service, - bool* p_pbFullNameMatch = 0) const; - - - // File: ..._Host_Transfer - // SENDING - bool _sendMDNSMessage(stcSendParameter& p_SendParameter); - bool _sendMDNSMessage_Multicast(stcSendParameter& p_rSendParameter, - uint8_t p_IPProtocolTypes); - bool _prepareMDNSMessage(stcSendParameter& p_SendParameter); - bool _addMDNSQueryRecord(stcSendParameter& p_rSendParameter, - const stcRRDomain& p_QueryDomain, - uint16_t p_u16QueryType); - bool _sendMDNSQuery(const stcQuery& p_Query, - stcQuery::stcAnswer* p_pKnownAnswers = 0); - bool _sendMDNSQuery(const stcRRDomain& p_QueryDomain, - uint16_t p_u16RecordType, - stcQuery::stcAnswer* p_pKnownAnswers = 0); - - IPAddress _getResponderIPAddress(enuIPProtocolType p_IPProtocolType) const; - - // RESOURCE RECORD - bool _readRRQuestion(stcRRQuestion& p_rQuestion); - bool _readRRAnswer(stcRRAnswer*& p_rpAnswer); -#ifdef MDNS_IPV4_SUPPORT - bool _readRRAnswerA(stcRRAnswerA& p_rRRAnswerA, - uint16_t p_u16RDLength); -#endif - bool _readRRAnswerPTR(stcRRAnswerPTR& p_rRRAnswerPTR, - uint16_t p_u16RDLength); - bool _readRRAnswerTXT(stcRRAnswerTXT& p_rRRAnswerTXT, - uint16_t p_u16RDLength); -#ifdef MDNS_IPV6_SUPPORT - bool _readRRAnswerAAAA(stcRRAnswerAAAA& p_rRRAnswerAAAA, - uint16_t p_u16RDLength); -#endif - bool _readRRAnswerSRV(stcRRAnswerSRV& p_rRRAnswerSRV, - uint16_t p_u16RDLength); - bool _readRRAnswerGeneric(stcRRAnswerGeneric& p_rRRAnswerGeneric, - uint16_t p_u16RDLength); - - bool _readRRHeader(stcRRHeader& p_rHeader); - bool _readRRDomain(stcRRDomain& p_rRRDomain); - bool _readRRDomain_Loop(stcRRDomain& p_rRRDomain, - uint8_t p_u8Depth); - bool _readRRAttributes(stcRRAttributes& p_rAttributes); - - // DOMAIN NAMES - bool _buildDomainForHost(const char* p_pcHostName, - stcRRDomain& p_rHostDomain) const; - bool _buildDomainForDNSSD(stcRRDomain& p_rDNSSDDomain) const; - bool _buildDomainForService(const stcService& p_Service, - bool p_bIncludeName, - stcRRDomain& p_rServiceDomain) const; - bool _buildDomainForService(const char* p_pcService, - const char* p_pcProtocol, - stcRRDomain& p_rServiceDomain) const; -#ifdef MDNS_IPV4_SUPPORT - bool _buildDomainForReverseIPv4(IPAddress p_IPv4Address, - stcRRDomain& p_rReverseIPv4Domain) const; -#endif -#ifdef MDNS_IPV6_SUPPORT - bool _buildDomainForReverseIPv6(IPAddress p_IPv4Address, - stcRRDomain& p_rReverseIPv6Domain) const; -#endif - - // UDP - bool _udpReadBuffer(unsigned char* p_pBuffer, - size_t p_stLength); - bool _udpRead8(uint8_t& p_ru8Value); - bool _udpRead16(uint16_t& p_ru16Value); - bool _udpRead32(uint32_t& p_ru32Value); - - bool _udpAppendBuffer(const unsigned char* p_pcBuffer, - size_t p_stLength); - bool _udpAppend8(uint8_t p_u8Value); - bool _udpAppend16(uint16_t p_u16Value); - bool _udpAppend32(uint32_t p_u32Value); - -#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER - bool _udpDump(bool p_bMovePointer = false); - bool _udpDump(unsigned p_uOffset, - unsigned p_uLength); -#endif - - // READ/WRITE MDNS STRUCTS - bool _readMDNSMsgHeader(stcMsgHeader& p_rMsgHeader); - - bool _write8(uint8_t p_u8Value, - stcSendParameter& p_rSendParameter); - bool _write16(uint16_t p_u16Value, - stcSendParameter& p_rSendParameter); - bool _write32(uint32_t p_u32Value, - stcSendParameter& p_rSendParameter); - - bool _writeMDNSMsgHeader(const stcMsgHeader& p_MsgHeader, - stcSendParameter& p_rSendParameter); - bool _writeMDNSRRAttributes(const stcRRAttributes& p_Attributes, - stcSendParameter& p_rSendParameter); - bool _writeMDNSRRDomain(const stcRRDomain& p_Domain, - stcSendParameter& p_rSendParameter); - bool _writeMDNSHostDomain(const char* m_pcHostName, - bool p_bPrependRDLength, - uint16_t p_u16AdditionalLength, - stcSendParameter& p_rSendParameter); - bool _writeMDNSServiceDomain(const stcService& p_Service, - bool p_bIncludeName, - bool p_bPrependRDLength, - uint16_t p_u16AdditionalLength, - stcSendParameter& p_rSendParameter); - - bool _writeMDNSQuestion(stcRRQuestion& p_Question, - stcSendParameter& p_rSendParameter); - -#ifdef MDNS_IPV4_SUPPORT - bool _writeMDNSAnswer_A(IPAddress p_IPAddress, - stcSendParameter& p_rSendParameter); - bool _writeMDNSAnswer_PTR_IPv4(IPAddress p_IPAddress, - stcSendParameter& p_rSendParameter); -#endif - bool _writeMDNSAnswer_PTR_TYPE(stcService& p_rService, - stcSendParameter& p_rSendParameter); - bool _writeMDNSAnswer_PTR_NAME(stcService& p_rService, - stcSendParameter& p_rSendParameter); - bool _writeMDNSAnswer_TXT(stcService& p_rService, - stcSendParameter& p_rSendParameter); -#ifdef MDNS_IPV6_SUPPORT - bool _writeMDNSAnswer_AAAA(IPAddress p_IPAddress, - stcSendParameter& p_rSendParameter); - bool _writeMDNSAnswer_PTR_IPv6(IPAddress p_IPAddress, - stcSendParameter& p_rSendParameter); -#endif - bool _writeMDNSAnswer_SRV(stcService& p_rService, - stcSendParameter& p_rSendParameter); - stcNSECBitmap* _createNSECBitmap(uint32_t p_u32NSECContent); - bool _writeMDNSNSECBitmap(const stcNSECBitmap& p_NSECBitmap, - stcSendParameter& p_rSendParameter); - bool _writeMDNSAnswer_NSEC(uint32_t p_u32NSECContent, - stcSendParameter& p_rSendParameter); -#ifdef MDNS_IPV4_SUPPORT - bool _writeMDNSAnswer_NSEC_PTR_IPv4(IPAddress p_IPAddress, - stcSendParameter& p_rSendParameter); -#endif -#ifdef MDNS_IPV6_SUPPORT - bool _writeMDNSAnswer_NSEC_PTR_IPv6(IPAddress p_IPAddress, - stcSendParameter& p_rSendParameter); -#endif - bool _writeMDNSAnswer_NSEC(stcService& p_rService, - uint32_t p_u32NSECContent, - stcSendParameter& p_rSendParameter); - - - // File: ..._Host_Debug -#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER - const char* _DH(const stcService* p_pMDNSService = 0) const; - const char* _service2String(const stcService* p_pMDNSService) const; - - bool _printRRDomain(const stcRRDomain& p_rRRDomain) const; - bool _printRRAnswer(const stcRRAnswer& p_RRAnswer) const; - const char* _RRType2Name(uint16_t p_u16RRType) const; - const char* _RRClass2String(uint16_t p_u16RRClass, - bool p_bIsQuery) const; - const char* _replyFlags2String(uint32_t p_u32ReplyFlags) const; - const char* _NSECBitmap2String(const stcNSECBitmap* p_pNSECBitmap) const; -#endif - - -public: - netif& m_rNetIf; - typeNetIfState m_NetIfState; - UdpContext& m_rUDPContext; - - char* m_pcHostName; - char* m_pcInstanceName; - stcService* m_pServices; - stcQuery* m_pQueries; - DynamicServiceTxtCallbackFn m_fnServiceTxtCallback; - stcProbeInformation_Host m_HostProbeInformation; -}; -using clsHostList = std::list<clsHost*>; - diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Structs.cpp deleted file mode 100755 index 7121abcfca..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Host_Structs.cpp +++ /dev/null @@ -1,2435 +0,0 @@ -/* - LEAmDNS2_Host_Structs.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#include "LEAmDNS2_Priv.h" -#include "LEAmDNS2_lwIPdefs.h" - -namespace esp8266 -{ - -/* - LEAmDNS -*/ -namespace experimental -{ - -/** - Internal CLASSES & STRUCTS -*/ - -/** - MDNSResponder::clsHost::stcServiceTxt - - One MDNS TXT item. - m_pcValue may be '\0'. - Objects can be chained together (list, m_pNext). - A 'm_bTemp' flag differentiates between static and dynamic items. - Output as byte array 'c#=1' is supported. -*/ - -/* - MDNSResponder::clsHost::stcServiceTxt::stcServiceTxt constructor -*/ -MDNSResponder::clsHost::stcServiceTxt::stcServiceTxt(const char* p_pcKey /*= 0*/, - const char* p_pcValue /*= 0*/, - bool p_bTemp /*= false*/) - : m_pNext(0), - m_pcKey(0), - m_pcValue(0), - m_bTemp(p_bTemp) -{ - setKey(p_pcKey); - setValue(p_pcValue); -} - -/* - MDNSResponder::clsHost::stcServiceTxt::stcServiceTxt copy-constructor -*/ -MDNSResponder::clsHost::stcServiceTxt::stcServiceTxt(const MDNSResponder::clsHost::stcServiceTxt& p_Other) - : m_pNext(0), - m_pcKey(0), - m_pcValue(0), - m_bTemp(false) -{ - operator=(p_Other); -} - -/* - MDNSResponder::clsHost::stcServiceTxt::~stcServiceTxt destructor -*/ -MDNSResponder::clsHost::stcServiceTxt::~stcServiceTxt(void) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcServiceTxt::operator= -*/ -MDNSResponder::clsHost::stcServiceTxt& MDNSResponder::clsHost::stcServiceTxt::operator=(const MDNSResponder::clsHost::stcServiceTxt& p_Other) -{ - if (&p_Other != this) - { - clear(); - set(p_Other.m_pcKey, p_Other.m_pcValue, p_Other.m_bTemp); - } - return *this; -} - -/* - MDNSResponder::clsHost::stcServiceTxt::clear -*/ -bool MDNSResponder::clsHost::stcServiceTxt::clear(void) -{ - releaseKey(); - releaseValue(); - return true; -} - -/* - MDNSResponder::clsHost::stcServiceTxt::allocKey -*/ -char* MDNSResponder::clsHost::stcServiceTxt::allocKey(size_t p_stLength) -{ - releaseKey(); - if (p_stLength) - { - m_pcKey = new char[p_stLength + 1]; - } - return m_pcKey; -} - -/* - MDNSResponder::clsHost::stcServiceTxt::setKey -*/ -bool MDNSResponder::clsHost::stcServiceTxt::setKey(const char* p_pcKey, - size_t p_stLength) -{ - bool bResult = false; - - releaseKey(); - if (p_stLength) - { - if (allocKey(p_stLength)) - { - strncpy(m_pcKey, p_pcKey, p_stLength); - m_pcKey[p_stLength] = 0; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcServiceTxt::setKey -*/ -bool MDNSResponder::clsHost::stcServiceTxt::setKey(const char* p_pcKey) -{ - return setKey(p_pcKey, (p_pcKey ? strlen(p_pcKey) : 0)); -} - -/* - MDNSResponder::clsHost::stcServiceTxt::releaseKey -*/ -bool MDNSResponder::clsHost::stcServiceTxt::releaseKey(void) -{ - if (m_pcKey) - { - delete[] m_pcKey; - m_pcKey = 0; - } - return true; -} - -/* - MDNSResponder::clsHost::stcServiceTxt::allocValue -*/ -char* MDNSResponder::clsHost::stcServiceTxt::allocValue(size_t p_stLength) -{ - releaseValue(); - if (p_stLength) - { - m_pcValue = new char[p_stLength + 1]; - } - return m_pcValue; -} - -/* - MDNSResponder::clsHost::stcServiceTxt::setValue -*/ -bool MDNSResponder::clsHost::stcServiceTxt::setValue(const char* p_pcValue, - size_t p_stLength) -{ - bool bResult = false; - - releaseValue(); - if (p_stLength) - { - if (allocValue(p_stLength)) - { - strncpy(m_pcValue, p_pcValue, p_stLength); - m_pcValue[p_stLength] = 0; - bResult = true; - } - } - else // No value -> also OK - { - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcServiceTxt::setValue -*/ -bool MDNSResponder::clsHost::stcServiceTxt::setValue(const char* p_pcValue) -{ - return setValue(p_pcValue, (p_pcValue ? strlen(p_pcValue) : 0)); -} - -/* - MDNSResponder::clsHost::stcServiceTxt::releaseValue -*/ -bool MDNSResponder::clsHost::stcServiceTxt::releaseValue(void) -{ - if (m_pcValue) - { - delete[] m_pcValue; - m_pcValue = 0; - } - return true; -} - -/* - MDNSResponder::clsHost::stcServiceTxt::set -*/ -bool MDNSResponder::clsHost::stcServiceTxt::set(const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp /*= false*/) -{ - m_bTemp = p_bTemp; - return ((setKey(p_pcKey)) && - (setValue(p_pcValue))); -} - -/* - MDNSResponder::clsHost::stcServiceTxt::update -*/ -bool MDNSResponder::clsHost::stcServiceTxt::update(const char* p_pcValue) -{ - return setValue(p_pcValue); -} - -/* - MDNSResponder::clsHost::stcServiceTxt::length - - length of eg. 'c#=1' without any closing '\0' -*/ -size_t MDNSResponder::clsHost::stcServiceTxt::length(void) const -{ - size_t stLength = 0; - if (m_pcKey) - { - stLength += strlen(m_pcKey); // Key - stLength += 1; // '=' - stLength += (m_pcValue ? strlen(m_pcValue) : 0); // Value - } - return stLength; -} - - -/** - MDNSResponder::clsHost::stcServiceTxts - - A list of zero or more MDNS TXT items. - Dynamic TXT items can be removed by 'removeTempTxts'. - A TXT item can be looke up by its 'key' member. - Export as ';'-separated byte array is supported. - Export as 'length byte coded' byte array is supported. - Comparision ((all A TXT items in B and equal) AND (all B TXT items in A and equal)) is supported. - -*/ - -/* - MDNSResponder::clsHost::stcServiceTxts::stcServiceTxts contructor -*/ -MDNSResponder::clsHost::stcServiceTxts::stcServiceTxts(void) - : m_pTxts(0), - m_pcCache(0) -{ -} - -/* - MDNSResponder::clsHost::stcServiceTxts::stcServiceTxts copy-constructor -*/ -MDNSResponder::clsHost::stcServiceTxts::stcServiceTxts(const stcServiceTxts& p_Other) - : m_pTxts(0), - m_pcCache(0) -{ - operator=(p_Other); -} - -/* - MDNSResponder::clsHost::stcServiceTxts::~stcServiceTxts destructor -*/ -MDNSResponder::clsHost::stcServiceTxts::~stcServiceTxts(void) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcServiceTxts::operator= -*/ -MDNSResponder::clsHost::stcServiceTxts& MDNSResponder::clsHost::stcServiceTxts::operator=(const stcServiceTxts& p_Other) -{ - if (this != &p_Other) - { - clear(); - - for (stcServiceTxt* pOtherTxt = p_Other.m_pTxts; pOtherTxt; pOtherTxt = pOtherTxt->m_pNext) - { - add(new stcServiceTxt(*pOtherTxt)); - } - } - return *this; -} - -/* - MDNSResponder::clsHost::stcServiceTxts::clear -*/ -bool MDNSResponder::clsHost::stcServiceTxts::clear(void) -{ - while (m_pTxts) - { - stcServiceTxt* pNext = m_pTxts->m_pNext; - delete m_pTxts; - m_pTxts = pNext; - } - return clearCache(); -} - -/* - MDNSResponder::clsHost::stcServiceTxts::clearCache -*/ -bool MDNSResponder::clsHost::stcServiceTxts::clearCache(void) -{ - if (m_pcCache) - { - delete[] m_pcCache; - m_pcCache = 0; - } - return true; -} - -/* - MDNSResponder::clsHost::stcServiceTxts::add -*/ -bool MDNSResponder::clsHost::stcServiceTxts::add(MDNSResponder::clsHost::stcServiceTxt* p_pTxt) -{ - bool bResult = false; - - if (p_pTxt) - { - p_pTxt->m_pNext = m_pTxts; - m_pTxts = p_pTxt; - bResult = true; - } - return ((clearCache()) && - (bResult)); -} - -/* - MDNSResponder::clsHost::stcServiceTxts::remove -*/ -bool MDNSResponder::clsHost::stcServiceTxts::remove(stcServiceTxt* p_pTxt) -{ - bool bResult = false; - - if (p_pTxt) - { - stcServiceTxt* pPred = m_pTxts; - while ((pPred) && - (pPred->m_pNext != p_pTxt)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pTxt->m_pNext; - delete p_pTxt; - bResult = true; - } - else if (m_pTxts == p_pTxt) // No predecesor, but first item - { - m_pTxts = p_pTxt->m_pNext; - delete p_pTxt; - bResult = true; - } - } - return ((clearCache()) && - (bResult)); -} - -/* - MDNSResponder::clsHost::stcServiceTxts::removeTempTxts -*/ -bool MDNSResponder::clsHost::stcServiceTxts::removeTempTxts(void) -{ - bool bResult = true; - - stcServiceTxt* pTxt = m_pTxts; - while ((bResult) && - (pTxt)) - { - stcServiceTxt* pNext = pTxt->m_pNext; - if (pTxt->m_bTemp) - { - bResult = remove(pTxt); - } - pTxt = pNext; - } - return ((clearCache()) && - (bResult)); -} - -/* - MDNSResponder::clsHost::stcServiceTxts::find -*/ -MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::stcServiceTxts::find(const char* p_pcKey) -{ - stcServiceTxt* pResult = 0; - - for (stcServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) - { - if ((p_pcKey) && - (0 == strcmp(pTxt->m_pcKey, p_pcKey))) - { - pResult = pTxt; - break; - } - } - return pResult; -} - -/* - MDNSResponder::clsHost::stcServiceTxts::find -*/ -const MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::stcServiceTxts::find(const char* p_pcKey) const -{ - const stcServiceTxt* pResult = 0; - - for (const stcServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) - { - if ((p_pcKey) && - (0 == strcmp(pTxt->m_pcKey, p_pcKey))) - { - - pResult = pTxt; - break; - } - } - return pResult; -} - -/* - MDNSResponder::clsHost::stcServiceTxts::find -*/ -MDNSResponder::clsHost::stcServiceTxt* MDNSResponder::clsHost::stcServiceTxts::find(const stcServiceTxt* p_pTxt) -{ - stcServiceTxt* pResult = 0; - - for (stcServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) - { - if (p_pTxt == pTxt) - { - pResult = pTxt; - break; - } - } - return pResult; -} - -/* - MDNSResponder::clsHost::stcServiceTxts::length -*/ -uint16_t MDNSResponder::clsHost::stcServiceTxts::length(void) const -{ - uint16_t u16Length = 0; - - stcServiceTxt* pTxt = m_pTxts; - while (pTxt) - { - u16Length += 1; // Length byte - u16Length += pTxt->length(); // Text - pTxt = pTxt->m_pNext; - } - return u16Length; -} - -/* - MDNSResponder::clsHost::stcServiceTxts::c_strLength - - (incl. closing '\0'). Length bytes place is used for delimiting ';' and closing '\0' -*/ -size_t MDNSResponder::clsHost::stcServiceTxts::c_strLength(void) const -{ - return length(); -} - -/* - MDNSResponder::clsHost::stcServiceTxts::c_str -*/ -bool MDNSResponder::clsHost::stcServiceTxts::c_str(char* p_pcBuffer) -{ - bool bResult = false; - - if (p_pcBuffer) - { - bResult = true; - - *p_pcBuffer = 0; - for (stcServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) - { - size_t stLength; - if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) - { - if (pTxt != m_pTxts) - { - *p_pcBuffer++ = ';'; - } - strncpy(p_pcBuffer, pTxt->m_pcKey, stLength); p_pcBuffer[stLength] = 0; - p_pcBuffer += stLength; - *p_pcBuffer++ = '='; - if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) - { - strncpy(p_pcBuffer, pTxt->m_pcValue, stLength); p_pcBuffer[stLength] = 0; - p_pcBuffer += stLength; - } - } - } - *p_pcBuffer++ = 0; - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcServiceTxts::c_str -*/ -const char* MDNSResponder::clsHost::stcServiceTxts::c_str(void) const -{ - - if ((!m_pcCache) && - (m_pTxts) && - ((((stcServiceTxts*)this)->m_pcCache = new char[c_strLength()]))) // TRANSPARENT caching - { - ((stcServiceTxts*)this)->c_str(m_pcCache); - } - return m_pcCache; -} - -/* - MDNSResponder::clsHost::stcServiceTxts::bufferLength - - (incl. closing '\0'). -*/ -size_t MDNSResponder::clsHost::stcServiceTxts::bufferLength(void) const -{ - return (length() + 1); -} - -/* - MDNSResponder::clsHost::stcServiceTxts::toBuffer -*/ -bool MDNSResponder::clsHost::stcServiceTxts::buffer(char* p_pcBuffer) -{ - bool bResult = false; - - if (p_pcBuffer) - { - bResult = true; - - *p_pcBuffer = 0; - for (stcServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) - { - *(unsigned char*)p_pcBuffer++ = pTxt->length(); - size_t stLength; - if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) - { - memcpy(p_pcBuffer, pTxt->m_pcKey, stLength); - p_pcBuffer += stLength; - *p_pcBuffer++ = '='; - if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) - { - memcpy(p_pcBuffer, pTxt->m_pcValue, stLength); - p_pcBuffer += stLength; - } - } - } - *p_pcBuffer++ = 0; - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcServiceTxts::compare -*/ -bool MDNSResponder::clsHost::stcServiceTxts::compare(const MDNSResponder::clsHost::stcServiceTxts& p_Other) const -{ - bool bResult = false; - - if ((bResult = (length() == p_Other.length()))) - { - // Compare A->B - for (const stcServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) - { - const stcServiceTxt* pOtherTxt = p_Other.find(pTxt->m_pcKey); - bResult = ((pOtherTxt) && - (pTxt->m_pcValue) && - (pOtherTxt->m_pcValue) && - (strlen(pTxt->m_pcValue) == strlen(pOtherTxt->m_pcValue)) && - (0 == strcmp(pTxt->m_pcValue, pOtherTxt->m_pcValue))); - } - // Compare B->A - for (const stcServiceTxt* pOtherTxt = p_Other.m_pTxts; ((bResult) && (pOtherTxt)); pOtherTxt = pOtherTxt->m_pNext) - { - const stcServiceTxt* pTxt = find(pOtherTxt->m_pcKey); - bResult = ((pTxt) && - (pOtherTxt->m_pcValue) && - (pTxt->m_pcValue) && - (strlen(pOtherTxt->m_pcValue) == strlen(pTxt->m_pcValue)) && - (0 == strcmp(pOtherTxt->m_pcValue, pTxt->m_pcValue))); - } - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcServiceTxts::operator== -*/ -bool MDNSResponder::clsHost::stcServiceTxts::operator==(const stcServiceTxts& p_Other) const -{ - return compare(p_Other); -} - -/* - MDNSResponder::clsHost::stcServiceTxts::operator!= -*/ -bool MDNSResponder::clsHost::stcServiceTxts::operator!=(const stcServiceTxts& p_Other) const -{ - return !compare(p_Other); -} - - -/** - MDNSResponder::clsHost::stcProbeInformation_Base - - Probing status information for a host or service domain - -*/ - -/* - MDNSResponder::clsHost::stcProbeInformation_Base::stcProbeInformation_Base constructor -*/ -MDNSResponder::clsHost::stcProbeInformation_Base::stcProbeInformation_Base(void) - : m_ProbingStatus(enuProbingStatus::WaitingForData), - m_u8SentCount(0), - m_Timeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()), - m_bConflict(false), - m_bTiebreakNeeded(false) -{ -} - -/* - MDNSResponder::clsHost::stcProbeInformation_Base::clear -*/ -bool MDNSResponder::clsHost::stcProbeInformation_Base::clear(void) -{ - m_ProbingStatus = enuProbingStatus::WaitingForData; - m_u8SentCount = 0; - m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); - m_bConflict = false; - m_bTiebreakNeeded = false; - - return true; -} - - -/** - MDNSResponder::clsHost::stcProbeInformation_Host - - Probing status information for a host or service domain - -*/ - -/* - MDNSResponder::clsHost::stcProbeInformation_Host::stcProbeInformation_Host constructor -*/ -MDNSResponder::clsHost::stcProbeInformation_Host::stcProbeInformation_Host(void) - : m_fnProbeResultCallback(0) -{ -} - -/* - MDNSResponder::clsHost::stcProbeInformation_Host::clear -*/ -bool MDNSResponder::clsHost::stcProbeInformation_Host::clear(bool p_bClearUserdata /*= false*/) -{ - if (p_bClearUserdata) - { - m_fnProbeResultCallback = 0; - } - return stcProbeInformation_Base::clear(); -} - - -/** - MDNSResponder::clsHost::stcProbeInformation_Service - - Probing status information for a host or service domain - -*/ - -/* - MDNSResponder::clsHost::stcProbeInformation_Service::stcProbeInformation_Service constructor -*/ -MDNSResponder::clsHost::stcProbeInformation_Service::stcProbeInformation_Service(void) - : m_fnProbeResultCallback(0) -{ -} - -/* - MDNSResponder::clsHost::stcProbeInformation_Service::clear -*/ -bool MDNSResponder::clsHost::stcProbeInformation_Service::clear(bool p_bClearUserdata /*= false*/) -{ - if (p_bClearUserdata) - { - m_fnProbeResultCallback = 0; - } - return stcProbeInformation_Base::clear(); -} - - -/** - MDNSResponder::clsHost::stcService - - A MDNS service object (to be announced by the MDNS responder) - The service instance may be '\0'; in this case the hostname is used - and the flag m_bAutoName is set. If the hostname changes, all 'auto- - named' services are renamed also. - m_u8Replymask is used while preparing a response to a MDNS query. It is - resetted in '_sendMDNSMessage' afterwards. -*/ - -/* - MDNSResponder::clsHost::stcService::stcService constructor -*/ -MDNSResponder::clsHost::stcService::stcService(const char* p_pcName /*= 0*/, - const char* p_pcServiceType /*= 0*/, - const char* p_pcProtocol /*= 0*/) - : m_pNext(0), - m_pcName(0), - m_bAutoName(false), - m_pcServiceType(0), - m_pcProtocol(0), - m_u16Port(0), - m_u32ReplyMask(0), - m_fnTxtCallback(0) -{ - setName(p_pcName); - setServiceType(p_pcServiceType); - setProtocol(p_pcProtocol); -} - -/* - MDNSResponder::clsHost::stcService::~stcService destructor -*/ -MDNSResponder::clsHost::stcService::~stcService(void) -{ - releaseName(); - releaseServiceType(); - releaseProtocol(); -} - -/* - MDNSResponder::clsHost::stcService::setName -*/ -bool MDNSResponder::clsHost::stcService::setName(const char* p_pcName) -{ - bool bResult = false; - - releaseName(); - size_t stLength = (p_pcName ? strlen(p_pcName) : 0); - if (stLength) - { - if ((bResult = (0 != (m_pcName = new char[stLength + 1])))) - { - strncpy(m_pcName, p_pcName, stLength); - m_pcName[stLength] = 0; - } - } - else - { - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcService::releaseName -*/ -bool MDNSResponder::clsHost::stcService::releaseName(void) -{ - if (m_pcName) - { - delete[] m_pcName; - m_pcName = 0; - } - return true; -} - -/* - MDNSResponder::clsHost::stcService::setServiceType -*/ -bool MDNSResponder::clsHost::stcService::setServiceType(const char* p_pcServiceType) -{ - bool bResult = false; - - releaseServiceType(); - size_t stLength = (p_pcServiceType ? strlen(p_pcServiceType) : 0); - if (stLength) - { - if ((bResult = (0 != (m_pcServiceType = new char[stLength + 1])))) - { - strncpy(m_pcServiceType, p_pcServiceType, stLength); - m_pcServiceType[stLength] = 0; - } - } - else - { - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcService::releaseServiceType -*/ -bool MDNSResponder::clsHost::stcService::releaseServiceType(void) -{ - if (m_pcServiceType) - { - delete[] m_pcServiceType; - m_pcServiceType = 0; - } - return true; -} - -/* - MDNSResponder::clsHost::stcService::setProtocol -*/ -bool MDNSResponder::clsHost::stcService::setProtocol(const char* p_pcProtocol) -{ - bool bResult = false; - - releaseProtocol(); - size_t stLength = (p_pcProtocol ? strlen(p_pcProtocol) : 0); - if (stLength) - { - if ((bResult = (0 != (m_pcProtocol = new char[stLength + 1])))) - { - strncpy(m_pcProtocol, p_pcProtocol, stLength); - m_pcProtocol[stLength] = 0; - } - } - else - { - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcService::releaseProtocol -*/ -bool MDNSResponder::clsHost::stcService::releaseProtocol(void) -{ - if (m_pcProtocol) - { - delete[] m_pcProtocol; - m_pcProtocol = 0; - } - return true; -} - -/* - MDNSResponder::clsHost::stcService::probeStatus -*/ -bool MDNSResponder::clsHost::stcService::probeStatus(void) const -{ - return (enuProbingStatus::Done == m_ProbeInformation.m_ProbingStatus); -} - - -/** - MDNSResponder::clsHost::stcMsgHeader - - A MDNS message haeder. - -*/ - -/* - MDNSResponder::clsHost::stcMsgHeader::stcMsgHeader -*/ -MDNSResponder::clsHost::stcMsgHeader::stcMsgHeader(uint16_t p_u16ID /*= 0*/, - bool p_bQR /*= false*/, - uint8_t p_u8Opcode /*= 0*/, - bool p_bAA /*= false*/, - bool p_bTC /*= false*/, - bool p_bRD /*= false*/, - bool p_bRA /*= false*/, - uint8_t p_u8RCode /*= 0*/, - uint16_t p_u16QDCount /*= 0*/, - uint16_t p_u16ANCount /*= 0*/, - uint16_t p_u16NSCount /*= 0*/, - uint16_t p_u16ARCount /*= 0*/) - : m_u16ID(p_u16ID), - m_1bQR(p_bQR), m_4bOpcode(p_u8Opcode), m_1bAA(p_bAA), m_1bTC(p_bTC), m_1bRD(p_bRD), - m_1bRA(p_bRA), m_3bZ(0), m_4bRCode(p_u8RCode), - m_u16QDCount(p_u16QDCount), - m_u16ANCount(p_u16ANCount), - m_u16NSCount(p_u16NSCount), - m_u16ARCount(p_u16ARCount) -{ -} - - -/** - MDNSResponder::clsHost::stcRRDomain - - A MDNS domain object. - The labels of the domain are stored (DNS-like encoded) in 'm_acName': - [length byte]varlength label[length byte]varlength label[0] - 'm_u16NameLength' stores the used length of 'm_acName'. - Dynamic label addition is supported. - Comparison is supported. - Export as byte array 'esp8266.local' is supported. - -*/ - -/* - MDNSResponder::clsHost::stcRRDomain::stcRRDomain constructor -*/ -MDNSResponder::clsHost::stcRRDomain::stcRRDomain(void) - : m_u16NameLength(0), - m_pcDecodedName(0) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcRRDomain::stcRRDomain copy-constructor -*/ -MDNSResponder::clsHost::stcRRDomain::stcRRDomain(const stcRRDomain& p_Other) - : m_u16NameLength(0), - m_pcDecodedName(0) -{ - operator=(p_Other); -} - -/* - MDNSResponder::clsHost::stcRRDomain::stcRRDomain destructor -*/ -MDNSResponder::clsHost::stcRRDomain::~stcRRDomain(void) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcRRDomain::operator = -*/ -MDNSResponder::clsHost::stcRRDomain& MDNSResponder::clsHost::stcRRDomain::operator=(const stcRRDomain& p_Other) -{ - if (&p_Other != this) - { - clear(); - memcpy(m_acName, p_Other.m_acName, sizeof(m_acName)); - m_u16NameLength = p_Other.m_u16NameLength; - } - return *this; -} - -/* - MDNSResponder::clsHost::stcRRDomain::clear -*/ -bool MDNSResponder::clsHost::stcRRDomain::clear(void) -{ - memset(m_acName, 0, sizeof(m_acName)); - m_u16NameLength = 0; - return clearNameCache(); -} - -/* - MDNSResponder::clsHost::stcRRDomain::clearNameCache -*/ -bool MDNSResponder::clsHost::stcRRDomain::clearNameCache(void) -{ - if (m_pcDecodedName) - { - delete[] m_pcDecodedName; - m_pcDecodedName = 0; - } - return true; -} - -/* - MDNSResponder::clsHost::stcRRDomain::addLabel -*/ -bool MDNSResponder::clsHost::stcRRDomain::addLabel(const char* p_pcLabel, - bool p_bPrependUnderline /*= false*/) -{ - bool bResult = false; - - size_t stLength = (p_pcLabel - ? (strlen(p_pcLabel) + (p_bPrependUnderline ? 1 : 0)) - : 0); - if ((MDNS_DOMAIN_LABEL_MAXLENGTH >= stLength) && - (MDNS_DOMAIN_MAXLENGTH >= (m_u16NameLength + (1 + stLength)))) - { - // Length byte - m_acName[m_u16NameLength] = (unsigned char)stLength; // Might be 0! - ++m_u16NameLength; - // Label - if (stLength) - { - if (p_bPrependUnderline) - { - m_acName[m_u16NameLength++] = '_'; - --stLength; - } - strncpy(&(m_acName[m_u16NameLength]), p_pcLabel, stLength); m_acName[m_u16NameLength + stLength] = 0; - m_u16NameLength += stLength; - } - bResult = clearNameCache(); - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcRRDomain::compare -*/ -bool MDNSResponder::clsHost::stcRRDomain::compare(const stcRRDomain& p_Other) const -{ - bool bResult = false; - - if (m_u16NameLength == p_Other.m_u16NameLength) - { - const char* pT = m_acName; - const char* pO = p_Other.m_acName; - while ((pT) && - (pO) && - (*((unsigned char*)pT) == *((unsigned char*)pO)) && // Same length AND - (0 == strncasecmp((pT + 1), (pO + 1), *((unsigned char*)pT)))) // Same content - { - if (*((unsigned char*)pT)) // Not 0 - { - pT += (1 + * ((unsigned char*)pT)); // Shift by length byte and lenght - pO += (1 + * ((unsigned char*)pO)); - } - else // Is 0 -> Successfully reached the end - { - bResult = true; - break; - } - } - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcRRDomain::operator == -*/ -bool MDNSResponder::clsHost::stcRRDomain::operator==(const stcRRDomain& p_Other) const -{ - return compare(p_Other); -} - -/* - MDNSResponder::clsHost::stcRRDomain::operator != -*/ -bool MDNSResponder::clsHost::stcRRDomain::operator!=(const stcRRDomain& p_Other) const -{ - return !compare(p_Other); -} - -/* - MDNSResponder::clsHost::stcRRDomain::operator > -*/ -bool MDNSResponder::clsHost::stcRRDomain::operator>(const stcRRDomain& p_Other) const -{ - // TODO: Check, if this is a good idea... - return !compare(p_Other); -} - -/* - MDNSResponder::clsHost::stcRRDomain::c_strLength -*/ -size_t MDNSResponder::clsHost::stcRRDomain::c_strLength(void) const -{ - size_t stLength = 0; - - unsigned char* pucLabelLength = (unsigned char*)m_acName; - while (*pucLabelLength) - { - stLength += (*pucLabelLength + 1 /* +1 for '.' or '\0'*/); - pucLabelLength += (*pucLabelLength + 1); - } - return stLength; -} - -/* - MDNSResponder::clsHost::stcRRDomain::c_str (const) -*/ -bool MDNSResponder::clsHost::stcRRDomain::c_str(char* p_pcBuffer) const -{ - bool bResult = false; - - if (p_pcBuffer) - { - *p_pcBuffer = 0; - unsigned char* pucLabelLength = (unsigned char*)m_acName; - while (*pucLabelLength) - { - memcpy(p_pcBuffer, (const char*)(pucLabelLength + 1), *pucLabelLength); - p_pcBuffer += *pucLabelLength; - pucLabelLength += (*pucLabelLength + 1); - *p_pcBuffer++ = (*pucLabelLength ? '.' : '\0'); - } - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcRRDomain::c_str -*/ -const char* MDNSResponder::clsHost::stcRRDomain::c_str(void) const -{ - if ((!m_pcDecodedName) && - (m_u16NameLength) && - ((((stcRRDomain*)this)->m_pcDecodedName = new char[c_strLength()]))) // TRANSPARENT caching - { - ((stcRRDomain*)this)->c_str(m_pcDecodedName); - } - return m_pcDecodedName; -} - - -/** - MDNSResponder::clsHost::stcRRAttributes - - A MDNS attributes object. - -*/ - -/* - MDNSResponder::clsHost::stcRRAttributes::stcRRAttributes constructor -*/ -MDNSResponder::clsHost::stcRRAttributes::stcRRAttributes(uint16_t p_u16Type /*= 0*/, - uint16_t p_u16Class /*= 1 DNS_RRCLASS_IN Internet*/) - : m_u16Type(p_u16Type), - m_u16Class(p_u16Class) -{ -} - -/* - MDNSResponder::clsHost::stcRRAttributes::stcRRAttributes copy-constructor -*/ -MDNSResponder::clsHost::stcRRAttributes::stcRRAttributes(const MDNSResponder::clsHost::stcRRAttributes& p_Other) -{ - operator=(p_Other); -} - -/* - MDNSResponder::clsHost::stcRRAttributes::operator = -*/ -MDNSResponder::clsHost::stcRRAttributes& MDNSResponder::clsHost::stcRRAttributes::operator=(const MDNSResponder::clsHost::stcRRAttributes& p_Other) -{ - if (&p_Other != this) - { - m_u16Type = p_Other.m_u16Type; - m_u16Class = p_Other.m_u16Class; - } - return *this; -} - - -/** - MDNSResponder::clsHost::stcRRHeader - - A MDNS record header (domain and attributes) object. - -*/ - -/* - MDNSResponder::clsHost::stcRRHeader::stcRRHeader constructor -*/ -MDNSResponder::clsHost::stcRRHeader::stcRRHeader(void) -{ -} - -/* - MDNSResponder::clsHost::stcRRHeader::stcRRHeader copy-constructor -*/ -MDNSResponder::clsHost::stcRRHeader::stcRRHeader(const stcRRHeader& p_Other) -{ - operator=(p_Other); -} - -/* - MDNSResponder::clsHost::stcRRHeader::operator = -*/ -MDNSResponder::clsHost::stcRRHeader& MDNSResponder::clsHost::stcRRHeader::operator=(const MDNSResponder::clsHost::stcRRHeader& p_Other) -{ - if (&p_Other != this) - { - m_Domain = p_Other.m_Domain; - m_Attributes = p_Other.m_Attributes; - } - return *this; -} - -/* - MDNSResponder::clsHost::stcRRHeader::clear -*/ -bool MDNSResponder::clsHost::stcRRHeader::clear(void) -{ - m_Domain.clear(); - return true; -} - - -/** - MDNSResponder::clsHost::stcRRQuestion - - A MDNS question record object (header + question flags) - -*/ - -/* - MDNSResponder::clsHost::stcRRQuestion::stcRRQuestion constructor -*/ -MDNSResponder::clsHost::stcRRQuestion::stcRRQuestion(void) - : m_pNext(0), - m_bUnicast(false) -{ -} - - -/** - MDNSResponder::clsHost::stcNSECBitmap - - A MDNS question record object (header + question flags) - -*/ - -/* - MDNSResponder::clsHost::stcNSECBitmap::stcNSECBitmap constructor -*/ -MDNSResponder::clsHost::stcNSECBitmap::stcNSECBitmap(void) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcNSECBitmap::stcNSECBitmap destructor -*/ -bool MDNSResponder::clsHost::stcNSECBitmap::clear(void) -{ - memset(m_au8BitmapData, 0, sizeof(m_au8BitmapData)); - return true; -} - -/* - MDNSResponder::clsHost::stcNSECBitmap::length -*/ -uint16_t MDNSResponder::clsHost::stcNSECBitmap::length(void) const -{ - return sizeof(m_au8BitmapData); // 6 -} - -/* - MDNSResponder::clsHost::stcNSECBitmap::setBit -*/ -bool MDNSResponder::clsHost::stcNSECBitmap::setBit(uint16_t p_u16Bit) -{ - bool bResult = false; - - if ((p_u16Bit) && - (length() > (p_u16Bit / 8))) // bit between 0..47(2F) - { - - uint8_t& ru8Byte = m_au8BitmapData[p_u16Bit / 8]; - uint8_t u8Flag = 1 << (7 - (p_u16Bit % 8)); // (7 - (0..7)) = 7..0 - - ru8Byte |= u8Flag; - - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcNSECBitmap::getBit -*/ -bool MDNSResponder::clsHost::stcNSECBitmap::getBit(uint16_t p_u16Bit) const -{ - bool bResult = false; - - if ((p_u16Bit) && - (length() > (p_u16Bit / 8))) // bit between 0..47(2F) - { - - uint8_t u8Byte = m_au8BitmapData[p_u16Bit / 8]; - uint8_t u8Flag = 1 << (7 - (p_u16Bit % 8)); // (7 - (0..7)) = 7..0 - - bResult = (u8Byte & u8Flag); - } - return bResult; -} - - -/** - MDNSResponder::clsHost::stcRRAnswer - - A MDNS answer record object (header + answer content). - This is a 'virtual' base class for all other MDNS answer classes. - -*/ - -/* - MDNSResponder::clsHost::stcRRAnswer::stcRRAnswer constructor -*/ -MDNSResponder::clsHost::stcRRAnswer::stcRRAnswer(enuAnswerType p_AnswerType, - const MDNSResponder::clsHost::stcRRHeader& p_Header, - uint32_t p_u32TTL) - : m_pNext(0), - m_AnswerType(p_AnswerType), - m_Header(p_Header), - m_u32TTL(p_u32TTL) -{ - // Extract 'cache flush'-bit - m_bCacheFlush = (m_Header.m_Attributes.m_u16Class & 0x8000); - m_Header.m_Attributes.m_u16Class &= (~0x8000); -} - -/* - MDNSResponder::clsHost::stcRRAnswer::~stcRRAnswer destructor -*/ -MDNSResponder::clsHost::stcRRAnswer::~stcRRAnswer(void) -{ -} - -/* - MDNSResponder::clsHost::stcRRAnswer::answerType -*/ -MDNSResponder::clsHost::enuAnswerType MDNSResponder::clsHost::stcRRAnswer::answerType(void) const -{ - return m_AnswerType; -} - -/* - MDNSResponder::clsHost::stcRRAnswer::clear -*/ -bool MDNSResponder::clsHost::stcRRAnswer::clear(void) -{ - m_pNext = 0; - m_Header.clear(); - return true; -} - - -/** - MDNSResponder::clsHost::stcRRAnswerA - - A MDNS A answer object. - Extends the base class by an IPv4 address member. - -*/ - -#ifdef MDNS_IPV4_SUPPORT -/* - MDNSResponder::clsHost::stcRRAnswerA::stcRRAnswerA constructor -*/ -MDNSResponder::clsHost::stcRRAnswerA::stcRRAnswerA(const MDNSResponder::clsHost::stcRRHeader& p_Header, - uint32_t p_u32TTL) - : stcRRAnswer(enuAnswerType::A, p_Header, p_u32TTL), - m_IPAddress() -{ -} - -/* - MDNSResponder::clsHost::stcRRAnswerA::stcRRAnswerA destructor -*/ -MDNSResponder::clsHost::stcRRAnswerA::~stcRRAnswerA(void) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcRRAnswerA::clear -*/ -bool MDNSResponder::clsHost::stcRRAnswerA::clear(void) -{ - m_IPAddress = IPAddress(); - return true; -} -#endif - - -/** - MDNSResponder::clsHost::stcRRAnswerPTR - - A MDNS PTR answer object. - Extends the base class by a MDNS domain member. - -*/ - -/* - MDNSResponder::clsHost::stcRRAnswerPTR::stcRRAnswerPTR constructor -*/ -MDNSResponder::clsHost::stcRRAnswerPTR::stcRRAnswerPTR(const MDNSResponder::clsHost::stcRRHeader& p_Header, - uint32_t p_u32TTL) - : stcRRAnswer(enuAnswerType::PTR, p_Header, p_u32TTL) -{ -} - -/* - MDNSResponder::clsHost::stcRRAnswerPTR::~stcRRAnswerPTR destructor -*/ -MDNSResponder::clsHost::stcRRAnswerPTR::~stcRRAnswerPTR(void) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcRRAnswerPTR::clear -*/ -bool MDNSResponder::clsHost::stcRRAnswerPTR::clear(void) -{ - m_PTRDomain.clear(); - return true; -} - - -/** - MDNSResponder::clsHost::stcRRAnswerTXT - - A MDNS TXT answer object. - Extends the base class by a MDNS TXT items list member. - -*/ - -/* - MDNSResponder::clsHost::stcRRAnswerTXT::stcRRAnswerTXT constructor -*/ -MDNSResponder::clsHost::stcRRAnswerTXT::stcRRAnswerTXT(const MDNSResponder::clsHost::stcRRHeader& p_Header, - uint32_t p_u32TTL) - : stcRRAnswer(enuAnswerType::TXT, p_Header, p_u32TTL) -{ -} - -/* - MDNSResponder::clsHost::stcRRAnswerTXT::~stcRRAnswerTXT destructor -*/ -MDNSResponder::clsHost::stcRRAnswerTXT::~stcRRAnswerTXT(void) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcRRAnswerTXT::clear -*/ -bool MDNSResponder::clsHost::stcRRAnswerTXT::clear(void) -{ - m_Txts.clear(); - return true; -} - - -/** - MDNSResponder::clsHost::stcRRAnswerAAAA - - A MDNS AAAA answer object. - Extends the base class by an IPv6 address member. - -*/ - -#ifdef MDNS_IPV6_SUPPORT -/* - MDNSResponder::clsHost::stcRRAnswerAAAA::stcRRAnswerAAAA constructor -*/ -MDNSResponder::clsHost::stcRRAnswerAAAA::stcRRAnswerAAAA(const MDNSResponder::clsHost::stcRRHeader& p_Header, - uint32_t p_u32TTL) - : stcRRAnswer(enuAnswerType::AAAA, p_Header, p_u32TTL), - m_IPAddress() -{ -} - -/* - MDNSResponder::clsHost::stcRRAnswerAAAA::~stcRRAnswerAAAA destructor -*/ -MDNSResponder::clsHost::stcRRAnswerAAAA::~stcRRAnswerAAAA(void) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcRRAnswerAAAA::clear -*/ -bool MDNSResponder::clsHost::stcRRAnswerAAAA::clear(void) -{ - m_IPAddress = IPAddress(); - return true; -} -#endif - - -/** - MDNSResponder::clsHost::stcRRAnswerSRV - - A MDNS SRV answer object. - Extends the base class by a port member. - -*/ - -/* - MDNSResponder::clsHost::stcRRAnswerSRV::stcRRAnswerSRV constructor -*/ -MDNSResponder::clsHost::stcRRAnswerSRV::stcRRAnswerSRV(const MDNSResponder::clsHost::stcRRHeader& p_Header, - uint32_t p_u32TTL) - : stcRRAnswer(enuAnswerType::SRV, p_Header, p_u32TTL), - m_u16Priority(0), - m_u16Weight(0), - m_u16Port(0) -{ -} - -/* - MDNSResponder::clsHost::stcRRAnswerSRV::~stcRRAnswerSRV destructor -*/ -MDNSResponder::clsHost::stcRRAnswerSRV::~stcRRAnswerSRV(void) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcRRAnswerSRV::clear -*/ -bool MDNSResponder::clsHost::stcRRAnswerSRV::clear(void) -{ - m_u16Priority = 0; - m_u16Weight = 0; - m_u16Port = 0; - m_SRVDomain.clear(); - return true; -} - - -/** - MDNSResponder::clsHost::stcRRAnswerGeneric - - An unknown (generic) MDNS answer object. - Extends the base class by a RDATA buffer member. - -*/ - -/* - MDNSResponder::clsHost::stcRRAnswerGeneric::stcRRAnswerGeneric constructor -*/ -MDNSResponder::clsHost::stcRRAnswerGeneric::stcRRAnswerGeneric(const stcRRHeader& p_Header, - uint32_t p_u32TTL) - : stcRRAnswer(enuAnswerType::Generic, p_Header, p_u32TTL), - m_u16RDLength(0), - m_pu8RDData(0) -{ -} - -/* - MDNSResponder::clsHost::stcRRAnswerGeneric::~stcRRAnswerGeneric destructor -*/ -MDNSResponder::clsHost::stcRRAnswerGeneric::~stcRRAnswerGeneric(void) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcRRAnswerGeneric::clear -*/ -bool MDNSResponder::clsHost::stcRRAnswerGeneric::clear(void) -{ - if (m_pu8RDData) - { - delete[] m_pu8RDData; - m_pu8RDData = 0; - } - m_u16RDLength = 0; - - return true; -} - - -/** - MDNSResponder::clsHost::stcSendParameter - - A 'collection' of properties and flags for one MDNS query or response. - Mainly managed by the 'Control' functions. - The current offset in the UPD output buffer is tracked to be able to do - a simple host or service domain compression. - -*/ - -/** - MDNSResponder::clsHost::stcSendParameter::stcDomainCacheItem - - A cached host or service domain, incl. the offset in the UDP output buffer. - -*/ - -/* - MDNSResponder::clsHost::stcSendParameter::stcDomainCacheItem::stcDomainCacheItem constructor -*/ -MDNSResponder::clsHost::stcSendParameter::stcDomainCacheItem::stcDomainCacheItem(const void* p_pHostNameOrService, - bool p_bAdditionalData, - uint32_t p_u16Offset) - : m_pNext(0), - m_pHostNameOrService(p_pHostNameOrService), - m_bAdditionalData(p_bAdditionalData), - m_u16Offset(p_u16Offset) -{ -} - -/** - MDNSResponder::clsHost::stcSendParameter -*/ - -/* - MDNSResponder::clsHost::stcSendParameter::stcSendParameter constructor -*/ -MDNSResponder::clsHost::stcSendParameter::stcSendParameter(void) - : m_pQuestions(0), - m_Response(enuResponseType::None), - m_pDomainCacheItems(0) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcSendParameter::~stcSendParameter destructor -*/ -MDNSResponder::clsHost::stcSendParameter::~stcSendParameter(void) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcSendParameter::clear -*/ -bool MDNSResponder::clsHost::stcSendParameter::clear(void) -{ - m_u16ID = 0; - flushQuestions(); - m_u32HostReplyMask = 0; - - m_bLegacyQuery = false; - m_Response = enuResponseType::None; - m_bAuthorative = false; - m_bCacheFlush = true; - m_bUnicast = false; - m_bUnannounce = false; - - m_u16Offset = 0; - flushDomainCache(); - return true; -} - -/* - MDNSResponder::clsHost::stcSendParameter::flushQuestions -*/ -bool MDNSResponder::clsHost::stcSendParameter::flushQuestions(void) -{ - while (m_pQuestions) - { - stcRRQuestion* pNext = m_pQuestions->m_pNext; - delete m_pQuestions; - m_pQuestions = pNext; - } - return true; -} - -/* - MDNSResponder::clsHost::stcSendParameter::flushDomainCache -*/ -bool MDNSResponder::clsHost::stcSendParameter::flushDomainCache(void) -{ - while (m_pDomainCacheItems) - { - stcDomainCacheItem* pNext = m_pDomainCacheItems->m_pNext; - delete m_pDomainCacheItems; - m_pDomainCacheItems = pNext; - } - return true; -} - -/* - MDNSResponder::clsHost::stcSendParameter::flushTempContent -*/ -bool MDNSResponder::clsHost::stcSendParameter::flushTempContent(void) -{ - m_u16Offset = 0; - flushDomainCache(); - return true; -} - -/* - MDNSResponder::clsHost::stcSendParameter::shiftOffset -*/ -bool MDNSResponder::clsHost::stcSendParameter::shiftOffset(uint16_t p_u16Shift) -{ - m_u16Offset += p_u16Shift; - return true; -} - -/* - MDNSResponder::clsHost::stcSendParameter::addDomainCacheItem -*/ -bool MDNSResponder::clsHost::stcSendParameter::addDomainCacheItem(const void* p_pHostNameOrService, - bool p_bAdditionalData, - uint16_t p_u16Offset) -{ - bool bResult = false; - - stcDomainCacheItem* pNewItem = 0; - if ((p_pHostNameOrService) && - (p_u16Offset) && - ((pNewItem = new stcDomainCacheItem(p_pHostNameOrService, p_bAdditionalData, p_u16Offset)))) - { - - pNewItem->m_pNext = m_pDomainCacheItems; - bResult = ((m_pDomainCacheItems = pNewItem)); - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcSendParameter::findCachedDomainOffset -*/ -uint16_t MDNSResponder::clsHost::stcSendParameter::findCachedDomainOffset(const void* p_pHostNameOrService, - bool p_bAdditionalData) const -{ - const stcDomainCacheItem* pCacheItem = m_pDomainCacheItems; - - for (; pCacheItem; pCacheItem = pCacheItem->m_pNext) - { - if ((pCacheItem->m_pHostNameOrService == p_pHostNameOrService) && - (pCacheItem->m_bAdditionalData == p_bAdditionalData)) // Found cache item - { - break; - } - } - return (pCacheItem ? pCacheItem->m_u16Offset : 0); -} - - -/** - MDNSResponder::clsHost::stcQuery - - A MDNS service query object. - Service queries may be static or dynamic. - As the static service query is processed in the blocking function 'queryService', - only one static service service may exist. The processing of the answers is done - on the WiFi-stack side of the ESP stack structure (via 'UDPContext.onRx(_update)'). - -*/ - -/** - MDNSResponder::clsHost::stcQuery::stcAnswer - - One answer for a service query. - Every answer must contain - - a service instance entry (pivot), - and may contain - - a host domain, - - a port - - an IPv4 address - (- an IPv6 address) - - a MDNS TXTs - The existance of a component is flaged in 'm_u32ContentFlags'. - For every answer component a TTL value is maintained. - Answer objects can be connected to a linked list. - - For the host domain, service domain and TXTs components, a char array - representation can be retrieved (which is created on demand). - -*/ - -/** - MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL - - The TTL (Time-To-Live) for an specific answer content. - The 80% and outdated states are calculated based on the current time (millis) - and the 'set' time (also millis). - If the answer is scheduled for an update, the corresponding flag should be set. - -*/ - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::stcTTL constructor -*/ -MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::stcTTL(void) - : m_u32TTL(0), - m_TTLTimeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()), - m_TimeoutLevel(static_cast<typeTimeoutLevel>(enuTimeoutLevel::None)) -{ -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::set -*/ -bool MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::set(uint32_t p_u32TTL) -{ - m_u32TTL = p_u32TTL; - if (m_u32TTL) - { - m_TimeoutLevel = static_cast<typeTimeoutLevel>(enuTimeoutLevel::Base); // Set to 80% - m_TTLTimeout.reset(timeout()); - } - else - { - m_TimeoutLevel = static_cast<typeTimeoutLevel>(enuTimeoutLevel::None); // undef - m_TTLTimeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); - } - return true; -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::flagged -*/ -bool MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::flagged(void) const -{ - return ((m_u32TTL) && - (static_cast<typeTimeoutLevel>(enuTimeoutLevel::None) != m_TimeoutLevel) && - (((esp8266::polledTimeout::timeoutTemplate<false>*)&m_TTLTimeout)->expired())); // Cast-away the const; in case of oneShot-timer OK (but ugly...) -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::restart -*/ -bool MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::restart(void) -{ - bool bResult = true; - - if ((static_cast<typeTimeoutLevel>(enuTimeoutLevel::Base) <= m_TimeoutLevel) && // >= 80% AND - (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final) > m_TimeoutLevel)) // < 100% - { - - m_TimeoutLevel += static_cast<typeTimeoutLevel>(enuTimeoutLevel::Interval); // increment by 5% - m_TTLTimeout.reset(timeout()); - } - else - { - bResult = false; - m_TTLTimeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); - m_TimeoutLevel = static_cast<typeTimeoutLevel>(enuTimeoutLevel::None); - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::prepareDeletion -*/ -bool MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::prepareDeletion(void) -{ - m_TimeoutLevel = static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final); - m_TTLTimeout.reset(1 * 1000); // See RFC 6762, 10.1 - - return true; -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::finalTimeoutLevel -*/ -bool MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::finalTimeoutLevel(void) const -{ - return (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final) == m_TimeoutLevel); -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::timeout -*/ -unsigned long MDNSResponder::clsHost::stcQuery::stcAnswer::stcTTL::timeout(void) const -{ - uint32_t u32Timeout = std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max(); - - if (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Base) == m_TimeoutLevel) // 80% - { - u32Timeout = (m_u32TTL * 800); // to milliseconds - } - else if ((static_cast<typeTimeoutLevel>(enuTimeoutLevel::Base) < m_TimeoutLevel) && // >80% AND - (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final) >= m_TimeoutLevel)) // <= 100% - { - - u32Timeout = (m_u32TTL * 50); - } // else: invalid - return u32Timeout; -} - - -/** - MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress - -*/ - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress::stcIPAddress constructor -*/ -MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress::stcIPAddress(IPAddress p_IPAddress, - uint32_t p_u32TTL /*= 0*/) - : m_pNext(0), - m_IPAddress(p_IPAddress) -{ - m_TTL.set(p_u32TTL); -} - - -/** - MDNSResponder::clsHost::stcQuery::stcAnswer -*/ - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::stcAnswer constructor -*/ -MDNSResponder::clsHost::stcQuery::stcAnswer::stcAnswer(void) - : m_pNext(0), - m_u16Port(0), -#ifdef MDNS_IPV4_SUPPORT - m_pIPv4Addresses(0), -#endif -#ifdef MDNS_IPV6_SUPPORT - m_pIPv6Addresses(0), -#endif - m_QueryAnswerFlags(0) -{ -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::~stcAnswer destructor -*/ -MDNSResponder::clsHost::stcQuery::stcAnswer::~stcAnswer(void) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::clear -*/ -bool MDNSResponder::clsHost::stcQuery::stcAnswer::clear(void) -{ - return ( -#ifdef MDNS_IPV4_SUPPORT - (releaseIPv4Addresses()) && -#endif -#ifdef MDNS_IPV6_SUPPORT - (releaseIPv6Addresses()) -#endif - ); -} - -#ifdef MDNS_IPV4_SUPPORT -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::releaseIPv4Addresses -*/ -bool MDNSResponder::clsHost::stcQuery::stcAnswer::releaseIPv4Addresses(void) -{ - while (m_pIPv4Addresses) - { - stcIPAddress* pNext = m_pIPv4Addresses->m_pNext; - delete m_pIPv4Addresses; - m_pIPv4Addresses = pNext; - } - return true; -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::addIPv4Address -*/ -bool MDNSResponder::clsHost::stcQuery::stcAnswer::addIPv4Address(MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* p_pIPv4Address) -{ - bool bResult = false; - - if (p_pIPv4Address) - { - p_pIPv4Address->m_pNext = m_pIPv4Addresses; - m_pIPv4Addresses = p_pIPv4Address; - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::removeIPv4Address -*/ -bool MDNSResponder::clsHost::stcQuery::stcAnswer::removeIPv4Address(MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* p_pIPv4Address) -{ - bool bResult = false; - - if (p_pIPv4Address) - { - stcIPAddress* pPred = m_pIPv4Addresses; - while ((pPred) && - (pPred->m_pNext != p_pIPv4Address)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pIPv4Address->m_pNext; - delete p_pIPv4Address; - bResult = true; - } - else if (m_pIPv4Addresses == p_pIPv4Address) // No predecesor, but first item - { - m_pIPv4Addresses = p_pIPv4Address->m_pNext; - delete p_pIPv4Address; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv4Address (const) -*/ -const MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv4Address(const IPAddress& p_IPAddress) const -{ - return (stcIPAddress*)(((const stcAnswer*)this)->findIPv4Address(p_IPAddress)); -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv4Address -*/ -MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv4Address(const IPAddress& p_IPAddress) -{ - stcIPAddress* pIPv4Address = m_pIPv4Addresses; - while (pIPv4Address) - { - if (pIPv4Address->m_IPAddress == p_IPAddress) - { - break; - } - pIPv4Address = pIPv4Address->m_pNext; - } - return pIPv4Address; -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::IPv4AddressCount -*/ -uint32_t MDNSResponder::clsHost::stcQuery::stcAnswer::IPv4AddressCount(void) const -{ - uint32_t u32Count = 0; - - stcIPAddress* pIPv4Address = m_pIPv4Addresses; - while (pIPv4Address) - { - ++u32Count; - pIPv4Address = pIPv4Address->m_pNext; - } - return u32Count; -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::IPv4AddressAtIndex -*/ -MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::IPv4AddressAtIndex(uint32_t p_u32Index) -{ - return (stcIPAddress*)(((const stcAnswer*)this)->IPv4AddressAtIndex(p_u32Index)); -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::IPv4AddressAtIndex (const) -*/ -const MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::IPv4AddressAtIndex(uint32_t p_u32Index) const -{ - const stcIPAddress* pIPv4Address = 0; - - if (((uint32_t)(-1) != p_u32Index) && - (m_pIPv4Addresses)) - { - - uint32_t u32Index; - for (pIPv4Address = m_pIPv4Addresses, u32Index = 0; ((pIPv4Address) && (u32Index < p_u32Index)); pIPv4Address = pIPv4Address->m_pNext, ++u32Index); - } - return pIPv4Address; -} -#endif - -#ifdef MDNS_IPV6_SUPPORT -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::releaseIPv6Addresses -*/ -bool MDNSResponder::clsHost::stcQuery::stcAnswer::releaseIPv6Addresses(void) -{ - while (m_pIPv6Addresses) - { - stcIPAddress* pNext = m_pIPv6Addresses->m_pNext; - delete m_pIPv6Addresses; - m_pIPv6Addresses = pNext; - } - return true; -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::addIPv6Address -*/ -bool MDNSResponder::clsHost::stcQuery::stcAnswer::addIPv6Address(MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* p_pIPv6Address) -{ - bool bResult = false; - - if (p_pIPv6Address) - { - p_pIPv6Address->m_pNext = m_pIPv6Addresses; - m_pIPv6Addresses = p_pIPv6Address; - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::removeIPv6Address -*/ -bool MDNSResponder::clsHost::stcQuery::stcAnswer::removeIPv6Address(MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* p_pIPv6Address) -{ - bool bResult = false; - - if (p_pIPv6Address) - { - stcIPAddress* pPred = m_pIPv6Addresses; - while ((pPred) && - (pPred->m_pNext != p_pIPv6Address)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pIPv6Address->m_pNext; - delete p_pIPv6Address; - bResult = true; - } - else if (m_pIPv6Addresses == p_pIPv6Address) // No predecesor, but first item - { - m_pIPv6Addresses = p_pIPv6Address->m_pNext; - delete p_pIPv6Address; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv6Address -*/ -MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv6Address(const IPAddress& p_IPAddress) -{ - return (stcIPAddress*)(((const stcAnswer*)this)->findIPv6Address(p_IPAddress)); -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv6Address (const) -*/ -const MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::findIPv6Address(const IPAddress& p_IPAddress) const -{ - const stcIPAddress* pIPv6Address = m_pIPv6Addresses; - while (pIPv6Address) - { - if (pIPv6Address->m_IPAddress == p_IPAddress) - { - break; - } - pIPv6Address = pIPv6Address->m_pNext; - } - return pIPv6Address; -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::IPv6AddressCount -*/ -uint32_t MDNSResponder::clsHost::stcQuery::stcAnswer::IPv6AddressCount(void) const -{ - uint32_t u32Count = 0; - - stcIPAddress* pIPv6Address = m_pIPv6Addresses; - while (pIPv6Address) - { - ++u32Count; - pIPv6Address = pIPv6Address->m_pNext; - } - return u32Count; -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::IPv6AddressAtIndex (const) -*/ -const MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::IPv6AddressAtIndex(uint32_t p_u32Index) const -{ - return (stcIPAddress*)(((const stcAnswer*)this)->IPv6AddressAtIndex(p_u32Index)); -} - -/* - MDNSResponder::clsHost::stcQuery::stcAnswer::IPv6AddressAtIndex -*/ -MDNSResponder::clsHost::stcQuery::stcAnswer::stcIPAddress* MDNSResponder::clsHost::stcQuery::stcAnswer::IPv6AddressAtIndex(uint32_t p_u32Index) -{ - stcIPAddress* pIPv6Address = 0; - - if (((uint32_t)(-1) != p_u32Index) && - (m_pIPv6Addresses)) - { - - uint32_t u32Index; - for (pIPv6Address = m_pIPv6Addresses, u32Index = 0; ((pIPv6Address) && (u32Index < p_u32Index)); pIPv6Address = pIPv6Address->m_pNext, ++u32Index); - } - return pIPv6Address; -} -#endif - - -/** - MDNSResponder::clsHost::stcQuery - - A service query object. - A static query is flaged via 'm_bLegacyQuery'; while the function 'queryService' - is waiting for answers, the internal flag 'm_bAwaitingAnswers' is set. When the - timeout is reached, the flag is removed. These two flags are only used for static - service queries. - All answers to the service query are stored in 'm_pAnswers' list. - Individual answers may be addressed by index (in the list of answers). - Every time a answer component is added (or changes) in a dynamic service query, - the callback 'm_fnCallback' is called. - The answer list may be searched by service and host domain. - - Service query object may be connected to a linked list. -*/ - -/* - MDNSResponder::clsHost::stcQuery::stcQuery constructor -*/ -MDNSResponder::clsHost::stcQuery::stcQuery(const enuQueryType p_QueryType) - : m_pNext(0), - m_QueryType(p_QueryType), - m_fnCallback(0), - m_bLegacyQuery(false), - m_u8SentCount(0), - m_ResendTimeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()), - m_bAwaitingAnswers(true), - m_pAnswers(0) -{ - clear(); - m_QueryType = p_QueryType; -} - -/* - MDNSResponder::clsHost::stcQuery::~stcQuery destructor -*/ -MDNSResponder::clsHost::stcQuery::~stcQuery(void) -{ - clear(); -} - -/* - MDNSResponder::clsHost::stcQuery::clear -*/ -bool MDNSResponder::clsHost::stcQuery::clear(void) -{ - m_pNext = 0; - m_QueryType = enuQueryType::None; - m_fnCallback = 0; - m_bLegacyQuery = false; - m_u8SentCount = 0; - m_ResendTimeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); - m_bAwaitingAnswers = true; - while (m_pAnswers) - { - stcAnswer* pNext = m_pAnswers->m_pNext; - delete m_pAnswers; - m_pAnswers = pNext; - } - return true; -} - -/* - MDNSResponder::clsHost::stcQuery::answerCount -*/ -uint32_t MDNSResponder::clsHost::stcQuery::answerCount(void) const -{ - uint32_t u32Count = 0; - - stcAnswer* pAnswer = m_pAnswers; - while (pAnswer) - { - ++u32Count; - pAnswer = pAnswer->m_pNext; - } - return u32Count; -} - -/* - MDNSResponder::clsHost::stcQuery::answerAtIndex -*/ -const MDNSResponder::clsHost::stcQuery::stcAnswer* MDNSResponder::clsHost::stcQuery::answerAtIndex(uint32_t p_u32Index) const -{ - const stcAnswer* pAnswer = 0; - - if (((uint32_t)(-1) != p_u32Index) && - (m_pAnswers)) - { - - uint32_t u32Index; - for (pAnswer = m_pAnswers, u32Index = 0; ((pAnswer) && (u32Index < p_u32Index)); pAnswer = pAnswer->m_pNext, ++u32Index); - } - return pAnswer; -} - -/* - MDNSResponder::clsHost::stcQuery::answerAtIndex -*/ -MDNSResponder::clsHost::stcQuery::stcAnswer* MDNSResponder::clsHost::stcQuery::answerAtIndex(uint32_t p_u32Index) -{ - return (stcAnswer*)(((const stcQuery*)this)->answerAtIndex(p_u32Index)); -} - -/* - MDNSResponder::clsHost::stcQuery::indexOfAnswer -*/ -uint32_t MDNSResponder::clsHost::stcQuery::indexOfAnswer(const MDNSResponder::clsHost::stcQuery::stcAnswer* p_pAnswer) const -{ - uint32_t u32Index = 0; - - for (const stcAnswer* pAnswer = m_pAnswers; pAnswer; pAnswer = pAnswer->m_pNext, ++u32Index) - { - if (pAnswer == p_pAnswer) - { - return u32Index; - } - } - return ((uint32_t)(-1)); -} - -/* - MDNSResponder::clsHost::stcQuery::addAnswer -*/ -bool MDNSResponder::clsHost::stcQuery::addAnswer(MDNSResponder::clsHost::stcQuery::stcAnswer* p_pAnswer) -{ - bool bResult = false; - - if (p_pAnswer) - { - p_pAnswer->m_pNext = m_pAnswers; - m_pAnswers = p_pAnswer; - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcQuery::removeAnswer -*/ -bool MDNSResponder::clsHost::stcQuery::removeAnswer(MDNSResponder::clsHost::stcQuery::stcAnswer* p_pAnswer) -{ - bool bResult = false; - - if (p_pAnswer) - { - stcAnswer* pPred = m_pAnswers; - while ((pPred) && - (pPred->m_pNext != p_pAnswer)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pAnswer->m_pNext; - delete p_pAnswer; - bResult = true; - } - else if (m_pAnswers == p_pAnswer) // No predecesor, but first item - { - m_pAnswers = p_pAnswer->m_pNext; - delete p_pAnswer; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::clsHost::stcQuery::findAnswerForServiceDomain -*/ -MDNSResponder::clsHost::stcQuery::stcAnswer* MDNSResponder::clsHost::stcQuery::findAnswerForServiceDomain(const MDNSResponder::clsHost::stcRRDomain& p_ServiceDomain) -{ - stcAnswer* pAnswer = m_pAnswers; - while (pAnswer) - { - if (pAnswer->m_ServiceDomain == p_ServiceDomain) - { - break; - } - pAnswer = pAnswer->m_pNext; - } - return pAnswer; -} - -/* - MDNSResponder::clsHost::stcQuery::findAnswerForHostDomain -*/ -MDNSResponder::clsHost::stcQuery::stcAnswer* MDNSResponder::clsHost::stcQuery::findAnswerForHostDomain(const MDNSResponder::clsHost::stcRRDomain& p_HostDomain) -{ - stcAnswer* pAnswer = m_pAnswers; - while (pAnswer) - { - if (pAnswer->m_HostDomain == p_HostDomain) - { - break; - } - pAnswer = pAnswer->m_pNext; - } - return pAnswer; -} - - -} // namespace MDNSImplementation - -} // namespace esp8266 - - - diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp new file mode 100644 index 0000000000..040d915905 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -0,0 +1,1493 @@ +/* + * LEAmDNS2_Legacy.cpp + * + * + */ + +#include "LEAmDNS2_Legacy.h" + + +namespace esp8266 +{ + +/** + * LEAmDNS + */ +namespace MDNSImplementation +{ + +/** + STRINGIZE +*/ +#ifndef STRINGIZE +#define STRINGIZE(x) #x +#endif +#ifndef STRINGIZE_VALUE_OF +#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) +#endif + + +/* + * clsLEAMDNSHost_Legacy::clsLEAMDNSHost_Legacy constructor + * + */ +clsLEAMDNSHost_Legacy::clsLEAMDNSHost_Legacy(void) +{ +} + +/* + * clsLEAMDNSHost_Legacy::clsLEAMDNSHost_Legacy destructor + * + */ +clsLEAMDNSHost_Legacy::~clsLEAMDNSHost_Legacy(void) +{ +} + +/* + * + * HOST SETUP + * + */ + +/* + * clsLEAMDNSHost_Legacy::begin + * + */ +bool clsLEAMDNSHost_Legacy::begin(const char* p_pcHostname) +{ + bool bResult = ( ( (!(WIFI_STA & (WiFiMode_t)wifi_get_opmode())) + || (addHostForNetIf(p_pcHostname, netif_get_by_index(WIFI_STA)))) + && ( (!(WIFI_AP & (WiFiMode_t)wifi_get_opmode())) + || (addHostForNetIf(p_pcHostname, netif_get_by_index(WIFI_AP))))); + return ( (bResult) + && (0 != m_HostInformations.size())); +} + +/* + * clsLEAMDNSHost_Legacy::begin (String) + * + */ +bool clsLEAMDNSHost_Legacy::begin(const String& p_strHostname) +{ + return begin(p_strHostname.c_str()); +} + +/* + * clsLEAMDNSHost_Legacy::begin (Ignored Options) + * + */ +bool clsLEAMDNSHost_Legacy::begin(const char* p_pcHostname, + IPAddress /*p_IPAddress = INADDR_ANY*/, // ignored + uint32_t /*p_u32TTL = 120*/) // ignored +{ + return begin(p_pcHostname); +} + +/* + * clsLEAMDNSHost_Legacy::begin (String & Ignored Options) + * + */ +bool clsLEAMDNSHost_Legacy::begin(const String& p_strHostname, + IPAddress /*p_IPAddress = INADDR_ANY*/, // ignored + uint32_t /*p_u32TTL = 120*/) // ignored +{ + return begin(p_strHostname.c_str()); +} + +/* + * clsLEAMDNSHost_Legacy::close + * + */ +bool clsLEAMDNSHost_Legacy::close(void) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + if ((bResult = (*it).m_pHost->close())) + { + delete (*it).m_pHost; + (*it).m_pHost = 0; + } + } + return ( (bResult) + && (m_HostInformations.clear(), true)); +} + +/* + * clsLEAMDNSHost_Legacy::end + * + */ +bool clsLEAMDNSHost_Legacy::end(void) +{ + return close(); +} + +/* + * clsLEAMDNSHost_Legacy::addHostForNetIf + * + * NEW! + * + */ +bool clsLEAMDNSHost_Legacy::addHostForNetIf(const char* p_pcHostname, + netif* p_pNetIf) +{ + clsLEAMDNSHost* pHost = 0; + + if ( ((pHost = new esp8266::experimental::clsLEAMDNSHost)) + && (!( (pHost->begin(p_pcHostname, p_pNetIf /*, default callback*/)) + && (m_HostInformations.push_back(stcHostInformation(pHost)), true)))) + { + delete pHost; + pHost = 0; + } + return (0 != pHost); +} + +/* + * clsLEAMDNSHost_Legacy::setHostname + * + */ +bool clsLEAMDNSHost_Legacy::setHostname(const char* p_pcHostname) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->setHostName(p_pcHostname); + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::setHostname + * + */ +bool clsLEAMDNSHost_Legacy::setHostname(String p_strHostname) +{ + return setHostname(p_strHostname.c_str()); +} + +/* + * clsLEAMDNSHost_Legacy::hostname + * + */ +const char* clsLEAMDNSHost_Legacy::hostname(void) const +{ + return (m_HostInformations.empty() + ? 0 + : m_HostInformations.front().m_pHost->hostName()); +} + +/* + * clsLEAMDNSHost_Legacy::status + * + */ +bool clsLEAMDNSHost_Legacy::status(void) const +{ + bool bStatus = true; + + for (const stcHostInformation& hostInformation : m_HostInformations) + { + if (!((bStatus = hostInformation.m_pHost->probeStatus()))) + { + break; + } + } + return bStatus; +} + + +/* + * + * SERVICE MANAGEMENT + * + */ + +/* + * clsLEAMDNSHost_Legacy::addService + * + */ +clsLEAMDNSHost_Legacy::hMDNSService clsLEAMDNSHost_Legacy::addService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + uint16_t p_u16Port) +{ + hMDNSService hResult = 0; + + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsService* pService = hostInformation.m_pHost->addService(p_pcName, p_pcService, p_pcProtocol, p_u16Port /*, default callback*/); + if (pService) + { + if (!hResult) + { // Store first service handle as result and key + hResult = (hMDNSService)pService; + } + hostInformation.m_HandleToPtr[hResult] = pService; + } + } + return hResult; +} + +/* + * clsLEAMDNSHost_Legacy::addService (String) + * + */ +bool clsLEAMDNSHost_Legacy::addService(String p_strServiceName, + String p_strProtocol, + uint16_t p_u16Port) +{ + return (0 != addService(0, p_strServiceName.c_str(), p_strProtocol.c_str(), p_u16Port)); +} + +/* + * clsLEAMDNSHost_Legacy::removeService (hService) + * + */ +bool clsLEAMDNSHost_Legacy::removeService(const hMDNSService p_hService) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; + if ((bResult = ( (pService) + && ((*it).m_pHost->removeService(pService))))) + { + (*it).m_HandleToPtr.erase(p_hService); + } + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::removeService (name) + * + */ +bool clsLEAMDNSHost_Legacy::removeService(const char* p_pcInstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol) +{ + hMDNSService hService = 0; + return ( ((hService = (m_HostInformations.empty() + ? 0 + : (hMDNSService)m_HostInformations.front().m_pHost->findService(p_pcInstanceName, p_pcServiceName, p_pcProtocol)))) + && (removeService(hService))); +} + +/* + * clsLEAMDNSHost_Legacy::setServiceName + * + */ +bool clsLEAMDNSHost_Legacy::setServiceName(const hMDNSService p_hService, + const char* p_pcInstanceName) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; + bResult = ( (pService) + && (pService->setInstanceName(p_pcInstanceName))); + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::setInstanceName + * + */ +void clsLEAMDNSHost_Legacy::setInstanceName(const char* p_pcInstanceName) +{ + for (stcHostInformation& hostInformation : m_HostInformations) + { + hostInformation.m_pHost->setDefaultInstanceName(p_pcInstanceName); + } +} + +/* + * clsLEAMDNSHost_Legacy::setInstanceName (String) + * + */ +void clsLEAMDNSHost_Legacy::setInstanceName(const String& p_strHostname) +{ + setInstanceName(p_strHostname.c_str()); +} + +/* + * clsLEAMDNSHost_Legacy::serviceName + * + */ +const char* clsLEAMDNSHost_Legacy::serviceName(const hMDNSService p_hService) const +{ + const clsLEAMDNSHost::clsService* pService = 0; + return (m_HostInformations.empty() + ? 0 + : (((pService = (const clsLEAMDNSHost::clsService*)(m_HostInformations.front().m_HandleToPtr.at(p_hService)))) + ? pService->instanceName() + : 0)); +} + +/* + * clsLEAMDNSHost_Legacy::service + * + */ +const char* clsLEAMDNSHost_Legacy::service(const hMDNSService p_hService) const +{ + const clsLEAMDNSHost::clsService* pService = 0; + return (m_HostInformations.empty() + ? 0 + : (((pService = (const clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr.at(p_hService))) + ? pService->type() + : 0)); +} + +/* + * clsLEAMDNSHost_Legacy::serviceProtocol + * + */ +const char* clsLEAMDNSHost_Legacy::serviceProtocol(const hMDNSService p_hService) const +{ + const clsLEAMDNSHost::clsService* pService = 0; + return (m_HostInformations.empty() + ? 0 + : (((pService = (const clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr.at(p_hService))) + ? pService->protocol() + : 0)); +} + +/* + * clsLEAMDNSHost_Legacy::serviceStatus + * + */ +bool clsLEAMDNSHost_Legacy::serviceStatus(const hMDNSService p_hService) const +{ + const clsLEAMDNSHost::clsService* pService = 0; + return (m_HostInformations.empty() + ? false + : (((pService = (const clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr.at(p_hService))) + ? pService->probeStatus() + : false)); +} + + +/* + * + * SERVICE TXT MANAGEMENT + * + */ + +/* + * clsLEAMDNSHost_Legacy::addServiceTxt (char*) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + const char* p_pcValue) +{ + return _addServiceTxt(p_hService, p_pcKey, p_pcValue, false); +} + +/* + * clsLEAMDNSHost_Legacy::addServiceTxt (uint32_t) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint32_t p_u32Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_u32Value, false); +} + +/* + * clsLEAMDNSHost_Legacy::addServiceTxt (uint16_t) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint16_t p_u16Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_u16Value, false); +} + +/* + * clsLEAMDNSHost_Legacy::addServiceTxt (uint8_t) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint8_t p_u8Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_u8Value, false); +} + +/* + * clsLEAMDNSHost_Legacy::addServiceTxt (int32_t) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int32_t p_i32Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_i32Value, false); +} + +/* + * clsLEAMDNSHost_Legacy::addServiceTxt (int16_t) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int16_t p_i16Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_i16Value, false); +} + +/* + * clsLEAMDNSHost_Legacy::addServiceTxt (int8_t) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int8_t p_i8Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_i8Value, false); +} + +/* + * clsLEAMDNSHost_Legacy::addServiceTxt (legacy) + * + */ +bool clsLEAMDNSHost_Legacy::addServiceTxt(const char* p_pcService, + const char* p_pcProtocol, + const char* p_pcKey, + const char* p_pcValue) +{ + hMDNSService hService = 0; + return ( ((hService = (m_HostInformations.empty() + ? 0 + : (hMDNSService)m_HostInformations.front().m_pHost->findService(0, p_pcService, p_pcProtocol)))) + && (_addServiceTxt(hService, p_pcKey, p_pcValue, false))); +} + +/* + * clsLEAMDNSHost_Legacy::addServiceTxt (legacy, String) + * + */ +bool clsLEAMDNSHost_Legacy::addServiceTxt(String p_strService, + String p_strProtocol, + String p_strKey, + String p_strValue) +{ + return addServiceTxt(p_strService.c_str(), p_strProtocol.c_str(), p_strKey.c_str(), p_strValue.c_str()); +} + +/* + * clsLEAMDNSHost_Legacy::removeServiceTxt (hTxt) + * + */ +bool clsLEAMDNSHost_Legacy::removeServiceTxt(const hMDNSService p_hService, + const hMDNSTxt p_hTxt) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; + clsLEAMDNSHost::clsServiceTxt* pTxt = (clsLEAMDNSHost::clsServiceTxt*)(*it).m_HandleToPtr[p_hTxt]; + if ((bResult = ( (pService) + && (pTxt) + && (pService->removeServiceTxt(pTxt))))) + { + (*it).m_HandleToPtr.erase(p_hTxt); + } + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::removeServiceTxt (char*) + * + */ +bool clsLEAMDNSHost_Legacy::removeServiceTxt(const hMDNSService p_hService, + const char* p_pcKey) +{ + clsLEAMDNSHost::clsService* pService = 0; + clsLEAMDNSHost::clsServiceTxt* pTxt = 0; + return ( ((pService = (m_HostInformations.empty() + ? 0 + : (clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr[p_hService]))) + && ((pTxt = pService->findServiceTxt(p_pcKey))) + && (removeServiceTxt(p_hService, (const hMDNSTxt)pTxt))); +} + +/* + * clsLEAMDNSHost_Legacy::removeServiceTxt (char*) + * + */ +bool clsLEAMDNSHost_Legacy::removeServiceTxt(const char* p_pcInstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol, + const char* p_pcKey) +{ + hMDNSService hService = 0; + return ( ((hService = (m_HostInformations.empty() + ? 0 + : (hMDNSService)m_HostInformations.front().m_pHost->findService(p_pcInstanceName, p_pcServiceName, p_pcProtocol)))) + && (removeServiceTxt(hService, p_pcKey))); +} + +/* + * clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback (global) + * + */ +bool clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFn p_fnCallback) +{ + bool bResult = true; + + if ((bResult = m_HostInformations.empty())) + { + // The service handles of the first host are the keys in the HostInformations.HandleToPtr map + for (const clsLEAMDNSHost::clsService* pService : m_HostInformations.front().m_pHost->services()) + { + if (!((bResult = setDynamicServiceTxtCallback((hMDNSService)pService, p_fnCallback)))) + { + break; + } + } + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback (service) + * + */ +bool clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback(const hMDNSService p_hService, + MDNSDynamicServiceTxtCallbackFn p_fnCallback) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; + bResult = pService->setDynamicServiceTxtCallback([p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/)->void + { + if (p_fnCallback) // void(const hMDNSService p_hService) + { + p_fnCallback(p_hService); + } + }); + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (char*) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + const char* p_pcValue) +{ + return _addServiceTxt(p_hService, p_pcKey, p_pcValue, true); +} + +/* + * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (uint32) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint32_t p_u32Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_u32Value, true); +} + +/* + * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (uint16) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint16_t p_u16Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_u16Value, true); +} + +/* + * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (uint8) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint8_t p_u8Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_u8Value, true); +} + +/* + * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (int32) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int32_t p_i32Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_i32Value, true); +} + +/* + * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (int16) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int16_t p_i16Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_i16Value, true); +} + +/* + * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (int8) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int8_t p_i8Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_i8Value, true); +} + + +/* + * + * STATIC QUERY + * + */ + + /* + * clsLEAMDNSHost_Legacy::queryService + * + * This will take p_u16Timeout millisec for every host! + * + */ +uint32_t clsLEAMDNSHost_Legacy::queryService(const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) +{ + uint32_t u32Answers = 0; + + for (stcHostInformation& hostInformation : m_HostInformations) + { + u32Answers += (hostInformation.m_pHost->queryService(p_pcService, p_pcProtocol, p_u16Timeout)).size(); + } + return u32Answers; +} + +/* + * clsLEAMDNSHost_Legacy::removeQuery + * + */ +bool clsLEAMDNSHost_Legacy::removeQuery(void) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->removeQuery(); + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::queryService + * + */ +uint32_t clsLEAMDNSHost_Legacy::queryService(String p_strService, + String p_strProtocol) +{ + return queryService(p_strService.c_str(), p_strProtocol.c_str()); +} + +/* + * clsLEAMDNSHost_Legacy::answerHostname + * + */ +const char* clsLEAMDNSHost_Legacy::answerHostname(const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_u32AnswerIndex); + return (answerAccessor.serviceDomainAvailable() + ? answerAccessor.serviceDomain() + : 0); +} + +/* + * clsLEAMDNSHost_Legacy::answerIP + * + */ +IPAddress clsLEAMDNSHost_Legacy::answerIP(const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_u32AnswerIndex); + return (answerAccessor.IPv4AddressAvailable() + ? answerAccessor.IPv4Addresses()[0] + : IPAddress()); +} + +/* + * clsLEAMDNSHost_Legacy::answerPort + * + */ +uint16_t clsLEAMDNSHost_Legacy::answerPort(const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_u32AnswerIndex); + return (answerAccessor.hostPortAvailable() + ? answerAccessor.hostPort() + : 0); +} + +/* + * clsLEAMDNSHost_Legacy::hostname + * + */ +String clsLEAMDNSHost_Legacy::hostname(const uint32_t p_u32AnswerIndex) +{ + return String(answerHostname(p_u32AnswerIndex)); +} + +/* + * clsLEAMDNSHost_Legacy::IP + * + */ +IPAddress clsLEAMDNSHost_Legacy::IP(const uint32_t p_u32AnswerIndex) +{ + return answerIP(p_u32AnswerIndex); +} + +/* + * clsLEAMDNSHost_Legacy::port + * + */ +uint16_t clsLEAMDNSHost_Legacy::port(const uint32_t p_u32AnswerIndex) +{ + return answerPort(p_u32AnswerIndex); +} + + +/* + * + * DYNAMIC QUERY + * + */ + +/* + * clsLEAMDNSHost_Legacy::installServiceQuery + * + */ +clsLEAMDNSHost_Legacy::hMDNSServiceQuery clsLEAMDNSHost_Legacy::installServiceQuery(const char* p_pcService, + const char* p_pcProtocol, + MDNSServiceQueryCallbackFn p_fnCallback) +{ + hMDNSServiceQuery hResult = 0; + + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsQuery* pQuery = hostInformation.m_pHost->installServiceQuery(p_pcService, p_pcProtocol, [this, p_fnCallback](const clsLEAMDNSHost::clsQuery& /*p_Query*/, + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor& p_AnswerAccessor, + clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)->void + { + if (p_fnCallback) // void(const stcMDNSServiceInfo& p_MDNSServiceInfo, MDNSResponder::AnswerType p_AnswerType, bool p_bSetContent) + { + p_fnCallback(stcMDNSServiceInfo(p_AnswerAccessor), _answerFlagsToAnswerType(p_QueryAnswerTypeFlags), p_bSetContent); + } + }); + if (pQuery) + { + if (!hResult) + { // Store first query as result and key + hResult = (hMDNSServiceQuery)pQuery; + } + hostInformation.m_HandleToPtr[hResult] = pQuery; + } + } + return hResult; +} + +/* + * clsLEAMDNSHost_Legacy::removeServiceQuery + * + */ +bool clsLEAMDNSHost_Legacy::removeServiceQuery(clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + if ((bResult = (*it).m_pHost->removeQuery((clsLEAMDNSHost::clsQuery*)(*it).m_HandleToPtr[p_hServiceQuery]))) + { + (*it).m_HandleToPtr.erase(p_hServiceQuery); + } + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::answerCount + * + */ +uint32_t clsLEAMDNSHost_Legacy::answerCount(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery) +{ + uint32_t u32AnswerCount = 0; + + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; + if (pQuery) + { + u32AnswerCount += pQuery->answerCount(); + } + else + { + u32AnswerCount = 0; + break; + } + } + return u32AnswerCount; +} + +/* + * clsLEAMDNSHost_Legacy::answerInfo + * + */ +std::vector<clsLEAMDNSHost_Legacy::stcMDNSServiceInfo> clsLEAMDNSHost_Legacy::answerInfo(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery) +{ + std::vector<stcMDNSServiceInfo> serviceInfos; + + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; + if (pQuery) + { + for (clsLEAMDNSHost::clsQuery::clsAnswerAccessor& answerAccessor : pQuery->answerAccessors()) + { + serviceInfos.push_back(stcMDNSServiceInfo(answerAccessor)); + } + } + else + { + serviceInfos.clear(); + break; + } + } + return serviceInfos; +} + +/* + * clsLEAMDNSHost_Legacy::answerServiceDomain + * + */ +const char* clsLEAMDNSHost_Legacy::answerServiceDomain(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.serviceDomainAvailable() + ? answerAccessor.serviceDomain() + : 0); +} + +/* + * clsLEAMDNSHost_Legacy::hasAnswerHostDomain + * + */ +bool clsLEAMDNSHost_Legacy::hasAnswerHostDomain(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).hostDomainAvailable(); +} + +/* + * clsLEAMDNSHost_Legacy::answerHostDomain + * + */ +const char* clsLEAMDNSHost_Legacy::answerHostDomain(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.hostDomainAvailable() + ? answerAccessor.hostDomain() + : 0); +} + +#ifdef MDNS_IP4_SUPPORT +/* + * clsLEAMDNSHost_Legacy::hasAnswerIP4Address + * + */ +bool clsLEAMDNSHost_Legacy::hasAnswerIP4Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).IPv4AddressAvailable(); +} + +/* + * clsLEAMDNSHost_Legacy::answerIP4AddressCount + * + */ +uint32_t clsLEAMDNSHost_Legacy::answerIP4AddressCount(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.IPv4AddressAvailable() + ? answerAccessor.IPv4Addresses().size() + : 0); +} + +/* + * clsLEAMDNSHost_Legacy::answerIP4Address + * + */ +IPAddress clsLEAMDNSHost_Legacy::answerIP4Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.IPv4AddressAvailable() + ? answerAccessor.IPv4Addresses()[p_u32AddressIndex] + : IPAddress()); +} +#endif +#ifdef MDNS_IP6_SUPPORT +/* + * clsLEAMDNSHost_Legacy::hasAnswerIP6Address + * + */ +bool clsLEAMDNSHost_Legacy::hasAnswerIP6Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).IPv6AddressAvailable(); +} + +/* + * clsLEAMDNSHost_Legacy::answerIP6AddressCount + * + */ +uint32_t clsLEAMDNSHost_Legacy::answerIP6AddressCount(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.IPv6AddressAvailable() + ? answerAccessor.IPv6Addresses().size() + : 0); +} + +/* + * clsLEAMDNSHost_Legacy::answerIP6Address + * + */ +IPAddress clsLEAMDNSHost_Legacy::answerIP6Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.IPv6AddressAvailable() + ? answerAccessor.IPv6Addresses()[p_u32AddressIndex] + : IPAddress()); +} +#endif + +/* + * clsLEAMDNSHost_Legacy::hasAnswerPort + * + */ +bool clsLEAMDNSHost_Legacy::hasAnswerPort(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).hostPortAvailable(); +} + +/* + * clsLEAMDNSHost_Legacy::answerPort + * + */ +uint16_t clsLEAMDNSHost_Legacy::answerPort(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.hostPortAvailable() + ? answerAccessor.hostPort() + : 0); +} + +/* + * clsLEAMDNSHost_Legacy::hasAnswerTxts + * + */ +bool clsLEAMDNSHost_Legacy::hasAnswerTxts(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).txtsAvailable(); +} + +/* + * clsLEAMDNSHost_Legacy::answerHostDomain + * + * Get the TXT items as a ';'-separated string + */ +const char* clsLEAMDNSHost_Legacy::answerTxts(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.txtsAvailable() + ? answerAccessor.txts() + : 0); +} + + +/* + * + * HOST/SERVICE PROBE CALLBACKS + * + */ + +/* + * clsLEAMDNSHost_Legacy::setHostProbeResultCallback + * + */ +bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MDNSHostProbeResultCallbackFn p_fnCallback) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->setProbeResultCallback([p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, + const char* p_pcDomainName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void(const char* p_pcDomainName, bool p_bProbeResult) + { + p_fnCallback(p_pcDomainName, p_bProbeResult); + } + }); + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::setHostProbeResultCallback + * + */ +bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MDNSHostProbeResultCallbackFn2 p_fnCallback) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->setProbeResultCallback([this, p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, + const char* p_pcDomainName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcDomainName, bool p_bProbeResult) + { + p_fnCallback(this, p_pcDomainName, p_bProbeResult); + } + }); + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::setServiceProbeResultCallback + * + */ +bool clsLEAMDNSHost_Legacy::setServiceProbeResultCallback(const clsLEAMDNSHost_Legacy::hMDNSService p_hService, + clsLEAMDNSHost_Legacy::MDNSServiceProbeResultCallbackFn p_fnCallback) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + clsLEAMDNSHost::clsService* pService = 0; + bResult = ( ((pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService])) + && (pService->setProbeResultCallback([this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, + const char* p_pcInstanceName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void(const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) + { + p_fnCallback(p_pcInstanceName, p_hService, p_bProbeResult); + } + }))); + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::setServiceProbeResultCallback + * + */ +bool clsLEAMDNSHost_Legacy::setServiceProbeResultCallback(const clsLEAMDNSHost_Legacy::hMDNSService p_hService, + clsLEAMDNSHost_Legacy::MDNSServiceProbeResultCallbackFn2 p_fnCallback) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + clsLEAMDNSHost::clsService* pService = 0; + bResult = ( ((pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService])) + && (pService->setProbeResultCallback([this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, + const char* p_pcInstanceName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void((clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) + { + p_fnCallback(this, p_pcInstanceName, p_hService, p_bProbeResult); + } + }))); + } + return bResult; +} + + +/* + * + * PROCESS + * + */ + +/* + * clsLEAMDNSHost_Legacy::notifyAPChange + * + */ +bool clsLEAMDNSHost_Legacy::notifyAPChange(void) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->restart(); + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::update + * + */ +bool clsLEAMDNSHost_Legacy::update(void) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->update(); + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::announce + * + */ +bool clsLEAMDNSHost_Legacy::announce(void) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->announce(true, true); + } + return bResult; +} + +/* + * clsLEAMDNSHost_Legacy::enableArduino + * + */ +clsLEAMDNSHost_Legacy::hMDNSService clsLEAMDNSHost_Legacy::enableArduino(uint16_t p_u16Port, + bool p_bAuthUpload /*= false*/) +{ + hMDNSService hService = addService(0, "arduino", "tcp", p_u16Port); + if (hService) + { + if ( (!addServiceTxt(hService, "tcp_check", "no")) + || (!addServiceTxt(hService, "ssh_upload", "no")) + || (!addServiceTxt(hService, "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD))) + || (!addServiceTxt(hService, "auth_upload", (p_bAuthUpload) ? "yes" : "no"))) + { + removeService(hService); + hService = 0; + } + } + return hService; +} + +/* + * clsLEAMDNSHost_Legacy::indexDomain + * + */ +bool clsLEAMDNSHost_Legacy::indexDomain(char*& p_rpcDomain, + const char* p_pcDivider /*= "-"*/, + const char* p_pcDefaultDomain /*= 0*/) +{ + bool bResult = false; + + const char* cpcDomainName = clsLEAMDNSHost::indexDomainName(p_rpcDomain, p_pcDivider, p_pcDefaultDomain); + delete[] p_rpcDomain; + p_rpcDomain = 0; + if ( (cpcDomainName) + && ((p_rpcDomain = new char[strlen(cpcDomainName) + 1]))) + { + strcpy(p_rpcDomain, cpcDomainName); + bResult = true; + } + return bResult; +} + + +/* + * + * INTERNAL HELPERS + * + */ + +/* + * clsLEAMDNSHost_Legacy::_addServiceTxt (char*) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bDynamic) +{ + hMDNSTxt hResult = 0; + + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsService* pService = 0; + clsLEAMDNSHost::clsServiceTxt* pTxt = 0; + if ( ((pService = (clsLEAMDNSHost::clsService*)hostInformation.m_HandleToPtr[p_hService])) + && ((pTxt = (p_bDynamic + ? pService->addDynamicServiceTxt(p_pcKey, p_pcValue) + : pService->addServiceTxt(p_pcKey, p_pcValue))))) + { + if (!hResult) + { + hResult = (hMDNSTxt)pTxt; + } + hostInformation.m_HandleToPtr[hResult] = pTxt; + } + } + return hResult; +} + +/* + * clsLEAMDNSHost_Legacy::_addServiceTxt (uint32_t) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint32_t p_u32Value, + bool p_bDynamic) +{ + char acValueBuffer[16]; // 32-bit max 10 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%u", p_u32Value); + + return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); +} + +/* + * clsLEAMDNSHost_Legacy::_addServiceTxt (uint16_t) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint16_t p_u16Value, + bool p_bDynamic) +{ + char acValueBuffer[8]; // 16-bit max 5 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%hu", p_u16Value); + + return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); +} + +/* + * clsLEAMDNSHost_Legacy::_addServiceTxt (uint8_t) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint8_t p_u8Value, + bool p_bDynamic) +{ + char acValueBuffer[8]; // 8-bit max 3 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%hhu", p_u8Value); + + return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); +} + +/* + * clsLEAMDNSHost_Legacy::_addServiceTxt (int32_t) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int32_t p_i32Value, + bool p_bDynamic) +{ + char acValueBuffer[16]; // 32-bit max 11 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%i", p_i32Value); + + return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); +} + +/* + * clsLEAMDNSHost_Legacy::_addServiceTxt (int16_t) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int16_t p_i16Value, + bool p_bDynamic) +{ + char acValueBuffer[8]; // 16-bit max 6 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%hi", p_i16Value); + + return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); +} + +/* + * clsLEAMDNSHost_Legacy::_addServiceTxt (int8_t) + * + */ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int8_t p_i8Value, + bool p_bDynamic) +{ + char acValueBuffer[8]; // 8-bit max 4 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%hhi", p_i8Value); + + return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); +} + +/* + * clsLEAMDNSHost_Legacy::_answerFlagsToAnswerType + * + */ +clsLEAMDNSHost_Legacy::AnswerType clsLEAMDNSHost_Legacy::_answerFlagsToAnswerType(clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags) const +{ + AnswerType answerType = AnswerType::Unknown; + + if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Unknown) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::Unknown; + } + else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::ServiceDomain; + } + else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomain) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::HostDomainAndPort; + } + else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Port) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::HostDomainAndPort; + } + else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::Txt; + } +#ifdef MDNS_IP4_SUPPORT + else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::IP4Address; + } +#endif +#ifdef MDNS_IP6_SUPPORT + else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::IP6Address; + } +#endif + return answerType; +} + +/* + * clsLEAMDNSHost_Legacy::_getAnswerAccessor + * + */ +clsLEAMDNSHost_Legacy::clsLEAMDNSHost::clsQuery::clsAnswerAccessor clsLEAMDNSHost_Legacy::_getAnswerAccessor(const uint32_t p_u32AnswerIndex) +{ + uint32_t u32AnswerIndexWithoutOffset = p_u32AnswerIndex; + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsQuery* pQuery = hostInformation.m_pHost->getQuery(); + if (pQuery) + { + if (pQuery->answerCount() > u32AnswerIndexWithoutOffset) + { + return pQuery->answerAccessor(u32AnswerIndexWithoutOffset); + } + else + { + u32AnswerIndexWithoutOffset -= pQuery->answerCount(); + } + } + else + { + break; + } + } + return clsLEAMDNSHost::clsQuery::clsAnswerAccessor(0); +} + +/* + * clsLEAMDNSHost_Legacy::_getAnswerAccessor + * + */ +clsLEAMDNSHost_Legacy::clsLEAMDNSHost::clsQuery::clsAnswerAccessor clsLEAMDNSHost_Legacy::_getAnswerAccessor(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + uint32_t u32AnswerIndexWithoutOffset = p_u32AnswerIndex; + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; + if (pQuery) + { + if (pQuery->answerCount() > u32AnswerIndexWithoutOffset) + { + return pQuery->answerAccessor(u32AnswerIndexWithoutOffset); + } + else + { + u32AnswerIndexWithoutOffset -= pQuery->answerCount(); + } + } + else + { + break; + } + } + return clsLEAMDNSHost::clsQuery::clsAnswerAccessor(0); +} + + +} // namespace MDNSImplementation + + +} // namespace esp8266 + + + + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h new file mode 100644 index 0000000000..3b37dd5451 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h @@ -0,0 +1,679 @@ +/* + * LEAmDNS2_Legacy.h + * (c) 2020, LaborEtArs + * + * Version 0.9 beta + * + * Some notes (from LaborEtArs, 2018): + * Essentially, this is an rewrite of the original EPS8266 Multicast DNS code (ESP8266mDNS). + * The target of this rewrite was to keep the existing interface as stable as possible while + * adding and extending the supported set of mDNS features. + * A lot of the additions were basicly taken from Erik Ekman's lwIP mdns app code. + * + * Supported mDNS features (in some cases somewhat limited): + * - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service + * - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented + * - Probing host and service domains for uniqueness in the local network + * - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak) + * - Announcing available services after successful probing + * - Using fixed service TXT items or + * - Using dynamic service TXT items for presented services (via callback) + * - Remove services (and un-announcing them to the observers by sending goodbye-messages) + * - Static queries for DNS-SD services (creating a fixed answer set after a certain timeout period) + * - Dynamic queries for DNS-SD services with cached and updated answers and user notifications + * + * + * Usage: + * In most cases, this implementation should work as a 'drop-in' replacement for the original + * ESP8266 Multicast DNS code. Adjustments to the existing code would only be needed, if some + * of the new features should be used. + * + * For presenting services: + * In 'setup()': + * Install a callback for the probing of host (and service) domains via 'MDNS.setProbeResultCallback(probeResultCallback, &userData);' + * Register DNS-SD services with 'clsLEAMDNSHost_Legacy::hMDNSService hService = MDNS.addService("MyESP", "http", "tcp", 5000);' + * (Install additional callbacks for the probing of these service domains via 'MDNS.setServiceProbeResultCallback(hService, probeResultCallback, &userData);') + * Add service TXT items with 'MDNS.addServiceTxt(hService, "c#", "1");' or by installing a service TXT callback + * using 'MDNS.setDynamicServiceTxtCallback(dynamicServiceTxtCallback, &userData);' or service specific + * 'MDNS.setDynamicServiceTxtCallback(hService, dynamicServiceTxtCallback, &userData);' + * Call MDNS.begin("MyHostname"); + * + * In 'probeResultCallback(clsLEAMDNSHost_Legacy* p_MDNSResponder, const char* p_pcDomain, clsLEAMDNSHost_Legacy:hMDNSService p_hService, bool p_bProbeResult, void* p_pUserdata)': + * Check the probe result and update the host or service domain name if the probe failed + * + * In 'dynamicServiceTxtCallback(clsLEAMDNSHost_Legacy* p_MDNSResponder, const hMDNSService p_hService, void* p_pUserdata)': + * Add dynamic TXT items by calling 'MDNS.addDynamicServiceTxt(p_hService, "c#", "1");' + * + * In loop(): + * Call 'MDNS.update();' + * + * + * For querying services: + * Static: + * Call 'uint32_t u32AnswerCount = MDNS.queryService("http", "tcp");' + * Iterate answers by: 'for (uint32_t u=0; u<u32AnswerCount; ++u) { const char* pHostname = MDNS.answerHostname(u); }' + * You should call MDNS.removeQuery() sometimes later (when the answers are nott needed anymore) + * + * Dynamic: + * Install a dynamic query by calling 'DNSResponder::hMDNSServiceQuery hServiceQuery = MDNS.installServiceQuery("http", "tcp", serviceQueryCallback, &userData);' + * The callback 'serviceQueryCallback(clsLEAMDNSHost_Legacy* p_MDNSResponder, const hMDNSServiceQuery p_hServiceQuery, uint32_t p_u32AnswerIndex, + * enuServiceQueryAnswerType p_ServiceQueryAnswerType, bool p_bSetContent, void* p_pUserdata)' + * is called for any change in the answer set. + * Call 'MDNS.removeServiceQuery(hServiceQuery);' when the answers are not needed anymore + * + * + * Reference: + * Used mDNS messages: + * A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 + * AAAA (0x1C): eg. esp8266.local AAAA OP TTL 1234:5678::90 + * PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local + * PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local + * PTR (0x0C, IP4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local + * PTR (0x0C, IP6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local + * SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local + * TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 + * NSEC (0x2F): eg. esp8266.local ... (DNSSEC) + * + * Some NOT used message types: + * OPT (0x29): eDNS + * + * + * License (MIT license): + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef __LEAMDNS2HOST_LEGACY_H__ +#define __LEAMDNS2HOST_LEGACY_H__ + +#include "LEAmDNS2Host.h" + + +namespace esp8266 +{ + +namespace MDNSImplementation +{ + +/** + * clsLEAMDNSHost_Legacy + */ +class clsLEAMDNSHost_Legacy +{ + using clsLEAMDNSHost = esp8266::experimental::clsLEAMDNSHost; + + /** + clsConsts + */ + class clsConsts + { + public: + static const uint16_t u16StaticQueryWaitTime = 1000; // Default wait time for query responses + }; + +public: + /* INTERFACE */ + clsLEAMDNSHost_Legacy(void); + virtual ~clsLEAMDNSHost_Legacy(void); + + // Start the MDNS responder by setting the default hostname + // Later call MDNS::update() in every 'loop' to run the process loop + // (probing, announcing, responding, ...) + bool begin(const char* p_pcHostname); + bool begin(const String& p_strHostname); + // for compatibility + bool begin(const char* p_pcHostname, + IPAddress p_IPAddress /*= INADDR_ANY*/, // ignored + uint32_t p_u32TTL /*= 120*/); // ignored + bool begin(const String& p_strHostname, + IPAddress p_IPAddress /*= INADDR_ANY*/, // ignored + uint32_t p_u32TTL /*= 120*/); // ignored + // Finish MDNS processing + bool close(void); + // for ESP32 compatibility + bool end(void); + // NEW! The ESP-default network interfaces are 'auto-added' via 'begin' when active + // Additional netifs may be added, but if done so after calling 'update' for the + // first time, 'notifyAPChange' should be called to restart the probing/announcing process + bool addHostForNetIf(const char* p_pcHostname, + netif* p_pNetIf); + + // Change hostname (probing is restarted) + // Caution! The final hostname (after probing) may be different for every host + bool setHostname(const char* p_pcHostname); + // for compatibility... + bool setHostname(String p_strHostname); + + const char* hostname(void) const; + + bool status(void) const; + + /** + * hMDNSService (opaque handle to access the service) + */ + typedef const void* hMDNSService; + + // Add a new service to the MDNS responder. If no name (instance name) is given (p_pcName = 0) + // the current hostname is used. If the hostname is changed later, the instance names for + // these 'auto-named' services are changed to the new name also (and probing is restarted). + // The usual '_' before p_pcService (eg. http) and protocol (eg. tcp) may be given. + hMDNSService addService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + uint16_t p_u16Port); + // Removes a service from the MDNS responder + bool removeService(const hMDNSService p_hService); + bool removeService(const char* p_pcInstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol); + // for compatibility... + bool addService(String p_strServiceName, + String p_strProtocol, + uint16_t p_u16Port); + + + // Change the services instance name (and restart probing). + bool setServiceName(const hMDNSService p_hService, + const char* p_pcInstanceName); + //for compatibility + void setInstanceName(const char* p_pcHostname); + + // for ESP32 compatibility + void setInstanceName(const String& p_strHostname); + + const char* serviceName(const hMDNSService p_hService) const; + const char* service(const hMDNSService p_hService) const; + const char* serviceProtocol(const hMDNSService p_hService) const; + + bool serviceStatus(const hMDNSService p_hService) const; + + /** + * hMDNSTxt (opaque handle to access the TXT items) + */ + typedef void* hMDNSTxt; + + // 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); + + // Remove an existing (static) MDNS TXT item from the service + bool removeServiceTxt(const hMDNSService p_hService, + const hMDNSTxt p_hTxt); + bool removeServiceTxt(const hMDNSService p_hService, + const char* p_pcKey); + bool removeServiceTxt(const char* p_pcinstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol, + const char* p_pcKey); + // for compatibility... + bool addServiceTxt(const char* p_pcService, + const char* p_pcProtocol, + const char* p_pcKey, + const char* p_pcValue); + bool addServiceTxt(String p_strService, + String p_strProtocol, + String p_strKey, + String p_strValue); + + /** + * MDNSDynamicServiceTxtCallbackFn + * Callback function for dynamic MDNS TXT items + */ + typedef std::function<void(const hMDNSService p_hService)> MDNSDynamicServiceTxtCallbackFn; + + // Set a global callback for dynamic MDNS TXT items. The callback function is called + // every time, a TXT item is needed for one of the installed services. + bool setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFn p_fnCallback); + + // Set a service specific callback for dynamic MDNS TXT items. The callback function + // is called every time, a TXT item is needed for the given service. + bool setDynamicServiceTxtCallback(const hMDNSService p_hService, + MDNSDynamicServiceTxtCallbackFn p_fnCallback); + + // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service + // Dynamic TXT items are removed right after one-time use. So they need to be added + // every time the value s needed (via callback). + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + const char* p_pcValue); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint32_t p_u32Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint16_t p_u16Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint8_t p_u8Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int32_t p_i32Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int16_t p_i16Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int8_t p_i8Value); + + // Perform a (static) service query. The function returns after p_u16Timeout milliseconds + // The answers (the number of received answers is returned) can be retrieved by calling + // - answerHostname (or hostname) + // - answerIP (or IP) + // - answerPort (or port) + uint32_t queryService(const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout = clsConsts::u16StaticQueryWaitTime); + bool removeQuery(void); + // for compatibility... + uint32_t queryService(String p_strService, + String p_strProtocol); + + const char* answerHostname(const uint32_t p_u32AnswerIndex); + IPAddress answerIP(const uint32_t p_u32AnswerIndex); + uint16_t answerPort(const uint32_t p_u32AnswerIndex); + // for compatibility... + String hostname(const uint32_t p_u32AnswerIndex); + IPAddress IP(const uint32_t p_u32AnswerIndex); + uint16_t port(const uint32_t p_u32AnswerIndex); + + /** + * hMDNSServiceQuery (opaque handle to access dynamic service queries) + */ + typedef const void* hMDNSServiceQuery; + + /** + * enuServiceQueryAnswerType + */ + typedef enum _enuServiceQueryAnswerType { + ServiceQueryAnswerType_Unknown = 0, + ServiceQueryAnswerType_ServiceDomain = (1 << 0), // Service instance name + ServiceQueryAnswerType_HostDomainAndPort = (1 << 1), // Host domain and service port + ServiceQueryAnswerType_Txts = (1 << 2), // TXT items +#ifdef MDNS_IP4_SUPPORT + ServiceQueryAnswerType_IP4Address = (1 << 3), // IP4 address +#endif +#ifdef MDNS_IP6_SUPPORT + ServiceQueryAnswerType_IP6Address = (1 << 4), // IP6 address +#endif + } enuServiceQueryAnswerType; + + /** + * AnswerType (std::map compatible version) + */ + enum class AnswerType : uint32_t { + Unknown = ServiceQueryAnswerType_Unknown, + ServiceDomain = ServiceQueryAnswerType_ServiceDomain, + HostDomainAndPort = ServiceQueryAnswerType_HostDomainAndPort, + Txt = ServiceQueryAnswerType_Txts, +#ifdef MDNS_IP4_SUPPORT + IP4Address = ServiceQueryAnswerType_IP4Address, +#endif +#ifdef MDNS_IP6_SUPPORT + IP6Address = ServiceQueryAnswerType_IP6Address +#endif + }; + + /** + * stcMDNSServiceInfo + */ + struct stcMDNSServiceInfo { + stcMDNSServiceInfo(const clsLEAMDNSHost::clsQuery::clsAnswerAccessor& p_rAnswerAccessor) + : m_rAnswerAccessor(p_rAnswerAccessor) {}; + /** + * stcCompareKey + */ + struct stcCompareKey { + /* + * operator () + */ + bool operator()(char const* p_pA, char const* p_pB) const { + return (0 > strcmp(p_pA, p_pB)); + } + }; + /** + * clsKeyValueMap + */ + using clsKeyValueMap = std::map<const char*, const char*, stcCompareKey>; + + protected: + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor& m_rAnswerAccessor; + clsKeyValueMap m_KeyValueMap; + + public: + /* + * serviceDomain + */ + const char* serviceDomain(void) const { + return (m_rAnswerAccessor.serviceDomainAvailable() + ? m_rAnswerAccessor.serviceDomain() + : nullptr); + } + /* + * hostDomainAvailable + */ + bool hostDomainAvailable(void) const { + return m_rAnswerAccessor.serviceDomainAvailable(); + } + /* + * hostDomain + */ + const char* hostDomain(void) const { + return (hostDomainAvailable() + ? m_rAnswerAccessor.hostDomain() + : nullptr); + } + /* + * hostPortAvailable + */ + bool hostPortAvailable(void) const { + return m_rAnswerAccessor.hostPortAvailable(); + } + /* + * hostPort + */ + uint16_t hostPort(void) const { + return (hostPortAvailable() + ? m_rAnswerAccessor.hostPort() + : 0); + } +#ifdef MDNS_IP4_SUPPORT + /* + * IP4AddressAvailable + */ + bool IP4AddressAvailable(void) const { + return m_rAnswerAccessor.IPv4AddressAvailable(); + } + /* + * IP4Addresses + */ + std::vector<IPAddress> IP4Adresses(void) const { + return (IP4AddressAvailable() + ? m_rAnswerAccessor.IPv4Addresses() + : std::vector<IPAddress>()); + } +#endif +#ifdef MDNS_IP6_SUPPORT + /* + * IP6AddressAvailable + */ + bool IP6AddressAvailable(void) const { + return m_rAnswerAccessor.IPv6AddressAvailable(); + } + /* + * IP6Addresses + */ + std::vector<IPAddress> IP6Adresses(void) const { + return (IP6AddressAvailable() + ? m_rAnswerAccessor.IPv6Addresses() + : std::vector<IPAddress>()); + } +#endif + /* + * txtAvailable + */ + bool txtAvailable(void) const { + return m_rAnswerAccessor.txtsAvailable(); + } + /* + * strKeyValue -> abc=def;hij=klm; + */ + const char* strKeyValue (void) const { + // TODO + return nullptr; + } + /* + * keyValues -> abc=def hij=klm ... + */ + const clsKeyValueMap& keyValues(void) { + if ((txtAvailable()) && + (0 == m_KeyValueMap.size())) { + for (auto kv : m_rAnswerAccessor.txtKeyValues()) + { + m_KeyValueMap.emplace(std::pair<const char*,const char*>(kv.first, kv.second)); + } + //for (auto kv=m_rMDNSResponder._answerKeyValue(m_hServiceQuery, m_u32AnswerIndex); kv!=nullptr; kv=kv->m_pNext) { + // m_KeyValueMap.emplace(std::pair<const char*,const char*>(kv->m_pcKey, kv->m_pcValue)); + //} + } + return m_KeyValueMap; + } + /* + * value (abc)->def + */ + const char* value(const char* p_pcKey) const { + return m_rAnswerAccessor.txtValue(p_pcKey); + } + }; + + /** + * MDNSServiceQueryCallbackFn + * + * Callback function for received answers for dynamic service queries + */ + typedef std::function<void(const stcMDNSServiceInfo& p_MDNSServiceInfo, + AnswerType p_AnswerType, // flags for the updated answer item + bool p_bSetContent // true: Answer component set, false: component deleted + )> MDNSServiceQueryCallbackFn; + + // Install a dynamic service query. For every received answer (part) the given callback + // function is called. The query will be updated every time, the TTL for an answer + // has timed-out. + // The answers can also be retrieved by calling + // - answerCount + // - answerServiceDomain + // - hasAnswerHostDomain/answerHostDomain + // - hasAnswerIP4Address/answerIP4Address + // - hasAnswerIP6Address/answerIP6Address + // - hasAnswerPort/answerPort + // - hasAnswerTxts/answerTxts + hMDNSServiceQuery installServiceQuery(const char* p_pcService, + const char* p_pcProtocol, + MDNSServiceQueryCallbackFn p_fnCallback); + // Remove a dynamic service query + bool removeServiceQuery(hMDNSServiceQuery p_hServiceQuery); + + uint32_t answerCount(const hMDNSServiceQuery p_hServiceQuery); + std::vector<stcMDNSServiceInfo> answerInfo(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery); + const char* answerServiceDomain(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + bool hasAnswerHostDomain(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + const char* answerHostDomain(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); +#ifdef MDNS_IP4_SUPPORT + bool hasAnswerIP4Address(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + uint32_t answerIP4AddressCount(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + IPAddress answerIP4Address(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex); +#endif +#ifdef MDNS_IP6_SUPPORT + bool hasAnswerIP6Address(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + uint32_t answerIP6AddressCount(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + IPAddress answerIP6Address(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex); +#endif + bool hasAnswerPort(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + uint16_t answerPort(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + bool hasAnswerTxts(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + // Get the TXT items as a ';'-separated string + const char* answerTxts(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + + /** + * MDNSHostProbeResultCallbackFn/2 + * Callback function for host domain probe results + */ + typedef std::function<void(const char* p_pcDomainName, + bool p_bProbeResult)> MDNSHostProbeResultCallbackFn; + + typedef std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, + const char* p_pcDomainName, + bool p_bProbeResult)> MDNSHostProbeResultCallbackFn2; + + // Set a callback function for host probe results + // The callback function is called, when the probeing for the host domain + // succeededs or fails. + // In case of failure, the failed domain name should be changed. + bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn p_fnCallback); + bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn2 p_fnCallback); + + /** + * MDNSServiceProbeResultCallbackFn/2 + * Callback function for service domain probe results + */ + typedef std::function<void(const char* p_pcServiceName, + const hMDNSService p_hMDNSService, + bool p_bProbeResult)> MDNSServiceProbeResultCallbackFn; + + typedef std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, + const char* p_pcServiceName, + const hMDNSService p_hMDNSService, + bool p_bProbeResult)> MDNSServiceProbeResultCallbackFn2; + + // Set a service specific probe result callcack + bool setServiceProbeResultCallback(const hMDNSService p_hService, + MDNSServiceProbeResultCallbackFn p_fnCallback); + bool setServiceProbeResultCallback(const hMDNSService p_hService, + MDNSServiceProbeResultCallbackFn2 p_fnCallback); + + // Application should call this whenever AP is configured/disabled + bool notifyAPChange(void); + + // 'update' should be called in every 'loop' to run the MDNS processing + bool update(void); + + // 'announce' can be called every time, the configuration of some service + // changes. Mainly, this would be changed content of TXT items. + bool announce(void); + + // Enable OTA update + hMDNSService enableArduino(uint16_t p_u16Port, + bool p_bAuthUpload = false); + + // Domain name helper + static bool indexDomain(char*& p_rpcDomain, + const char* p_pcDivider = "-", + const char* p_pcDefaultDomain = 0); + +protected: + /** + * stcHostInformation + */ + struct stcHostInformation + { + /** + * clsHandleToPtrMap + */ + using clsHandleToPtrMap = std::map<const void*, const void*>; + + clsLEAMDNSHost* m_pHost; + clsHandleToPtrMap m_HandleToPtr; + + stcHostInformation(clsLEAMDNSHost* p_pHost) + : m_pHost(p_pHost) + {} + + /** + * list + */ + using list = std::list<stcHostInformation>; + }; + + stcHostInformation::list m_HostInformations; + + // HELPERS + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bDynamic); + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint32_t p_u32Value, + bool p_bDynamic); + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint16_t p_u16Value, + bool p_bDynamic); + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint8_t p_u8Value, + bool p_bDynamic); + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int32_t p_i32Value, + bool p_bDynamic); + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int16_t p_i16Value, + bool p_bDynamic); + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int8_t p_i8Value, + bool p_bDynamic); + + AnswerType _answerFlagsToAnswerType(clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags) const; + + clsLEAMDNSHost::clsQuery::clsAnswerAccessor _getAnswerAccessor(const uint32_t p_u32AnswerIndex); + clsLEAMDNSHost::clsQuery::clsAnswerAccessor _getAnswerAccessor(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + +}; + + +} // namespace MDNSImplementation + + +} // namespace esp8266 + + +#endif // __LEAMDNS2HOST_LEGACY_H__ + + + + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h deleted file mode 100755 index 240700b7cf..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - LEAmDNS2_Priv.h - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#ifndef LEAMDNS2_PRIV_H -#define LEAMDNS2_PRIV_H - -namespace esp8266 -{ - -/* - LEAmDNS -*/ - -namespace experimental -{ - -// Enable class debug functions -#define ESP_8266_MDNS_INCLUDE -#define DEBUG_ESP_MDNS_RESPONDER - - -#ifndef LWIP_OPEN_SRC -#define LWIP_OPEN_SRC -#endif - -// -// If ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE is defined, the mDNS responder ignores a successful probing -// This allows to drive the responder in a environment, where 'update()' isn't called in the loop -//#define ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE - -// Enable/disable debug trace macros -#ifdef DEBUG_ESP_MDNS_RESPONDER -#define DEBUG_ESP_MDNS_INFO -#define DEBUG_ESP_MDNS_ERR -#define DEBUG_ESP_MDNS_TX -#define DEBUG_ESP_MDNS_RX -#endif - -#ifdef DEBUG_ESP_MDNS_RESPONDER -#ifdef DEBUG_ESP_MDNS_INFO -#define DEBUG_EX_INFO(A) A -#else -#define DEBUG_EX_INFO(A) -#endif -#ifdef DEBUG_ESP_MDNS_ERR -#define DEBUG_EX_ERR(A) A -#else -#define DEBUG_EX_ERR(A) -#endif -#ifdef DEBUG_ESP_MDNS_TX -#define DEBUG_EX_TX(A) A -#else -#define DEBUG_EX_TX(A) -#endif -#ifdef DEBUG_ESP_MDNS_RX -#define DEBUG_EX_RX(A) A -#else -#define DEBUG_EX_RX(A) -#endif - -#ifdef DEBUG_ESP_PORT -#define DEBUG_OUTPUT DEBUG_ESP_PORT -#else -#define DEBUG_OUTPUT Serial -#endif -#else -#define DEBUG_EX_INFO(A) -#define DEBUG_EX_ERR(A) -#define DEBUG_EX_TX(A) -#define DEBUG_EX_RX(A) -#endif - -/* - This is NOT the TTL (Time-To-Live) for MDNS records, but the - subnet level distance MDNS records should travel. - 1 sets the subnet distance to 'local', which is default for MDNS. - (Btw.: 255 would set it to 'as far as possible' -> internet) - - However, RFC 3171 seems to force 255 instead -*/ -#define MDNS_MULTICAST_TTL 255 /* some say 1 is right*/ - -/* - This is the MDNS record TTL - Host level records are set to 2min (120s) - service level records are set to 75min (4500s) -*/ -#define MDNS_LEGACY_TTL 10 -#define MDNS_HOST_TTL 120 -#define MDNS_SERVICE_TTL 4500 - -/* - Compressed labels are flaged by the two topmost bits of the length byte being set -*/ -#define MDNS_DOMAIN_COMPRESS_MARK 0xC0 -/* - Avoid endless recursion because of malformed compressed labels -*/ -#define MDNS_DOMAIN_MAX_REDIRCTION 6 - -/* - Default service priority and weight in SRV answers -*/ -#define MDNS_SRV_PRIORITY 0 -#define MDNS_SRV_WEIGHT 0 - -/* - Delay between and number of probes for host and service domains - Delay between and number of announces for host and service domains - Delay between and number of queries; the delay is multiplied by the resent number in '_checkQueryCache' -*/ -#define MDNS_PROBE_DELAY 250 -#define MDNS_PROBE_COUNT 3 -#define MDNS_ANNOUNCE_DELAY 1000 -#define MDNS_ANNOUNCE_COUNT 3 -#define MDNS_DYNAMIC_QUERY_RESEND_DELAY 1000 - - -/* - Force host domain to use only lowercase letters -*/ -//#define MDNS_FORCE_LOWERCASE_HOSTNAME - -/* - Enable/disable the usage of the F() macro in debug trace printf calls. - There needs to be an PGM comptible printf function to use this. - - USE_PGM_PRINTF and F -*/ -#define USE_PGM_PRINTF - -#ifdef USE_PGM_PRINTF -#else -#ifdef F -#undef F -#endif -#define F(A) A -#endif - -} // namespace MDNSImplementation - -} // namespace esp8266 - -// Include the main header, so the submodlues only need to include this header -#include "LEAmDNS2.h" - - -#endif // LEAMDNS2_PRIV_H diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h b/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h old mode 100755 new mode 100644 From d47f6f07e412659da52396ed6435ab059390a206 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 8 May 2020 11:29:26 +0200 Subject: [PATCH 004/152] style --- .../LEAmDNS/TwoInterfaces/TwoInterfaces.ino | 246 +- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 144 +- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 28 +- .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 260 +- .../ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp | 4 +- .../ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 192 +- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 180 +- .../ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 14 +- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 2988 +++++++++-------- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h | 1377 ++++---- 10 files changed, 2729 insertions(+), 2704 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino index 3434454491..3f06f543b7 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino @@ -12,151 +12,123 @@ ESP8266WebServer server(80); void connectToWiFi(const char* p_pcSSID, const char* p_pcPWD, - uint32_t p_u32Timeout = 20) -{ - WiFi.begin(p_pcSSID, p_pcPWD); + uint32_t p_u32Timeout = 20) { + WiFi.begin(p_pcSSID, p_pcPWD); + Serial.println(""); + + // Wait for connection + uint8 u8Tries = p_u32Timeout; + while ((WiFi.status() != WL_CONNECTED) && + (u8Tries--)) { + delay(500); + Serial.print("."); + } + if (WiFi.status() == WL_CONNECTED) { Serial.println(""); - - // Wait for connection - uint8 u8Tries = p_u32Timeout; - while ((WiFi.status() != WL_CONNECTED) && - (u8Tries--)) { - delay(500); - Serial.print("."); - } - if (WiFi.status() == WL_CONNECTED) - { - Serial.println(""); - Serial.print("Connected to "); - Serial.println(p_pcSSID); - Serial.print("IP address: "); - Serial.println(WiFi.localIP()); - } - else - { - Serial.printf("FAILED to connect to '%s'!\n", p_pcSSID); - } + Serial.print("Connected to "); + Serial.println(p_pcSSID); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + } else { + Serial.printf("FAILED to connect to '%s'!\n", p_pcSSID); + } } -void setup(void) -{ - Serial.begin(115200); - Serial.setDebugOutput(false); - delay(2000); - Serial.printf("\nStart\n"); - - // Setup WiFi and AP - WiFi.setAutoConnect(false); - WiFi.mode(WIFI_AP_STA); - WiFi.softAP("ESP8266", "12345678"); - Serial.print("Created AP "); - Serial.println("ESP8266"); - Serial.print("AP-IP address: "); - Serial.println(WiFi.softAPIP()); - - if (mDNSHost_AP.begin("ESP8266", WIFI_AP, [](clsMDNSHost& p_rMDNSHost, - const char* p_pcDomainName, - bool p_bProbeResult)->void - { - Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); - - // Unattended added service - p_rMDNSHost.addService(0, "http", "tcp", 80); - })) - { - Serial.println("mDNS-AP started"); - } - else - { - Serial.println("FAILED to start mDNS-AP"); - } - - // Connect to WiFi network, with WRONG password - connectToWiFi("AP8", "WRONG_PW", 5); - - if (mDNSHost_STA.begin("esp8266", WIFI_STA, [](clsMDNSHost& p_rMDNSHost, - const char* p_pcDomainName, - bool p_bProbeResult)->void - { - Serial.printf("mDNSHost_STA::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); - if (p_bProbeResult) - { - p_rMDNSHost.addService("LEA_Weather", "http", "tcp", 80, [](clsMDNSHost::clsService& p_rService, - const char* p_pcInstanceName, - bool p_bProbeResult)->void - { - Serial.printf("mDNSHost_STA::HTTP-Service::ProbeResultCallback: '%s' is %s\n", p_pcInstanceName, (p_bProbeResult ? "FREE" : "USED!")); - if (p_bProbeResult) - { - if (!p_rService.addServiceTxt("path", "/")) - { - Serial.println("FAILED to add service TXT item!"); - } - p_rService.setDynamicServiceTxtCallback([](clsMDNSHost::clsService& p_rService)->void - { - Serial.printf("mDNSHost_STA::HTTP-Service::DynamicTXTCallback\n"); - - p_rService.addDynamicServiceTxt("user", "admin"); - static uint32_t u32Counter = 0; - p_rService.addDynamicServiceTxt("cnt", ++u32Counter); - }); - } - else - { - if (p_rService.indexInstanceName()) - { - Serial.printf("Changed service instance name to '%s'\n", p_rService.instanceName()); - } - else - { - Serial.println("FAILED to index service instance name!"); - } - } - }); - - // Unattended added service - p_rMDNSHost.addService("MQTTInstance", "mqtt", "tcp", 1883); - } - else - { - p_rMDNSHost.indexHostName(); - } - })) - { - Serial.println("mDNS-STA started"); - } - else - { - Serial.println("FAILED to start mDNS-STA"); +void setup(void) { + Serial.begin(115200); + Serial.setDebugOutput(false); + delay(2000); + Serial.printf("\nStart\n"); + + // Setup WiFi and AP + WiFi.setAutoConnect(false); + WiFi.mode(WIFI_AP_STA); + WiFi.softAP("ESP8266", "12345678"); + Serial.print("Created AP "); + Serial.println("ESP8266"); + Serial.print("AP-IP address: "); + Serial.println(WiFi.softAPIP()); + + if (mDNSHost_AP.begin("ESP8266", WIFI_AP, [](clsMDNSHost & p_rMDNSHost, + const char* p_pcDomainName, + bool p_bProbeResult)->void { + Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); + + // Unattended added service + p_rMDNSHost.addService(0, "http", "tcp", 80); + })) { + Serial.println("mDNS-AP started"); + } else { + Serial.println("FAILED to start mDNS-AP"); + } + + // Connect to WiFi network, with WRONG password + connectToWiFi("AP8", "WRONG_PW", 5); + + if (mDNSHost_STA.begin("esp8266", WIFI_STA, [](clsMDNSHost & p_rMDNSHost, + const char* p_pcDomainName, + bool p_bProbeResult)->void { + Serial.printf("mDNSHost_STA::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); + if (p_bProbeResult) { + p_rMDNSHost.addService("LEA_Weather", "http", "tcp", 80, [](clsMDNSHost::clsService & p_rService, + const char* p_pcInstanceName, + bool p_bProbeResult)->void { + Serial.printf("mDNSHost_STA::HTTP-Service::ProbeResultCallback: '%s' is %s\n", p_pcInstanceName, (p_bProbeResult ? "FREE" : "USED!")); + if (p_bProbeResult) { + if (!p_rService.addServiceTxt("path", "/")) { + Serial.println("FAILED to add service TXT item!"); + } + p_rService.setDynamicServiceTxtCallback([](clsMDNSHost::clsService & p_rService)->void { + Serial.printf("mDNSHost_STA::HTTP-Service::DynamicTXTCallback\n"); + + p_rService.addDynamicServiceTxt("user", "admin"); + static uint32_t u32Counter = 0; + p_rService.addDynamicServiceTxt("cnt", ++u32Counter); + }); + } else { + if (p_rService.indexInstanceName()) { + Serial.printf("Changed service instance name to '%s'\n", p_rService.instanceName()); + } else { + Serial.println("FAILED to index service instance name!"); + } + } + }); + + // Unattended added service + p_rMDNSHost.addService("MQTTInstance", "mqtt", "tcp", 1883); + } else { + p_rMDNSHost.indexHostName(); } - - // Non-synchronized added service - mDNSHost_STA.addService(0, "test", "tcp", 999); - - // Setup HTTP server - server.on("/", [](void) - { - Serial.println("server.on"); - server.send(200, "text/plain", "test"); - }); - server.begin(); - Serial.println("HTTP server started"); + })) { + Serial.println("mDNS-STA started"); + } else { + Serial.println("FAILED to start mDNS-STA"); + } + + // Non-synchronized added service + mDNSHost_STA.addService(0, "test", "tcp", 999); + + // Setup HTTP server + server.on("/", [](void) { + Serial.println("server.on"); + server.send(200, "text/plain", "test"); + }); + server.begin(); + Serial.println("HTTP server started"); } -void loop(void) -{ - server.handleClient(); - mDNSHost_AP.update(); - mDNSHost_STA.update(); +void loop(void) { + server.handleClient(); + mDNSHost_AP.update(); + mDNSHost_STA.update(); - static esp8266::polledTimeout::oneShotMs timer2(esp8266::polledTimeout::oneShotMs::alwaysExpired); - if (timer2) - { - Serial.println("FIX PASSWORD"); - connectToWiFi("AP8", "_______"); + static esp8266::polledTimeout::oneShotMs timer2(esp8266::polledTimeout::oneShotMs::alwaysExpired); + if (timer2) { + Serial.println("FIX PASSWORD"); + connectToWiFi("AP8", "_______"); - timer2.reset(esp8266::polledTimeout::oneShotMs::neverExpires); - } + timer2.reset(esp8266::polledTimeout::oneShotMs::neverExpires); + } } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index dd46d09ad3..cee90c907c 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -51,8 +51,8 @@ const char* strrstr(const char*__restrict p_pcString, size_t stPatternLength = (p_pcPattern ? strlen(p_pcPattern) : 0); if ((stStringLength) && - (stPatternLength) && - (stPatternLength <= stStringLength)) + (stPatternLength) && + (stPatternLength <= stStringLength)) { // Pattern is shorter or has the same length than the string for (const char* s = (p_pcString + stStringLength - stPatternLength); s >= p_pcString; --s) @@ -99,8 +99,8 @@ namespace experimental */ //static const char* clsLEAMDNSHost::indexDomainName(const char* p_pcDomainName, - const char* p_pcDivider /*= "-"*/, - const char* p_pcDefaultDomainName /*= 0*/) + const char* p_pcDivider /*= "-"*/, + const char* p_pcDefaultDomainName /*= 0*/) { static char acResultDomainName[clsConsts::stDomainLabelMaxLength]; *acResultDomainName = 0; @@ -117,8 +117,8 @@ const char* clsLEAMDNSHost::indexDomainName(const char* p_pcDomainName, char* pEnd = 0; unsigned long ulIndex = strtoul((pFoundDivider + strlen(pcDivider)), &pEnd, 10); if ((ulIndex) && - ((pEnd - p_pcDomainName) == (ptrdiff_t)strlen(p_pcDomainName)) && - (!*pEnd)) + ((pEnd - p_pcDomainName) == (ptrdiff_t)strlen(p_pcDomainName)) && + (!*pEnd)) { // Valid (old) index found char acIndexBuffer[16]; @@ -165,7 +165,7 @@ bool clsLEAMDNSHost::setNetIfHostName(netif* p_pNetIf, const char* p_pcHostName) { if ((p_pNetIf) && - (p_pcHostName)) + (p_pcHostName)) { netif_set_hostname(p_pNetIf, (char*)p_pcHostName); // LWIP 1.x forces 'char*' instead of 'const char*' DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[mDNS] setNetIfHostName host name: %s!\n"), p_pcHostName);); @@ -332,7 +332,7 @@ bool clsLEAMDNSHost::setHostName(const char* p_pcHostName) for (clsService* pService : m_Services) { if ((pService->m_bAutoName) && - (!m_pcDefaultInstanceName)) + (!m_pcDefaultInstanceName)) { if (!((bResult = pService->setInstanceName(p_pcHostName)))) { @@ -426,10 +426,10 @@ const char* clsLEAMDNSHost::defaultInstanceName(void) const */ clsLEAMDNSHost::clsService* clsLEAMDNSHost::addService(const char* p_pcInstanceName, - const char* p_pcType, - const char* p_pcProtocol, - uint16_t p_u16Port, - clsLEAMDNSHost::clsService::fnProbeResultCallback p_fnCallback /*= 0*/) + const char* p_pcType, + const char* p_pcProtocol, + uint16_t p_u16Port, + clsLEAMDNSHost::clsService::fnProbeResultCallback p_fnCallback /*= 0*/) { clsService* pService = 0; @@ -439,10 +439,10 @@ clsLEAMDNSHost::clsService* clsLEAMDNSHost::addService(const char* p_pcInstanceN if ((pService = new clsService)) { if ((pService->setInstanceName(_instanceName(p_pcInstanceName))) && - (pService->setType(p_pcType)) && - (pService->setProtocol(p_pcProtocol)) && - (pService->setPort(p_u16Port)) && - (p_fnCallback ? pService->setProbeResultCallback(p_fnCallback) : true)) + (pService->setType(p_pcType)) && + (pService->setProtocol(p_pcProtocol)) && + (pService->setPort(p_u16Port)) && + (p_fnCallback ? pService->setProbeResultCallback(p_fnCallback) : true)) { m_Services.push_back(pService); } @@ -482,19 +482,19 @@ bool clsLEAMDNSHost::removeService(clsLEAMDNSHost::clsService* p_pService) */ const clsLEAMDNSHost::clsService* clsLEAMDNSHost::findService(const char* p_pcInstanceName, - const char* p_pcType, - const char* p_pcProtocol, - uint16_t p_u16Port/*= (uint16_t)(-1)*/) const + const char* p_pcType, + const char* p_pcProtocol, + uint16_t p_u16Port/*= (uint16_t)(-1)*/) const { clsService* pFoundService = 0; for (clsService* pService : m_Services) { if ((0 == strcmp(pService->instanceName(), _instanceName(p_pcInstanceName))) && - (0 == strcmp(pService->type(), p_pcType)) && - (0 == strcmp(pService->protocol(), p_pcProtocol)) && - (((uint16_t)(-1) == p_u16Port) || - (pService->port() == p_u16Port))) + (0 == strcmp(pService->type(), p_pcType)) && + (0 == strcmp(pService->protocol(), p_pcProtocol)) && + (((uint16_t)(-1) == p_u16Port) || + (pService->port() == p_u16Port))) { pFoundService = pService; break; @@ -508,20 +508,20 @@ const clsLEAMDNSHost::clsService* clsLEAMDNSHost::findService(const char* p_pcIn */ clsLEAMDNSHost::clsService* clsLEAMDNSHost::findService(const char* p_pcInstanceName, - const char* p_pcType, - const char* p_pcProtocol, - uint16_t p_u16Port /*= (uint16_t)(-1)*/) + const char* p_pcType, + const char* p_pcProtocol, + uint16_t p_u16Port /*= (uint16_t)(-1)*/) { return (clsService*)((const clsLEAMDNSHost*)this)->findService(p_pcInstanceName, p_pcType, p_pcProtocol, p_u16Port); } /* clsLEAMDNSHost::services - + */ const clsLEAMDNSHost::clsService::list& clsLEAMDNSHost::services(void) const { - return m_Services; + return m_Services; } @@ -536,21 +536,21 @@ const clsLEAMDNSHost::clsService::list& clsLEAMDNSHost::services(void) const */ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout) + const char* p_pcProtocol, + const uint16_t p_u16Timeout) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService '_%s._%s.local'\n"), _DH(), p_pcService, p_pcProtocol);); clsQuery* pQuery = 0; if ((p_pcService) && (*p_pcService) && - (p_pcProtocol) && (*p_pcProtocol) && - (p_u16Timeout) && - ((pQuery = _allocQuery(clsQuery::enuQueryType::Service))) && - (_buildDomainForService(p_pcService, p_pcProtocol, pQuery->m_Domain))) + (p_pcProtocol) && (*p_pcProtocol) && + (p_u16Timeout) && + ((pQuery = _allocQuery(clsQuery::enuQueryType::Service))) && + (_buildDomainForService(p_pcService, p_pcProtocol, pQuery->m_Domain))) { if ((_removeLegacyQuery()) && - ((pQuery->m_bStaticQuery = true)) && - (_sendQuery(*pQuery))) + ((pQuery->m_bStaticQuery = true)) && + (_sendQuery(*pQuery))) { // Wait for answers to arrive DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); @@ -579,19 +579,19 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryService */ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryHost(const char* p_pcHostName, - const uint16_t p_u16Timeout) + const uint16_t p_u16Timeout) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost '%s.local'\n"), _DH(), p_pcHostName);); clsQuery* pQuery = 0; if ((p_pcHostName) && (*p_pcHostName) && - (p_u16Timeout) && - ((pQuery = _allocQuery(clsQuery::enuQueryType::Host))) && - (_buildDomainForHost(p_pcHostName, pQuery->m_Domain))) + (p_u16Timeout) && + ((pQuery = _allocQuery(clsQuery::enuQueryType::Host))) && + (_buildDomainForHost(p_pcHostName, pQuery->m_Domain))) { if ((_removeLegacyQuery()) && - ((pQuery->m_bStaticQuery = true)) && - (_sendQuery(*pQuery))) + ((pQuery->m_bStaticQuery = true)) && + (_sendQuery(*pQuery))) { // Wait for answers to arrive DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); @@ -647,8 +647,8 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::getQuery(void) */ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) + const char* p_pcProtocol, + clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) { clsQuery* pQuery = 0; if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) @@ -663,8 +663,8 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcSe */ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) + const char* p_pcProtocol, + clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) { clsQuery* pQuery = 0; if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) @@ -678,7 +678,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcSe clsLEAmDNS2_Host::installHostQuery (answer) */ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, - clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) + clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) { clsQuery* pQuery = 0; if ((p_pcHostName) && (*p_pcHostName)) @@ -698,7 +698,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostN clsLEAmDNS2_Host::installHostQuery (accessor) */ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, - clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) + clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) { clsQuery* pQuery = 0; if ((p_pcHostName) && (*p_pcHostName)) @@ -803,7 +803,7 @@ UdpContext* clsLEAMDNSHost::_allocBackbone(void) DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocBackbone: Created backbone.\n"), _DH());); if ((clsBackbone::sm_pBackbone) && - (!clsBackbone::sm_pBackbone->init())) + (!clsBackbone::sm_pBackbone->init())) { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _allocBackbone: FAILED to init backbone!\n"), _DH());); @@ -828,8 +828,8 @@ bool clsLEAMDNSHost::_releaseBackbone(void) bool bResult = false; if ((clsBackbone::sm_pBackbone) && - ((bResult = clsBackbone::sm_pBackbone->removeHost(this))) && - (0 == clsBackbone::sm_pBackbone->hostCount())) + ((bResult = clsBackbone::sm_pBackbone->removeHost(this))) && + (0 == clsBackbone::sm_pBackbone->hostCount())) { delete clsBackbone::sm_pBackbone; clsBackbone::sm_pBackbone = 0; @@ -945,14 +945,14 @@ clsLEAMDNSHost::typeNetIfState clsLEAMDNSHost::_getNetIfState(void) const typeNetIfState curNetIfState = static_cast<typeNetIfState>(enuNetIfState::None); if ((m_pNetIf) && - (netif_is_up(m_pNetIf))) + (netif_is_up(m_pNetIf))) { curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::IsUp); // Check if netif link is up if ((netif_is_link_up(m_pNetIf)) && - ((m_pNetIf != netif_get_by_index(WIFI_STA)) || - (STATION_GOT_IP == wifi_station_get_connect_status()))) + ((m_pNetIf != netif_get_by_index(WIFI_STA)) || + (STATION_GOT_IP == wifi_station_get_connect_status()))) { curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::LinkIsUp); } @@ -1084,7 +1084,7 @@ bool clsLEAMDNSHost::_allocDomainName(const char* p_pcNewDomainName, size_t stLength = 0; if ((p_pcNewDomainName) && - (clsConsts::stDomainLabelMaxLength >= (stLength = strlen(p_pcNewDomainName)))) // char max size for a single label + (clsConsts::stDomainLabelMaxLength >= (stLength = strlen(p_pcNewDomainName)))) // char max size for a single label { // Copy in hostname characters as lowercase if ((bResult = (0 != (p_rpcDomainName = new char[stLength + 1])))) @@ -1156,7 +1156,7 @@ bool clsLEAMDNSHost::_releaseDefaultInstanceName(void) clsLEAmDNS2_Host::_instanceName */ const char* clsLEAMDNSHost::_instanceName(const char* p_pcInstanceName, - bool p_bReturnZero /*= true*/) const + bool p_bReturnZero /*= true*/) const { return (p_pcInstanceName ? : (m_pcDefaultInstanceName ? : (m_pcHostName ? : (p_bReturnZero ? 0 : "-")))); } @@ -1283,8 +1283,8 @@ bool clsLEAMDNSHost::_releaseQueries(void) */ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findNextQueryByDomain(const clsLEAMDNSHost::clsRRDomain& p_Domain, - const clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType, - const clsQuery* p_pPrevQuery) + const clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType, + const clsQuery* p_pPrevQuery) { clsQuery* pMatchingQuery = 0; @@ -1292,17 +1292,21 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findNextQueryByDomain(const clsLEAMDN if (p_pPrevQuery) { if (m_Queries.end() != ((it = std::find(m_Queries.begin(), m_Queries.end(), p_pPrevQuery)))) - { // Found previous object + { + // Found previous object it++; } - DEBUG_EX_ERR(else DEBUG_OUTPUT.printf_P(PSTR("%s _findNextQueryByDomain: FAILED to find 'previous' object!\n"), _DH());); // if not prev was found -> 'cancel' + DEBUG_EX_ERR(else + { + DEBUG_OUTPUT.printf_P(PSTR("%s _findNextQueryByDomain: FAILED to find 'previous' object!\n"), _DH()); + }); // if not prev was found -> 'cancel' } for (; it != m_Queries.end(); it++) { if (((clsQuery::enuQueryType::None == p_QueryType) || - ((*it)->m_QueryType == p_QueryType)) && - (p_Domain == (*it)->m_Domain)) + ((*it)->m_QueryType == p_QueryType)) && + (p_Domain == (*it)->m_Domain)) { pMatchingQuery = *it; break; @@ -1316,14 +1320,14 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findNextQueryByDomain(const clsLEAMDN */ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery(const char* p_pcService, - const char* p_pcProtocol) + const char* p_pcProtocol) { clsQuery* pMDNSQuery = 0; if ((p_pcService) && (*p_pcService) && - (p_pcProtocol) && (*p_pcProtocol) && - ((pMDNSQuery = _allocQuery(clsQuery::enuQueryType::Service))) && - (_buildDomainForService(p_pcService, p_pcProtocol, pMDNSQuery->m_Domain))) + (p_pcProtocol) && (*p_pcProtocol) && + ((pMDNSQuery = _allocQuery(clsQuery::enuQueryType::Service))) && + (_buildDomainForService(p_pcService, p_pcProtocol, pMDNSQuery->m_Domain))) { pMDNSQuery->m_bStaticQuery = false; @@ -1346,7 +1350,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery(const char* p_pcS clsLEAmDNS2_Host::_installDomainQuery */ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installDomainQuery(clsLEAMDNSHost::clsRRDomain& p_Domain, - clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType) + clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType) { clsQuery* pQuery = 0; @@ -1402,9 +1406,9 @@ bool clsLEAMDNSHost::_hasQueriesWaitingForAnswers(void) const clsLEAmDNS2_Host::_executeQueryCallback */ bool clsLEAMDNSHost::_executeQueryCallback(const clsQuery& p_Query, - const clsQuery::clsAnswer& p_Answer, - clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, - bool p_bSetContent) + const clsQuery::clsAnswer& p_Answer, + clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, + bool p_bSetContent) { if (p_Query.m_fnCallbackAnswer) { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 5a63d1f59e..ff590473c7 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -465,8 +465,8 @@ class clsLEAMDNSHost Callback function for host domain probe results */ using fnProbeResultCallback = std::function<void(clsLEAMDNSHost& p_rHost, - const char* p_pcDomainName, - bool p_bProbeResult)>; + const char* p_pcDomainName, + bool p_bProbeResult)>; protected: /** @@ -498,8 +498,8 @@ class clsLEAMDNSHost fnProbeResultCallback */ using fnProbeResultCallback = std::function<void(clsService& p_rMDNSService, - const char* p_pcInstanceName, - bool p_bProbeResult)>; + const char* p_pcInstanceName, + bool p_bProbeResult)>; protected: friend clsLEAMDNSHost; @@ -1188,16 +1188,16 @@ class clsLEAMDNSHost QueryCallbackAnswerFn */ using QueryCallbackAnswerFn = std::function<void(const clsQuery& p_Query, - const clsAnswer& p_Answer, - clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item - bool p_bSetContent)>; // true: Answer component set, false: component deleted + const clsAnswer& p_Answer, + clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)>; // true: Answer component set, false: component deleted /** QueryCallbackAccessorFn */ using QueryCallbackAccessorFn = std::function<void(const clsQuery& p_Query, - const clsAnswerAccessor& p_AnswerAccessor, - clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item - bool p_bSetContent)>; // true: Answer component set, false: component deleted + const clsAnswerAccessor& p_AnswerAccessor, + clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)>; // true: Answer component set, false: component deleted protected: friend clsLEAMDNSHost; @@ -1292,7 +1292,7 @@ class clsLEAMDNSHost const char* p_pcType, const char* p_pcProtocol, uint16_t p_u16Port = (uint16_t)(-1)); - const clsService::list& services(void) const; + const clsService::list& services(void) const; // QUERIES @@ -1303,10 +1303,10 @@ class clsLEAMDNSHost // - answerIP (or IP) // - answerPort (or port) clsQuery::clsAnswerAccessor::vector queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout); + const char* p_pcProtocol, + const uint16_t p_u16Timeout); clsQuery::clsAnswerAccessor::vector queryHost(const char* p_pcHostName, - const uint16_t p_u16Timeout); + const uint16_t p_u16Timeout); bool removeQuery(void); bool hasQuery(void); clsQuery* getQuery(void); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index 11fece09c1..efc9d1879e 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -133,8 +133,8 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader // Define host replies, BUT only answer queries after probing is done u32HostOrServiceReplies = sendParameter.m_u32HostReplyMask |= ((probeStatus()) - ? _replyMaskForHost(questionRR.m_Header, 0) - : 0); + ? _replyMaskForHost(questionRR.m_Header, 0) + : 0); DEBUG_EX_INFO(if (u32HostOrServiceReplies) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Host reply needed %s\n"), _DH(), _replyFlags2String(u32HostOrServiceReplies));); // Check tiebreak need for host domain @@ -142,7 +142,7 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader { bool bFullNameMatch = false; if ((_replyMaskForHost(questionRR.m_Header, &bFullNameMatch)) && - (bFullNameMatch)) + (bFullNameMatch)) { // We're in 'probing' state and someone is asking for our host domain: this might be // a race-condition: Two hosts with the same domain names try simutanously to probe their domains @@ -172,7 +172,7 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader { bool bFullNameMatch = false; if ((_replyMaskForService(questionRR.m_Header, *pService, &bFullNameMatch)) && - (bFullNameMatch)) + (bFullNameMatch)) { // We're in 'probing' state and someone is asking for this service domain: this might be // a race-condition: Two services with the same domain names try simutanously to probe their domains @@ -189,8 +189,8 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader // Handle unicast and legacy specialities // If only one question asks for unicast reply, the whole reply packet is send unicast if (((DNS_MQUERY_PORT != m_pUDPContext->getRemotePort()) || // Unicast (maybe legacy) query OR - (questionRR.m_bUnicast)) && // Expressivly unicast query - (!sendParameter.m_bUnicast)) + (questionRR.m_bUnicast)) && // Expressivly unicast query + (!sendParameter.m_bUnicast)) { sendParameter.m_bUnicast = true; //sendParameter.m_bCacheFlush = false; @@ -198,9 +198,9 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader //Serial.printf_P(PSTR("%s _parseQuery: Ignored Unicast response asked for by %s!\n"), _DH(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str()); if ((DNS_MQUERY_PORT != m_pUDPContext->getRemotePort()) && // Unicast (maybe legacy) query AND - (1 == p_MsgHeader.m_u16QDCount) && // Only one question AND - ((sendParameter.m_u32HostReplyMask) || // Host replies OR - (u32HostOrServiceReplies))) // Host or service replies available + (1 == p_MsgHeader.m_u16QDCount) && // Only one question AND + ((sendParameter.m_u32HostReplyMask) || // Host replies OR + (u32HostOrServiceReplies))) // Host or service replies available { // Local host check // We're a match for this legacy query, BUT @@ -209,20 +209,20 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader ip_info IPInfo_Local; #endif if ((m_pNetIf) && - (m_pUDPContext) && + (m_pUDPContext) && #ifdef MDNS_IPV4_SUPPORT - (m_pUDPContext->getRemoteAddress().isV4()) && - ((wifi_get_ip_info(netif_get_index(m_pNetIf), &IPInfo_Local))) && - (ip4_addr_netcmp(ip_2_ip4((const ip_addr_t*)m_pUDPContext->getRemoteAddress()), &IPInfo_Local.ip, &IPInfo_Local.netmask)) + (m_pUDPContext->getRemoteAddress().isV4()) && + ((wifi_get_ip_info(netif_get_index(m_pNetIf), &IPInfo_Local))) && + (ip4_addr_netcmp(ip_2_ip4((const ip_addr_t*)m_pUDPContext->getRemoteAddress()), &IPInfo_Local.ip, &IPInfo_Local.netmask)) #else - (true) + (true) #endif - && + && #ifdef MDNS_IPV6_SUPPORT - (m_pUDPContext->getRemoteAddress().isV6()) && - (ip6_addr_islinklocal(ip_2_ip6((const ip_addr_t*)m_pUDPContext->getRemoteAddress()))) + (m_pUDPContext->getRemoteAddress().isV6()) && + (ip6_addr_islinklocal(ip_2_ip6((const ip_addr_t*)m_pUDPContext->getRemoteAddress()))) #else - (true) + (true) #endif ) { @@ -275,8 +275,8 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader // Handle known answers uint32_t u32Answers = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); if (((u32HostOrServiceReplies) || - (bHostOrServiceTiebreakNeeded)) && - (u32Answers)) + (bHostOrServiceTiebreakNeeded)) && + (u32Answers)) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Reading known answers(%u):\n"), _DH(), u32Answers);); @@ -284,10 +284,10 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader { clsRRAnswer* pKnownRRAnswer = 0; if (((bResult = _readRRAnswer(pKnownRRAnswer))) && - (pKnownRRAnswer)) + (pKnownRRAnswer)) { if ((DNS_RRTYPE_ANY != pKnownRRAnswer->m_Header.m_Attributes.m_u16Type) && // No ANY type answer - (DNS_RRCLASS_ANY != (pKnownRRAnswer->m_Header.m_Attributes.m_u16Class & (~0x8000)))) // No ANY class answer + (DNS_RRCLASS_ANY != (pKnownRRAnswer->m_Header.m_Attributes.m_u16Class & (~0x8000)))) // No ANY class answer { /* - RFC6762 7.1 Suppression only for 'Shared Records' - // Find match between planned answer (sendParameter.m_u8HostReplyMask) and this 'known answer' @@ -357,7 +357,7 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader { clsRRDomain hostDomain; if ((_buildDomainForHost(m_pcHostName, hostDomain)) && - (pKnownRRAnswer->m_Header.m_Domain == hostDomain)) + (pKnownRRAnswer->m_Header.m_Domain == hostDomain)) { // Host domain match #ifdef MDNS_IPV4_SUPPORT @@ -429,21 +429,21 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader uint32_t u32ServiceMatchMask = (pService->m_u32ReplyMask & _replyMaskForService(pKnownRRAnswer->m_Header, *pService)); if ((u32ServiceMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND - ((clsConsts::u32ServiceTTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new service TTL (4500s) + ((clsConsts::u32ServiceTTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new service TTL (4500s) { if (enuAnswerType::PTR == pKnownRRAnswer->answerType()) { clsRRDomain serviceDomain; if ((u32ServiceMatchMask & static_cast<uint32_t>(enuContentFlag::PTR_TYPE)) && - (_buildDomainForService(*pService, false, serviceDomain)) && - (serviceDomain == ((clsRRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) + (_buildDomainForService(*pService, false, serviceDomain)) && + (serviceDomain == ((clsRRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service type PTR already known (TTL:%u)... skipping!\n"), _DH(pService), pKnownRRAnswer->m_u32TTL);); pService->m_u32ReplyMask &= ~static_cast<uint32_t>(enuContentFlag::PTR_TYPE); } if ((u32ServiceMatchMask & static_cast<uint32_t>(enuContentFlag::PTR_NAME)) && - (_buildDomainForService(*pService, true, serviceDomain)) && - (serviceDomain == ((clsRRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) + (_buildDomainForService(*pService, true, serviceDomain)) && + (serviceDomain == ((clsRRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Service name PTR already known (TTL:%u)... skipping!\n"), _DH(pService), pKnownRRAnswer->m_u32TTL);); pService->m_u32ReplyMask &= ~static_cast<uint32_t>(enuContentFlag::PTR_NAME); @@ -488,14 +488,14 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader { clsRRDomain serviceDomain; if ((_buildDomainForService(*pService, true, serviceDomain)) && - (pKnownRRAnswer->m_Header.m_Domain == serviceDomain)) + (pKnownRRAnswer->m_Header.m_Domain == serviceDomain)) { // Service domain match if (enuAnswerType::SRV == pKnownRRAnswer->answerType()) { clsRRDomain hostDomain; if ((_buildDomainForHost(m_pcHostName, hostDomain)) && - (hostDomain == ((clsRRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain)) // Host domain match + (hostDomain == ((clsRRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain)) // Host domain match { // We've received an old message from ourselfs (same SRV) DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (SRV) won (was an old message)!\n"), _DH(pService));); @@ -626,7 +626,7 @@ bool clsLEAMDNSHost::_parseResponse(const clsLEAMDNSHost::clsMsgHeader& p_MsgHea // A response should be the result of a query or a probe if ((_hasQueriesWaitingForAnswers()) || // Waiting for query answers OR - (_hasProbesWaitingForAnswers())) // Probe responses + (_hasProbesWaitingForAnswers())) // Probe responses { DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: Received a response\n"), _DH()); @@ -651,7 +651,7 @@ bool clsLEAMDNSHost::_parseResponse(const clsLEAMDNSHost::clsMsgHeader& p_MsgHea { clsRRAnswer* pRRAnswer = 0; if (((bResult = _readRRAnswer(pRRAnswer))) && - (pRRAnswer)) + (pRRAnswer)) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: ADDING answer!\n"));); pRRAnswer->m_pNext = pCollectedRRAnswers; @@ -753,36 +753,41 @@ bool clsLEAMDNSHost::_processAnswers(const clsLEAMDNSHost::clsRRAnswer* p_pAnswe const clsRRAnswer* pRRAnswer = p_pAnswers; while ((pRRAnswer) && - (bResult)) + (bResult)) { // 1. level answer (PTR) if (enuAnswerType::PTR == pRRAnswer->answerType()) - { // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local + { + // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local bResult = _processPTRAnswer((clsRRAnswerPTR*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new SRV or TXT answers to be linked to queries } // 2. level answers // SRV -> host domain and port else if (enuAnswerType::SRV == pRRAnswer->answerType()) - { // eg. MyESP._http._tcp.local SRV xxxx xx yy zz 5000 esp8266.local + { + // eg. MyESP._http._tcp.local SRV xxxx xx yy zz 5000 esp8266.local bResult = _processSRVAnswer((clsRRAnswerSRV*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new A/AAAA answers to be linked to queries } // TXT -> Txts else if (enuAnswerType::TXT == pRRAnswer->answerType()) - { // eg. MyESP_http._tcp.local TXT xxxx xx c#=1 + { + // eg. MyESP_http._tcp.local TXT xxxx xx c#=1 bResult = _processTXTAnswer((clsRRAnswerTXT*)pRRAnswer); } // 3. level answers #ifdef MDNS_IPV4_SUPPORT // A -> IPv4Address else if (enuAnswerType::A == pRRAnswer->answerType()) - { // eg. esp8266.local A xxxx xx 192.168.2.120 + { + // eg. esp8266.local A xxxx xx 192.168.2.120 bResult = _processAAnswer((clsRRAnswerA*)pRRAnswer); } #endif #ifdef MDNS_IPV6_SUPPORT // AAAA -> IPv6Address else if (enuAnswerType::AAAA == pRRAnswer->answerType()) - { // eg. esp8266.local AAAA xxxx xx 09cf::0c + { + // eg. esp8266.local AAAA xxxx xx 09cf::0c bResult = _processAAAAAnswer((clsRRAnswerAAAA*)pRRAnswer); } #endif @@ -790,24 +795,24 @@ bool clsLEAMDNSHost::_processAnswers(const clsLEAMDNSHost::clsRRAnswer* p_pAnswe // Finally check for probing conflicts // Host domain if ((clsProbeInformation_Base::enuProbingStatus::InProgress == m_ProbeInformation.m_ProbingStatus) && - ((enuAnswerType::A == pRRAnswer->answerType()) || - (enuAnswerType::AAAA == pRRAnswer->answerType()))) + ((enuAnswerType::A == pRRAnswer->answerType()) || + (enuAnswerType::AAAA == pRRAnswer->answerType()))) { clsRRDomain hostDomain; if ((_buildDomainForHost(m_pcHostName, hostDomain)) && - (pRRAnswer->m_Header.m_Domain == hostDomain)) + (pRRAnswer->m_Header.m_Domain == hostDomain)) { bool bPossibleEcho = false; #ifdef MDNS_IPV4_SUPPORT if ((enuAnswerType::A == pRRAnswer->answerType()) && - (((clsRRAnswerA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V4))) + (((clsRRAnswerA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V4))) { bPossibleEcho = true; } #endif #ifdef MDNS_IPV6_SUPPORT if ((enuAnswerType::AAAA == pRRAnswer->answerType()) && - (((clsRRAnswerAAAA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V6))) + (((clsRRAnswerAAAA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V6))) { bPossibleEcho = true; } @@ -828,12 +833,12 @@ bool clsLEAMDNSHost::_processAnswers(const clsLEAMDNSHost::clsRRAnswer* p_pAnswe for (clsService* pService : m_Services) { if ((clsProbeInformation_Base::enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) && - ((enuAnswerType::TXT == pRRAnswer->answerType()) || - (enuAnswerType::SRV == pRRAnswer->answerType()))) + ((enuAnswerType::TXT == pRRAnswer->answerType()) || + (enuAnswerType::SRV == pRRAnswer->answerType()))) { clsRRDomain serviceDomain; if ((_buildDomainForService(*pService, true, serviceDomain)) && - (pRRAnswer->m_Header.m_Domain == serviceDomain)) + (pRRAnswer->m_Header.m_Domain == serviceDomain)) { // TODO: Echo management needed? DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _processAnswers: Probing CONFLICT found with '%s'\n"), _DH(), _service2String(pService));); @@ -870,12 +875,15 @@ bool clsLEAMDNSHost::_processPTRAnswer(const clsLEAMDNSHost::clsRRAnswerPTR* p_p while (pQuery) { if (pQuery->m_bAwaitingAnswers) - { // Find answer for service domain (eg. MyESP._http._tcp.local) + { + // Find answer for service domain (eg. MyESP._http._tcp.local) clsQuery::clsAnswer* pSQAnswer = pQuery->findAnswerForServiceDomain(p_pPTRAnswer->m_PTRDomain); if (pSQAnswer) - { // existing answer + { + // existing answer if (p_pPTRAnswer->m_u32TTL) - { // Received update message + { + // Received update message pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); // Update TTL tag DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processPTRAnswer: Updated TTL(%lu) for "), _DH(), p_pPTRAnswer->m_u32TTL); @@ -884,7 +892,8 @@ bool clsLEAMDNSHost::_processPTRAnswer(const clsLEAMDNSHost::clsRRAnswerPTR* p_p ); } else - { // received goodbye-message + { + // received goodbye-message pSQAnswer->m_TTLServiceDomain.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processPTRAnswer: 'Goodbye' received for "), _DH()); @@ -942,7 +951,8 @@ bool clsLEAMDNSHost::_processSRVAnswer(const clsLEAMDNSHost::clsRRAnswerSRV* p_p { // Answer for this service domain (eg. MyESP._http._tcp.local) available if (p_pSRVAnswer->m_u32TTL) - { // First or update message (TTL != 0) + { + // First or update message (TTL != 0) pSQAnswer->m_TTLHostDomainAndPort.set(p_pSRVAnswer->m_u32TTL); // Update TTL tag DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processSRVAnswer: Updated TTL(%lu) for "), _DH(), p_pSRVAnswer->m_u32TTL); @@ -951,7 +961,7 @@ bool clsLEAMDNSHost::_processSRVAnswer(const clsLEAMDNSHost::clsRRAnswerSRV* p_p ); // Host domain & Port if ((pSQAnswer->m_HostDomain != p_pSRVAnswer->m_SRVDomain) || - (pSQAnswer->m_u16Port != p_pSRVAnswer->m_u16Port)) + (pSQAnswer->m_u16Port != p_pSRVAnswer->m_u16Port)) { pSQAnswer->m_HostDomain = p_pSRVAnswer->m_SRVDomain; @@ -972,7 +982,8 @@ bool clsLEAMDNSHost::_processSRVAnswer(const clsLEAMDNSHost::clsRRAnswerSRV* p_p } } else - { // Goodby message + { + // Goodby message pSQAnswer->m_TTLHostDomainAndPort.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processSRVAnswer: 'Goodbye' received for "), _DH()); @@ -1006,9 +1017,11 @@ bool clsLEAMDNSHost::_processTXTAnswer(const clsLEAMDNSHost::clsRRAnswerTXT* p_p { clsQuery::clsAnswer* pSQAnswer = pQuery->findAnswerForServiceDomain(p_pTXTAnswer->m_Header.m_Domain); if (pSQAnswer) - { // Answer for this service domain (eg. MyESP._http._tcp.local) available + { + // Answer for this service domain (eg. MyESP._http._tcp.local) available if (p_pTXTAnswer->m_u32TTL) - { // First or update message + { + // First or update message pSQAnswer->m_TTLTxts.set(p_pTXTAnswer->m_u32TTL); // Update TTL tag DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processTXTAnswer: Updated TTL(%lu) for "), _DH(), p_pTXTAnswer->m_u32TTL); @@ -1031,7 +1044,8 @@ bool clsLEAMDNSHost::_processTXTAnswer(const clsLEAMDNSHost::clsRRAnswerTXT* p_p } } else - { // Goodby message + { + // Goodby message pSQAnswer->m_TTLTxts.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processTXTAnswer: 'Goodbye' received for "), _DH()); @@ -1063,15 +1077,17 @@ bool clsLEAMDNSHost::_processAAnswer(const clsLEAMDNSHost::clsRRAnswerA* p_pAAns clsQuery* pQuery = *it; if (pQuery->m_bAwaitingAnswers) - { // Look for answers to host queries + { + // Look for answers to host queries if ((p_pAAnswer->m_u32TTL) && // NOT just a goodbye message - (clsQuery::enuQueryType::Host == pQuery->m_QueryType) && // AND a host query - (pQuery->m_Domain == p_pAAnswer->m_Header.m_Domain)) // AND a matching host domain + (clsQuery::enuQueryType::Host == pQuery->m_QueryType) && // AND a host query + (pQuery->m_Domain == p_pAAnswer->m_Header.m_Domain)) // AND a matching host domain { clsQuery::clsAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAnswer->m_Header.m_Domain); if ((!pSQAnswer) && - ((pSQAnswer = new clsQuery::clsAnswer))) - { // Add not yet included answer + ((pSQAnswer = new clsQuery::clsAnswer))) + { + // Add not yet included answer pSQAnswer->m_HostDomain = p_pAAnswer->m_Header.m_Domain; //pSQAnswer->releaseHostDomain(); @@ -1090,12 +1106,15 @@ bool clsLEAMDNSHost::_processAAnswer(const clsLEAMDNSHost::clsRRAnswerA* p_pAAns // Look for answers to service queries clsQuery::clsAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAnswer->m_Header.m_Domain); if (pSQAnswer) - { // Answer for this host domain (eg. esp8266.local) available + { + // Answer for this host domain (eg. esp8266.local) available clsQuery::clsAnswer::clsIPAddressWithTTL* pIPAddress = pSQAnswer->findIPv4Address(p_pAAnswer->m_IPAddress); if (pIPAddress) - { // Already known IPv4 address + { + // Already known IPv4 address if (p_pAAnswer->m_u32TTL) - { // Valid TTL -> Update answers TTL + { + // Valid TTL -> Update answers TTL pIPAddress->m_TTL.set(p_pAAnswer->m_u32TTL); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: Updated TTL(%lu) for "), _DH(), p_pAAnswer->m_u32TTL); @@ -1104,7 +1123,8 @@ bool clsLEAMDNSHost::_processAAnswer(const clsLEAMDNSHost::clsRRAnswerA* p_pAAns ); } else - { // 'Goodbye' message for known IPv4 address + { + // 'Goodbye' message for known IPv4 address pIPAddress->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: 'Goodbye' received for "), _DH()); @@ -1114,12 +1134,14 @@ bool clsLEAMDNSHost::_processAAnswer(const clsLEAMDNSHost::clsRRAnswerA* p_pAAns } } else - { // Until now unknown IPv4 address -> Add (if the message isn't just a 'Goodbye' note) + { + // Until now unknown IPv4 address -> Add (if the message isn't just a 'Goodbye' note) if (p_pAAnswer->m_u32TTL) - { // NOT just a 'Goodbye' message + { + // NOT just a 'Goodbye' message pIPAddress = new clsQuery::clsAnswer::clsIPAddressWithTTL(p_pAAnswer->m_IPAddress, p_pAAnswer->m_u32TTL); if ((pIPAddress) && - (pSQAnswer->addIPv4Address(pIPAddress))) + (pSQAnswer->addIPv4Address(pIPAddress))) { DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: Added IPv4 address to "), _DH()); @@ -1161,15 +1183,17 @@ bool clsLEAMDNSHost::_processAAAAAnswer(const clsLEAMDNSHost::clsRRAnswerAAAA* p clsQuery* pQuery = *it; if (pQuery->m_bAwaitingAnswers) - { // Look for answers to host queries + { + // Look for answers to host queries if ((p_pAAAAAnswer->m_u32TTL) && // NOT just a goodbye message - (clsQuery::enuQueryType::Host == pQuery->m_QueryType) && // AND a host query - (pQuery->m_Domain == p_pAAAAAnswer->m_Header.m_Domain)) // AND a matching host domain + (clsQuery::enuQueryType::Host == pQuery->m_QueryType) && // AND a host query + (pQuery->m_Domain == p_pAAAAAnswer->m_Header.m_Domain)) // AND a matching host domain { clsQuery::clsAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAAAAnswer->m_Header.m_Domain); if ((!pSQAnswer) && - ((pSQAnswer = new clsQuery::clsAnswer))) - { // Add not yet included answer + ((pSQAnswer = new clsQuery::clsAnswer))) + { + // Add not yet included answer pSQAnswer->m_HostDomain = p_pAAAAAnswer->m_Header.m_Domain; //pSQAnswer->releaseHostDomain(); @@ -1191,9 +1215,11 @@ bool clsLEAMDNSHost::_processAAAAAnswer(const clsLEAMDNSHost::clsRRAnswerAAAA* p { clsQuery::clsAnswer::clsIPAddressWithTTL* pIPAddress = pSQAnswer->findIPv6Address(p_pAAAAAnswer->m_IPAddress); if (pIPAddress) - { // Already known IPv6 address + { + // Already known IPv6 address if (p_pAAAAAnswer->m_u32TTL) - { // Valid TTL -> Update answers TTL + { + // Valid TTL -> Update answers TTL pIPAddress->m_TTL.set(p_pAAAAAnswer->m_u32TTL); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processAAAAAnswer: Updated TTL(%lu) for "), _DH(), p_pAAAAAnswer->m_u32TTL); @@ -1202,7 +1228,8 @@ bool clsLEAMDNSHost::_processAAAAAnswer(const clsLEAMDNSHost::clsRRAnswerAAAA* p ); } else - { // 'Goodbye' message for known IPv6 address + { + // 'Goodbye' message for known IPv6 address pIPAddress->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processAAAAAnswer: 'Goodbye' received for "), _DH()); @@ -1212,13 +1239,14 @@ bool clsLEAMDNSHost::_processAAAAAnswer(const clsLEAMDNSHost::clsRRAnswerAAAA* p } } else - { // Until now unknown IPv6 address -> Add (if the message isn't just a 'Goodbye' note) + { + // Until now unknown IPv6 address -> Add (if the message isn't just a 'Goodbye' note) if (p_pAAAAAnswer->m_u32TTL) { // NOT just a 'Goodbye' message pIPAddress = new clsQuery::clsAnswer::clsIPAddressWithTTL(p_pAAAAAnswer->m_IPAddress, p_pAAAAAnswer->m_u32TTL); if ((pIPAddress) && - (pSQAnswer->addIPv6Address(pIPAddress))) + (pSQAnswer->addIPv6Address(pIPAddress))) { DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _processAAAAAnswer: Added IPv6 address to "), _DH()); @@ -1270,19 +1298,19 @@ bool clsLEAMDNSHost::_updateProbeStatus(void) // // Probe host domain if ((clsProbeInformation_Base::enuProbingStatus::ReadyToStart == m_ProbeInformation.m_ProbingStatus) && // Ready to get started AND - (( + (( #ifdef MDNS_IPV4_SUPPORT - _getResponderIPAddress(enuIPProtocolType::V4).isSet() // AND has IPv4 address + _getResponderIPAddress(enuIPProtocolType::V4).isSet() // AND has IPv4 address #else - true + true #endif - ) || ( + ) || ( #ifdef MDNS_IPV6_SUPPORT - _getResponderIPAddress(enuIPProtocolType::V6).isSet() // OR has IPv6 address + _getResponderIPAddress(enuIPProtocolType::V6).isSet() // OR has IPv6 address #else - true + true #endif - ))) // Has IP address + ))) // Has IP address { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Starting host probing...\n"), _DH());); @@ -1476,7 +1504,7 @@ bool clsLEAMDNSHost::_sendHostProbe(void) clsRRQuestion* pNewRRQuestion = new clsRRQuestion; if (((bResult = (0 != pNewRRQuestion))) && - ((bResult = _buildDomainForHost(m_pcHostName, pNewRRQuestion->m_Header.m_Domain)))) + ((bResult = _buildDomainForHost(m_pcHostName, pNewRRQuestion->m_Header.m_Domain)))) { //sendParameter.m_pQuestions->m_bUnicast = true; pNewRRQuestion->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; @@ -1531,7 +1559,7 @@ bool clsLEAMDNSHost::_sendServiceProbe(clsService& p_rService) clsRRQuestion* pNewRRQuestion = new clsRRQuestion; if (((bResult = (0 != pNewRRQuestion))) && - ((bResult = _buildDomainForService(p_rService, true, pNewRRQuestion->m_Header.m_Domain)))) + ((bResult = _buildDomainForService(p_rService, true, pNewRRQuestion->m_Header.m_Domain)))) { pNewRRQuestion->m_bUnicast = true; pNewRRQuestion->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; @@ -1612,7 +1640,7 @@ bool clsLEAMDNSHost::_callHostProbeResultCallback(bool p_bResult) */ bool clsLEAMDNSHost::_callServiceProbeResultCallback(clsLEAMDNSHost::clsService& p_rService, - bool p_bResult) + bool p_bResult) { if (p_rService.m_ProbeInformation.m_fnProbeResultCallback) { @@ -1763,7 +1791,7 @@ bool clsLEAMDNSHost::_checkQueryCache(void) // // Resend dynamic queries, if not already done often enough if ((!pQuery->m_bStaticQuery) && - (pQuery->m_ResendTimeout.expired())) + (pQuery->m_ResendTimeout.expired())) { if ((bResult = _sendQuery(*pQuery))) { @@ -1794,7 +1822,7 @@ bool clsLEAMDNSHost::_checkQueryCache(void) // 1. level answer if ((bResult) && - (pQAnswer->m_TTLServiceDomain.flagged())) + (pQAnswer->m_TTLServiceDomain.flagged())) { if (!pQAnswer->m_TTLServiceDomain.finalTimeoutLevel()) { @@ -1826,7 +1854,7 @@ bool clsLEAMDNSHost::_checkQueryCache(void) // 2. level answers // HostDomain & Port (from SRV) if ((bResult) && - (pQAnswer->m_TTLHostDomainAndPort.flagged())) + (pQAnswer->m_TTLHostDomainAndPort.flagged())) { if (!pQAnswer->m_TTLHostDomainAndPort.finalTimeoutLevel()) { @@ -1872,7 +1900,7 @@ bool clsLEAMDNSHost::_checkQueryCache(void) // Txts (from TXT) if ((bResult) && - (pQAnswer->m_TTLTxts.flagged())) + (pQAnswer->m_TTLTxts.flagged())) { if (!pQAnswer->m_TTLTxts.finalTimeoutLevel()) { @@ -1919,7 +1947,7 @@ bool clsLEAMDNSHost::_checkQueryCache(void) { // Needs update if ((bAUpdateQuerySent) || - ((bResult = _sendQuery(pQAnswer->m_HostDomain, DNS_RRTYPE_A)))) + ((bResult = _sendQuery(pQAnswer->m_HostDomain, DNS_RRTYPE_A)))) { pIPv4Address->m_TTL.restart(); bAUpdateQuerySent = true; @@ -1972,7 +2000,7 @@ bool clsLEAMDNSHost::_checkQueryCache(void) { // Needs update if ((bAAAAUpdateQuerySent) || - ((bResult = _sendQuery(pQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) + ((bResult = _sendQuery(pQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) { pIPv6Address->m_TTL.restart(); bAAAAUpdateQuerySent = true; @@ -2036,7 +2064,7 @@ bool clsLEAMDNSHost::_checkQueryCache(void) In addition, a full name match (question domain == host domain) is marked. */ uint32_t clsLEAMDNSHost::_replyMaskForHost(const clsLEAMDNSHost::clsRRHeader& p_RRHeader, - bool* p_pbFullNameMatch /*= 0*/) const + bool* p_pbFullNameMatch /*= 0*/) const { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _replyMaskForHost\n"));); @@ -2044,18 +2072,18 @@ uint32_t clsLEAMDNSHost::_replyMaskForHost(const clsLEAMDNSHost::clsRRHeader& p_ (p_pbFullNameMatch ? *p_pbFullNameMatch = false : 0); if ((DNS_RRCLASS_IN == (p_RRHeader.m_Attributes.m_u16Class & (~0x8000))) || - (DNS_RRCLASS_ANY == (p_RRHeader.m_Attributes.m_u16Class & (~0x8000)))) + (DNS_RRCLASS_ANY == (p_RRHeader.m_Attributes.m_u16Class & (~0x8000)))) { if ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) { // PTR request #ifdef MDNS_IPV4_SUPPORT clsRRDomain reverseIPv4Domain; if ((_getResponderIPAddress(enuIPProtocolType::V4).isSet()) && - (_buildDomainForReverseIPv4(_getResponderIPAddress(enuIPProtocolType::V4), reverseIPv4Domain)) && - (p_RRHeader.m_Domain == reverseIPv4Domain)) + (_buildDomainForReverseIPv4(_getResponderIPAddress(enuIPProtocolType::V4), reverseIPv4Domain)) && + (p_RRHeader.m_Domain == reverseIPv4Domain)) { // Reverse domain match u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::PTR_IPv4); @@ -2064,8 +2092,8 @@ uint32_t clsLEAMDNSHost::_replyMaskForHost(const clsLEAMDNSHost::clsRRHeader& p_ #ifdef MDNS_IPV6_SUPPORT clsRRDomain reverseIPv6Domain; if ((_getResponderIPAddress(enuIPProtocolType::V6).isSet()) && - (_buildDomainForReverseIPv6(_getResponderIPAddress(enuIPProtocolType::V6), reverseIPv6Domain)) && - (p_RRHeader.m_Domain == reverseIPv6Domain)) + (_buildDomainForReverseIPv6(_getResponderIPAddress(enuIPProtocolType::V6), reverseIPv6Domain)) && + (p_RRHeader.m_Domain == reverseIPv6Domain)) { // Reverse domain match u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::PTR_IPv6); @@ -2075,13 +2103,13 @@ uint32_t clsLEAMDNSHost::_replyMaskForHost(const clsLEAMDNSHost::clsRRHeader& p_ clsRRDomain hostDomain; if ((_buildDomainForHost(m_pcHostName, hostDomain)) && - (p_RRHeader.m_Domain == hostDomain)) // Host domain match + (p_RRHeader.m_Domain == hostDomain)) // Host domain match { (p_pbFullNameMatch ? (*p_pbFullNameMatch = true) : (0)); #ifdef MDNS_IPV4_SUPPORT if ((DNS_RRTYPE_A == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) { // IPv4 address request u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::A); @@ -2089,7 +2117,7 @@ uint32_t clsLEAMDNSHost::_replyMaskForHost(const clsLEAMDNSHost::clsRRHeader& p_ #endif #ifdef MDNS_IPV6_SUPPORT if ((DNS_RRTYPE_AAAA == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) { // IPv6 address request u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::AAAA); @@ -2119,20 +2147,20 @@ uint32_t clsLEAMDNSHost::_replyMaskForHost(const clsLEAMDNSHost::clsRRHeader& p_ */ uint32_t clsLEAMDNSHost::_replyMaskForService(const clsLEAMDNSHost::clsRRHeader& p_RRHeader, - clsLEAMDNSHost::clsService& p_rService, - bool* p_pbFullNameMatch /*= 0*/) + clsLEAMDNSHost::clsService& p_rService, + bool* p_pbFullNameMatch /*= 0*/) { uint32_t u32ReplyMask = 0; (p_pbFullNameMatch ? *p_pbFullNameMatch = false : 0); if ((DNS_RRCLASS_IN == (p_RRHeader.m_Attributes.m_u16Class & (~0x8000))) || - (DNS_RRCLASS_ANY == (p_RRHeader.m_Attributes.m_u16Class & (~0x8000)))) + (DNS_RRCLASS_ANY == (p_RRHeader.m_Attributes.m_u16Class & (~0x8000)))) { clsRRDomain DNSSDDomain; if ((_buildDomainForDNSSD(DNSSDDomain)) && // _services._dns-sd._udp.local - (p_RRHeader.m_Domain == DNSSDDomain) && - ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type))) + (p_RRHeader.m_Domain == DNSSDDomain) && + ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type))) { // Common service info requested u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::PTR_TYPE); @@ -2140,27 +2168,27 @@ uint32_t clsLEAMDNSHost::_replyMaskForService(const clsLEAMDNSHost::clsRRHeader& clsRRDomain serviceDomain; if ((_buildDomainForService(p_rService, false, serviceDomain)) && // eg. _http._tcp.local - (p_RRHeader.m_Domain == serviceDomain) && - ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type))) + (p_RRHeader.m_Domain == serviceDomain) && + ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type))) { // Special service info requested u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::PTR_NAME); } if ((_buildDomainForService(p_rService, true, serviceDomain)) && // eg. MyESP._http._tcp.local - (p_RRHeader.m_Domain == serviceDomain)) + (p_RRHeader.m_Domain == serviceDomain)) { (p_pbFullNameMatch ? (*p_pbFullNameMatch = true) : (0)); if ((DNS_RRTYPE_SRV == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) { // Instance info SRV requested u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::SRV); } if ((DNS_RRTYPE_TXT == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) { // Instance info TXT requested u32ReplyMask |= static_cast<uint32_t>(enuContentFlag::TXT); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp index 434f61a0ea..b449d1cd08 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp @@ -197,7 +197,7 @@ const char* clsLEAMDNSHost::_RRType2Name(uint16_t p_u16RRType) const */ const char* clsLEAMDNSHost::_RRClass2String(uint16_t p_u16RRClass, - bool p_bIsQuery) const + bool p_bIsQuery) const { static char acClassString[16]; *acClassString = 0; @@ -267,7 +267,7 @@ const char* clsLEAMDNSHost::_replyFlags2String(uint32_t p_u32ReplyFlags) const // Remove trailing spaces while ((*acFlagsString) && - (' ' == acFlagsString[strlen(acFlagsString) - 1])) + (' ' == acFlagsString[strlen(acFlagsString) - 1])) { acFlagsString[strlen(acFlagsString) - 1] = 0; } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index b4db3c0531..b2fe64072a 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -52,8 +52,8 @@ namespace experimental */ clsLEAMDNSHost::clsServiceTxt::clsServiceTxt(const char* p_pcKey /*= 0*/, - const char* p_pcValue /*= 0*/, - bool p_bTemp /*= false*/) + const char* p_pcValue /*= 0*/, + bool p_bTemp /*= false*/) : m_pcKey(0), m_pcValue(0), m_bTemp(p_bTemp) @@ -127,7 +127,7 @@ char* clsLEAMDNSHost::clsServiceTxt::allocKey(size_t p_stLength) */ bool clsLEAMDNSHost::clsServiceTxt::setKey(const char* p_pcKey, - size_t p_stLength) + size_t p_stLength) { bool bResult = false; @@ -186,7 +186,7 @@ char* clsLEAMDNSHost::clsServiceTxt::allocValue(size_t p_stLength) */ bool clsLEAMDNSHost::clsServiceTxt::setValue(const char* p_pcValue, - size_t p_stLength) + size_t p_stLength) { bool bResult = false; @@ -446,7 +446,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsServiceTxts::find(const char* for (clsServiceTxt* pTxt : m_Txts) { if ((p_pcKey) && - (0 == strcmp(pTxt->m_pcKey, p_pcKey))) + (0 == strcmp(pTxt->m_pcKey, p_pcKey))) { pResult = pTxt; break; @@ -466,7 +466,7 @@ const clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsServiceTxts::find(const for (const clsServiceTxt* pTxt : m_Txts) { if ((p_pcKey) && - (0 == strcmp(pTxt->m_pcKey, p_pcKey))) + (0 == strcmp(pTxt->m_pcKey, p_pcKey))) { pResult = pTxt; break; @@ -571,8 +571,8 @@ const char* clsLEAMDNSHost::clsServiceTxts::c_str(void) const { if ((!m_pcCache) && - (m_Txts.size()) && - ((((clsServiceTxts*)this)->m_pcCache = new char[c_strLength()]))) // TRANSPARENT caching + (m_Txts.size()) && + ((((clsServiceTxts*)this)->m_pcCache = new char[c_strLength()]))) // TRANSPARENT caching { ((clsServiceTxts*)this)->c_str(m_pcCache); } @@ -825,7 +825,7 @@ bool clsLEAMDNSHost::clsService::setInstanceName(const char* p_pcInstanceName) _releaseInstanceName(); size_t stLength = (p_pcInstanceName ? strlen(p_pcInstanceName) : 0); if ((stLength) && - (stLength <= clsConsts::stDomainLabelMaxLength)) + (stLength <= clsConsts::stDomainLabelMaxLength)) { if ((bResult = (0 != (m_pcInstanceName = new char[stLength + 1])))) { @@ -887,7 +887,7 @@ bool clsLEAMDNSHost::clsService::setType(const char* p_pcType) _releaseType(); size_t stLength = (p_pcType ? strlen(p_pcType) : 0); if ((stLength) && - (stLength <= clsConsts::stServiceTypeMaxLength)) + (stLength <= clsConsts::stServiceTypeMaxLength)) { if ((bResult = (0 != (m_pcType = new char[stLength + 1])))) { @@ -934,7 +934,7 @@ bool clsLEAMDNSHost::clsService::setProtocol(const char* p_pcProtocol) _releaseProtocol(); size_t stLength = (p_pcProtocol ? strlen(p_pcProtocol) : 0); if ((stLength) && - (stLength <= clsConsts::stServiceProtocolMaxLength)) + (stLength <= clsConsts::stServiceProtocolMaxLength)) { if ((bResult = (0 != (m_pcProtocol = new char[stLength + 1])))) { @@ -1030,7 +1030,7 @@ void clsLEAMDNSHost::clsService::_resetProbeStatus(void) */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, - const char* p_pcValue) + const char* p_pcValue) { return _addServiceTxt(p_pcKey, p_pcValue, false); } @@ -1040,7 +1040,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const c */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, - uint32_t p_u32Value) + uint32_t p_u32Value) { return _addServiceTxt(p_pcKey, p_u32Value, false); } @@ -1050,7 +1050,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const c */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, - uint16_t p_u16Value) + uint16_t p_u16Value) { return _addServiceTxt(p_pcKey, p_u16Value, false); } @@ -1060,7 +1060,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const c */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, - uint8_t p_u8Value) + uint8_t p_u8Value) { return _addServiceTxt(p_pcKey, p_u8Value, false); } @@ -1070,7 +1070,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const c */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, - int32_t p_i32Value) + int32_t p_i32Value) { return _addServiceTxt(p_pcKey, p_i32Value, false); } @@ -1080,7 +1080,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const c */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, - int16_t p_i16Value) + int16_t p_i16Value) { return _addServiceTxt(p_pcKey, p_i16Value, false); } @@ -1090,7 +1090,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const c */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const char* p_pcKey, - int8_t p_i8Value) + int8_t p_i8Value) { return _addServiceTxt(p_pcKey, p_i8Value, false); } @@ -1100,7 +1100,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addServiceTxt(const c */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, - const char* p_pcValue) + const char* p_pcValue) { return _addServiceTxt(p_pcKey, p_pcValue, true); } @@ -1110,7 +1110,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt( */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, - uint32_t p_u32Value) + uint32_t p_u32Value) { return _addServiceTxt(p_pcKey, p_u32Value, true); } @@ -1120,7 +1120,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt( */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, - uint16_t p_u16Value) + uint16_t p_u16Value) { return _addServiceTxt(p_pcKey, p_u16Value, true); } @@ -1130,7 +1130,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt( */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, - uint8_t p_u8Value) + uint8_t p_u8Value) { return _addServiceTxt(p_pcKey, p_u8Value, true); } @@ -1140,7 +1140,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt( */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, - int32_t p_i32Value) + int32_t p_i32Value) { return _addServiceTxt(p_pcKey, p_i32Value, true); } @@ -1150,7 +1150,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt( */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, - int16_t p_i16Value) + int16_t p_i16Value) { return _addServiceTxt(p_pcKey, p_i16Value, true); } @@ -1160,7 +1160,7 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt( */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::addDynamicServiceTxt(const char* p_pcKey, - int8_t p_i8Value) + int8_t p_i8Value) { return _addServiceTxt(p_pcKey, p_i8Value, true); } @@ -1180,13 +1180,13 @@ bool clsLEAMDNSHost::clsService::setDynamicServiceTxtCallback(fnDynamicServiceTx */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp) + const char* p_pcValue, + bool p_bTemp) { clsServiceTxt* pServiceTxt = 0; if ((p_pcKey) && - (*p_pcKey)) + (*p_pcKey)) { if ((pServiceTxt = m_Txts.find(p_pcKey))) { @@ -1220,8 +1220,8 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const (p_pcValue ? strlen(p_pcValue) : 0))) { if (!(((pServiceTxt = new clsServiceTxt)) && - (pServiceTxt->set(p_pcKey, p_pcValue, p_bTemp)) && - (m_Txts.add(pServiceTxt)))) + (pServiceTxt->set(p_pcKey, p_pcValue, p_bTemp)) && + (m_Txts.add(pServiceTxt)))) { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[LEAmDNS2_Host] clsService::_addServiceTxt: FAILED to add TXT item '%s'!\n"), p_pcKey)); if (pServiceTxt) @@ -1247,8 +1247,8 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, - uint32_t p_u32Value, - bool p_bTemp) + uint32_t p_u32Value, + bool p_bTemp) { char acValueBuffer[16]; // 32-bit max 10 digits *acValueBuffer = 0; @@ -1262,8 +1262,8 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, - uint16_t p_u16Value, - bool p_bTemp) + uint16_t p_u16Value, + bool p_bTemp) { char acValueBuffer[8]; // 16-bit max 5 digits *acValueBuffer = 0; @@ -1277,8 +1277,8 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, - uint8_t p_u8Value, - bool p_bTemp) + uint8_t p_u8Value, + bool p_bTemp) { char acValueBuffer[8]; // 8-bit max 3 digits *acValueBuffer = 0; @@ -1292,8 +1292,8 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, - int32_t p_i32Value, - bool p_bTemp) + int32_t p_i32Value, + bool p_bTemp) { char acValueBuffer[16]; // 32-bit max 10 digits *acValueBuffer = 0; @@ -1307,8 +1307,8 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, - int16_t p_i16Value, - bool p_bTemp) + int16_t p_i16Value, + bool p_bTemp) { char acValueBuffer[8]; // 16-bit max 5 digits *acValueBuffer = 0; @@ -1322,8 +1322,8 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const */ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, - int8_t p_i8Value, - bool p_bTemp) + int8_t p_i8Value, + bool p_bTemp) { char acValueBuffer[8]; // 8-bit max 3 digits *acValueBuffer = 0; @@ -1345,17 +1345,17 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const */ clsLEAMDNSHost::clsMsgHeader::clsMsgHeader(uint16_t p_u16ID /*= 0*/, - bool p_bQR /*= false*/, - uint8_t p_u8Opcode /*= 0*/, - bool p_bAA /*= false*/, - bool p_bTC /*= false*/, - bool p_bRD /*= false*/, - bool p_bRA /*= false*/, - uint8_t p_u8RCode /*= 0*/, - uint16_t p_u16QDCount /*= 0*/, - uint16_t p_u16ANCount /*= 0*/, - uint16_t p_u16NSCount /*= 0*/, - uint16_t p_u16ARCount /*= 0*/) + bool p_bQR /*= false*/, + uint8_t p_u8Opcode /*= 0*/, + bool p_bAA /*= false*/, + bool p_bTC /*= false*/, + bool p_bRD /*= false*/, + bool p_bRA /*= false*/, + uint8_t p_u8RCode /*= 0*/, + uint16_t p_u16QDCount /*= 0*/, + uint16_t p_u16ANCount /*= 0*/, + uint16_t p_u16NSCount /*= 0*/, + uint16_t p_u16ARCount /*= 0*/) : m_u16ID(p_u16ID), m_1bQR(p_bQR), m_4bOpcode(p_u8Opcode), m_1bAA(p_bAA), m_1bTC(p_bTC), m_1bRD(p_bRD), m_1bRA(p_bRA), m_3bZ(0), m_4bRCode(p_u8RCode), @@ -1456,7 +1456,7 @@ bool clsLEAMDNSHost::clsRRDomain::clearNameCache(void) */ bool clsLEAMDNSHost::clsRRDomain::addLabel(const char* p_pcLabel, - bool p_bPrependUnderline /*= false*/) + bool p_bPrependUnderline /*= false*/) { bool bResult = false; @@ -1464,7 +1464,7 @@ bool clsLEAMDNSHost::clsRRDomain::addLabel(const char* p_pcLabel, ? (strlen(p_pcLabel) + (p_bPrependUnderline ? 1 : 0)) : 0); if ((clsConsts::stDomainLabelMaxLength >= stLength) && - (clsConsts::stDomainMaxLength >= (m_u16NameLength + (1 + stLength)))) + (clsConsts::stDomainMaxLength >= (m_u16NameLength + (1 + stLength)))) { // Length byte m_acName[m_u16NameLength] = (unsigned char)stLength; // Might be 0! @@ -1498,9 +1498,9 @@ bool clsLEAMDNSHost::clsRRDomain::compare(const clsRRDomain& p_Other) const const char* pT = m_acName; const char* pO = p_Other.m_acName; while ((pT) && - (pO) && - (*((unsigned char*)pT) == *((unsigned char*)pO)) && // Same length AND - (0 == strncasecmp((pT + 1), (pO + 1), *((unsigned char*)pT)))) // Same content + (pO) && + (*((unsigned char*)pT) == *((unsigned char*)pO)) && // Same length AND + (0 == strncasecmp((pT + 1), (pO + 1), *((unsigned char*)pT)))) // Same content { if (*((unsigned char*)pT)) // Not 0 { @@ -1593,8 +1593,8 @@ bool clsLEAMDNSHost::clsRRDomain::c_str(char* p_pcBuffer) const const char* clsLEAMDNSHost::clsRRDomain::c_str(void) const { if ((!m_pcDecodedName) && - (m_u16NameLength) && - ((((clsRRDomain*)this)->m_pcDecodedName = new char[c_strLength()]))) // TRANSPARENT caching + (m_u16NameLength) && + ((((clsRRDomain*)this)->m_pcDecodedName = new char[c_strLength()]))) // TRANSPARENT caching { ((clsRRDomain*)this)->c_str(m_pcDecodedName); } @@ -1614,7 +1614,7 @@ const char* clsLEAMDNSHost::clsRRDomain::c_str(void) const */ clsLEAMDNSHost::clsRRAttributes::clsRRAttributes(uint16_t p_u16Type /*= 0*/, - uint16_t p_u16Class /*= 1 DNS_RRCLASS_IN Internet*/) + uint16_t p_u16Class /*= 1 DNS_RRCLASS_IN Internet*/) : m_u16Type(p_u16Type), m_u16Class(p_u16Class) { @@ -1753,7 +1753,7 @@ bool clsLEAMDNSHost::clsNSECBitmap::setBit(uint16_t p_u16Bit) bool bResult = false; if ((p_u16Bit) && - (length() > (p_u16Bit / 8))) // bit between 0..47(2F) + (length() > (p_u16Bit / 8))) // bit between 0..47(2F) { uint8_t& ru8Byte = m_au8BitmapData[p_u16Bit / 8]; @@ -1775,7 +1775,7 @@ bool clsLEAMDNSHost::clsNSECBitmap::getBit(uint16_t p_u16Bit) const bool bResult = false; if ((p_u16Bit) && - (length() > (p_u16Bit / 8))) // bit between 0..47(2F) + (length() > (p_u16Bit / 8))) // bit between 0..47(2F) { uint8_t u8Byte = m_au8BitmapData[p_u16Bit / 8]; @@ -1800,8 +1800,8 @@ bool clsLEAMDNSHost::clsNSECBitmap::getBit(uint16_t p_u16Bit) const */ clsLEAMDNSHost::clsRRAnswer::clsRRAnswer(enuAnswerType p_AnswerType, - const clsLEAMDNSHost::clsRRHeader& p_Header, - uint32_t p_u32TTL) + const clsLEAMDNSHost::clsRRHeader& p_Header, + uint32_t p_u32TTL) : m_pNext(0), m_AnswerType(p_AnswerType), m_Header(p_Header), @@ -1855,7 +1855,7 @@ bool clsLEAMDNSHost::clsRRAnswer::clear(void) */ clsLEAMDNSHost::clsRRAnswerA::clsRRAnswerA(const clsLEAMDNSHost::clsRRHeader& p_Header, - uint32_t p_u32TTL) + uint32_t p_u32TTL) : clsRRAnswer(enuAnswerType::A, p_Header, p_u32TTL), m_IPAddress() { @@ -1895,7 +1895,7 @@ bool clsLEAMDNSHost::clsRRAnswerA::clear(void) */ clsLEAMDNSHost::clsRRAnswerPTR::clsRRAnswerPTR(const clsLEAMDNSHost::clsRRHeader& p_Header, - uint32_t p_u32TTL) + uint32_t p_u32TTL) : clsRRAnswer(enuAnswerType::PTR, p_Header, p_u32TTL) { } @@ -1933,7 +1933,7 @@ bool clsLEAMDNSHost::clsRRAnswerPTR::clear(void) */ clsLEAMDNSHost::clsRRAnswerTXT::clsRRAnswerTXT(const clsLEAMDNSHost::clsRRHeader& p_Header, - uint32_t p_u32TTL) + uint32_t p_u32TTL) : clsRRAnswer(enuAnswerType::TXT, p_Header, p_u32TTL) { } @@ -1972,7 +1972,7 @@ bool clsLEAMDNSHost::clsRRAnswerTXT::clear(void) */ clsLEAMDNSHost::clsRRAnswerAAAA::clsRRAnswerAAAA(const clsLEAMDNSHost::clsRRHeader& p_Header, - uint32_t p_u32TTL) + uint32_t p_u32TTL) : clsRRAnswer(enuAnswerType::AAAA, p_Header, p_u32TTL), m_IPAddress() { @@ -2012,7 +2012,7 @@ bool clsLEAMDNSHost::clsRRAnswerAAAA::clear(void) */ clsLEAMDNSHost::clsRRAnswerSRV::clsRRAnswerSRV(const clsLEAMDNSHost::clsRRHeader& p_Header, - uint32_t p_u32TTL) + uint32_t p_u32TTL) : clsRRAnswer(enuAnswerType::SRV, p_Header, p_u32TTL), m_u16Priority(0), m_u16Weight(0), @@ -2056,7 +2056,7 @@ bool clsLEAMDNSHost::clsRRAnswerSRV::clear(void) */ clsLEAMDNSHost::clsRRAnswerGeneric::clsRRAnswerGeneric(const clsRRHeader& p_Header, - uint32_t p_u32TTL) + uint32_t p_u32TTL) : clsRRAnswer(enuAnswerType::Generic, p_Header, p_u32TTL), m_u16RDLength(0), m_pu8RDData(0) @@ -2111,8 +2111,8 @@ bool clsLEAMDNSHost::clsRRAnswerGeneric::clear(void) */ clsLEAMDNSHost::clsSendParameter::clsDomainCacheItem::clsDomainCacheItem(const void* p_pHostNameOrService, - bool p_bAdditionalData, - uint32_t p_u16Offset) + bool p_bAdditionalData, + uint32_t p_u16Offset) : m_pHostNameOrService(p_pHostNameOrService), m_bAdditionalData(p_bAdditionalData), m_u16Offset(p_u16Offset) @@ -2227,15 +2227,15 @@ bool clsLEAMDNSHost::clsSendParameter::shiftOffset(uint16_t p_u16Shift) */ bool clsLEAMDNSHost::clsSendParameter::addDomainCacheItem(const void* p_pHostNameOrService, - bool p_bAdditionalData, - uint16_t p_u16Offset) + bool p_bAdditionalData, + uint16_t p_u16Offset) { bool bResult = false; clsDomainCacheItem* pNewItem = 0; if ((p_pHostNameOrService) && - (p_u16Offset) && - ((pNewItem = new clsDomainCacheItem(p_pHostNameOrService, p_bAdditionalData, p_u16Offset)))) + (p_u16Offset) && + ((pNewItem = new clsDomainCacheItem(p_pHostNameOrService, p_bAdditionalData, p_u16Offset)))) { m_DomainCacheItems.push_back(pNewItem); bResult = true; @@ -2248,14 +2248,14 @@ bool clsLEAMDNSHost::clsSendParameter::addDomainCacheItem(const void* p_pHostNam */ uint16_t clsLEAMDNSHost::clsSendParameter::findCachedDomainOffset(const void* p_pHostNameOrService, - bool p_bAdditionalData) const + bool p_bAdditionalData) const { const clsDomainCacheItem* pMatchingCacheItem = 0; for (const clsDomainCacheItem* pCacheItem : m_DomainCacheItems) { if ((pCacheItem->m_pHostNameOrService == p_pHostNameOrService) && - (pCacheItem->m_bAdditionalData == p_bAdditionalData)) // Found cache item + (pCacheItem->m_bAdditionalData == p_bAdditionalData)) // Found cache item { pMatchingCacheItem = pCacheItem; break; @@ -2356,7 +2356,7 @@ bool clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::restart(void) bool bResult = true; if ((static_cast<typeTimeoutLevel>(enuTimeoutLevel::Base) <= m_TimeoutLevel) && // >= 80% AND - (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final) > m_TimeoutLevel)) // < 100% + (static_cast<typeTimeoutLevel>(enuTimeoutLevel::Final) > m_TimeoutLevel)) // < 100% { m_TimeoutLevel += static_cast<typeTimeoutLevel>(enuTimeoutLevel::Interval); // increment by 5% m_TTLTimeout.reset(timeout()); @@ -2422,7 +2422,7 @@ unsigned long clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::timeout(void) const */ clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL::clsIPAddressWithTTL(IPAddress p_IPAddress, - uint32_t p_u32TTL /*= 0*/) + uint32_t p_u32TTL /*= 0*/) : m_IPAddress(p_IPAddress) { m_TTL.set(p_u32TTL); @@ -2514,8 +2514,8 @@ bool clsLEAMDNSHost::clsQuery::clsAnswer::removeIPv4Address(clsLEAMDNSHost::clsQ bool bResult = false; clsIPAddressWithTTL::list::iterator it(p_pIPv4Address - ? std::find(m_IPv4Addresses.begin(), m_IPv4Addresses.end(), p_pIPv4Address) - : m_IPv4Addresses.end()); + ? std::find(m_IPv4Addresses.begin(), m_IPv4Addresses.end(), p_pIPv4Address) + : m_IPv4Addresses.end()); if (m_IPv4Addresses.end() != it) { m_IPv4Addresses.erase(it); @@ -2583,8 +2583,8 @@ const clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* clsLEAMDNSHost:: uint32_t u32CurIndex = 0; for (clsIPAddressWithTTL::list::const_iterator it = m_IPv4Addresses.begin(); - (((uint32_t)(-1) != p_u32Index) && (u32CurIndex <= p_u32Index) && (it != m_IPv4Addresses.end())); - it++, u32CurIndex++) + (((uint32_t)(-1) != p_u32Index) && (u32CurIndex <= p_u32Index) && (it != m_IPv4Addresses.end())); + it++, u32CurIndex++) { if (p_u32Index == u32CurIndex++) { @@ -2636,8 +2636,8 @@ bool clsLEAMDNSHost::clsQuery::clsAnswer::removeIPv6Address(clsLEAMDNSHost::clsQ bool bResult = false; clsIPAddressWithTTL::list::iterator it(p_pIPv6Address - ? std::find(m_IPv6Addresses.begin(), m_IPv6Addresses.end(), p_pIPv6Address) - : m_IPv6Addresses.end()); + ? std::find(m_IPv6Addresses.begin(), m_IPv6Addresses.end(), p_pIPv6Address) + : m_IPv6Addresses.end()); if (m_IPv6Addresses.end() != it) { m_IPv6Addresses.erase(it); @@ -2705,8 +2705,8 @@ const clsLEAMDNSHost::clsQuery::clsAnswer::clsIPAddressWithTTL* clsLEAMDNSHost:: uint32_t u32CurIndex = 0; for (clsIPAddressWithTTL::list::const_iterator it = m_IPv6Addresses.begin(); - (((uint32_t)(-1) != p_u32Index) && (u32CurIndex <= p_u32Index) && (it != m_IPv6Addresses.end())); - it++, u32CurIndex++) + (((uint32_t)(-1) != p_u32Index) && (u32CurIndex <= p_u32Index) && (it != m_IPv6Addresses.end())); + it++, u32CurIndex++) { if (p_u32Index == u32CurIndex++) { @@ -2732,7 +2732,7 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::clsAnswerAccessor(const clsLEAMDNSH : m_pAnswer(p_pAnswer) { if ((m_pAnswer) && - (txtsAvailable())) + (txtsAvailable())) { // Prepare m_TxtKeyValueMap for (const clsLEAMDNSHost::clsServiceTxt* pTxt : m_pAnswer->m_Txts.m_Txts) @@ -2759,7 +2759,7 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::~clsAnswerAccessor(void) */ bool clsLEAMDNSHost::clsQuery::clsAnswerAccessor::stcCompareTxtKey::operator()(char const* p_pA, - char const* p_pB) const + char const* p_pB) const { return (0 > strcasecmp(p_pA, p_pB)); } @@ -2846,7 +2846,7 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::clsIPAddressVector clsLEAMDNSHost:: { clsIPAddressVector internalIP; if ((m_pAnswer) && - (IPv4AddressAvailable())) + (IPv4AddressAvailable())) { for (uint32_t u = 0; u < m_pAnswer->IPv4AddressCount(); ++u) { @@ -2880,7 +2880,7 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::clsIPAddressVector clsLEAMDNSHost:: { clsIPAddressVector internalIP; if ((m_pAnswer) && - (IPv6AddressAvailable())) + (IPv6AddressAvailable())) { for (uint32_t u = 0; u < m_pAnswer->IPv6AddressCount(); ++u) { @@ -2941,7 +2941,7 @@ const char* clsLEAMDNSHost::clsQuery::clsAnswerAccessor::txtValue(const char* p_ for (const clsLEAMDNSHost::clsServiceTxt* pTxt : m_pAnswer->m_Txts.m_Txts) { if ((p_pcKey) && - (0 == strcasecmp(pTxt->m_pcKey, p_pcKey))) + (0 == strcasecmp(pTxt->m_pcKey, p_pcKey))) { pcResult = pTxt->m_pcValue; break; @@ -3110,8 +3110,8 @@ const clsLEAMDNSHost::clsQuery::clsAnswer* clsLEAMDNSHost::clsQuery::answer(uint uint32_t u32CurIndex = 0; for (clsAnswer::list::const_iterator it = m_Answers.begin(); - (((uint32_t)(-1) != p_u32Index) && (u32CurIndex <= p_u32Index) && (it != m_Answers.end())); - it++, u32CurIndex++) + (((uint32_t)(-1) != p_u32Index) && (u32CurIndex <= p_u32Index) && (it != m_Answers.end())); + it++, u32CurIndex++) { if (p_u32Index == u32CurIndex++) { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 50880585cc..f4a187b667 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -100,7 +100,7 @@ bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParam DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage (V4): FAILED!\n"), _DH());); if ((clsConsts::u32SendCooldown) && - (can_yield())) + (can_yield())) { delay(clsConsts::u32SendCooldown); } @@ -110,16 +110,16 @@ bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParam // Multicast response -> Send via the same network interface, that received the query #ifdef MDNS_IPV4_SUPPORT if (((!ipRemote.isSet()) || // NO remote IP - (ipRemote.isV4())) && // OR IPv4 - (u8AvailableProtocols & static_cast<uint8_t>(enuIPProtocolType::V4))) // AND IPv4 protocol available + (ipRemote.isV4())) && // OR IPv4 + (u8AvailableProtocols & static_cast<uint8_t>(enuIPProtocolType::V4))) // AND IPv4 protocol available { bResult = _sendMessage_Multicast(p_rSendParameter, static_cast<uint8_t>(enuIPProtocolType::V4)); } #endif #ifdef MDNS_IPV6_SUPPORT if (((!ipRemote.isSet()) || // NO remote IP - (ipRemote.isV6())) && // OR IPv6 - (u8AvailableProtocols & static_cast<uint8_t>(enuIPProtocolType::V6))) // AND IPv6 protocol available + (ipRemote.isV6())) && // OR IPv6 + (u8AvailableProtocols & static_cast<uint8_t>(enuIPProtocolType::V6))) // AND IPv6 protocol available { bResult = _sendMessage_Multicast(p_rSendParameter, static_cast<uint8_t>(enuIPProtocolType::V6)); } @@ -153,7 +153,7 @@ bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParam via the selected WiFi protocols */ bool clsLEAMDNSHost::_sendMessage_Multicast(clsLEAMDNSHost::clsSendParameter& p_rSendParameter, - uint8_t p_IPProtocolTypes) + uint8_t p_IPProtocolTypes) { bool bIPv4Result = true; bool bIPv6Result = true; @@ -173,7 +173,7 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(clsLEAMDNSHost::clsSendParameter& p_ DEBUG_EX_ERR(if (!bIPv4Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (V4): FAILED!\n"), _DH());); if ((clsConsts::u32SendCooldown) && - (can_yield())) + (can_yield())) { delay(clsConsts::u32SendCooldown); } @@ -199,7 +199,7 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(clsLEAMDNSHost::clsSendParameter& p_ DEBUG_EX_ERR(if (!bIPv6Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (IPv6): FAILED! (%s, %s, %s)\n"), _DH(), (_getResponderIPAddress(enuIPProtocolType::V6).isSet() ? "1" : "0"), (bPrepareMessage ? "1" : "0"), (bUDPContextSend ? "1" : "0"));); if ((clsConsts::u32SendCooldown) && - (can_yield())) + (can_yield())) { delay(clsConsts::u32SendCooldown); } @@ -287,8 +287,8 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa #ifdef MDNS_IPV4_SUPPORT // A if ((bResult) && - (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::A)) && - (_getResponderIPAddress(enuIPProtocolType::V4).isSet())) + (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::A)) && + (_getResponderIPAddress(enuIPProtocolType::V4).isSet())) { u32NSECContent |= static_cast<uint32_t>(enuContentFlag::A); @@ -299,8 +299,8 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa } // PTR_IPv4 if ((bResult) && - (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)) && - (_getResponderIPAddress(enuIPProtocolType::V4).isSet())) + (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)) && + (_getResponderIPAddress(enuIPProtocolType::V4).isSet())) { u32NSECContent |= static_cast<uint32_t>(enuContentFlag::PTR_IPv4); @@ -313,8 +313,8 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa #ifdef MDNS_IPV6_SUPPORT // AAAA if ((bResult) && - (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::AAAA)) && - (_getResponderIPAddress(enuIPProtocolType::V6).isSet())) + (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::AAAA)) && + (_getResponderIPAddress(enuIPProtocolType::V6).isSet())) { u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); @@ -325,8 +325,8 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa } // PTR_IPv6 if ((bResult) && - (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv6)) && - (_getResponderIPAddress(enuIPProtocolType::V6).isSet())) + (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv6)) && + (_getResponderIPAddress(enuIPProtocolType::V6).isSet())) { u32NSECContent |= static_cast<uint32_t>(enuContentFlag::PTR_IPv6); @@ -343,7 +343,7 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa // PTR_TYPE if ((bResult) && - (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_TYPE))) + (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_TYPE))) { ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16Answers @@ -352,7 +352,7 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa } // PTR_NAME if ((bResult) && - (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_NAME))) + (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_NAME))) { ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16Answers @@ -361,7 +361,7 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa } // SRV if ((bResult) && - (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::SRV))) + (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::SRV))) { ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16Answers @@ -370,7 +370,7 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa } // TXT if ((bResult) && - (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::TXT))) + (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::TXT))) { ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16Answers @@ -393,8 +393,8 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa clsService* pService = *it; if ((bResult) && - (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_NAME)) && // If PTR_NAME is requested, AND - (!(pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::SRV)))) // NOT SRV -> add SRV as additional answer + (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_NAME)) && // If PTR_NAME is requested, AND + (!(pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::SRV)))) // NOT SRV -> add SRV as additional answer { ((static_cast<typeSequence>(enuSequence::Count) == sequence) @@ -413,18 +413,18 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa } */ if ((pService->m_u32ReplyMask & (static_cast<uint32_t>(enuContentFlag::PTR_NAME) | static_cast<uint32_t>(enuContentFlag::SRV))) || // If service instance name or SRV OR - (p_rSendParameter.m_u32HostReplyMask & (static_cast<uint32_t>(enuContentFlag::A) | static_cast<uint32_t>(enuContentFlag::AAAA)))) // any host IP address is requested + (p_rSendParameter.m_u32HostReplyMask & (static_cast<uint32_t>(enuContentFlag::A) | static_cast<uint32_t>(enuContentFlag::AAAA)))) // any host IP address is requested { #ifdef MDNS_IPV4_SUPPORT if ((bResult) && - (!(p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::A)))) // Add IPv4 address + (!(p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::A)))) // Add IPv4 address { bNeedsAdditionalAnswerA = true; } #endif #ifdef MDNS_IPV6_SUPPORT if ((bResult) && - (!(p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::AAAA)))) // Add IPv6 address + (!(p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::AAAA)))) // Add IPv6 address { bNeedsAdditionalAnswerAAAA = true; } @@ -432,8 +432,8 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa } // NSEC record for service if ((bResult) && - (pService->m_u32ReplyMask) && - ((clsSendParameter::enuResponseType::None != p_rSendParameter.m_Response))) + (pService->m_u32ReplyMask) && + ((clsSendParameter::enuResponseType::None != p_rSendParameter.m_Response))) { ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16AdditionalAnswers @@ -445,8 +445,8 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa #ifdef MDNS_IPV4_SUPPORT // Answer A needed? if ((bResult) && - (bNeedsAdditionalAnswerA) && - (_getResponderIPAddress(enuIPProtocolType::V4).isSet())) + (bNeedsAdditionalAnswerA) && + (_getResponderIPAddress(enuIPProtocolType::V4).isSet())) { // Additional A u32NSECContent |= static_cast<uint32_t>(enuContentFlag::A); @@ -460,8 +460,8 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa #ifdef MDNS_IPV6_SUPPORT // Answer AAAA needed? if ((bResult) && - (bNeedsAdditionalAnswerAAAA) && - (_getResponderIPAddress(enuIPProtocolType::V6).isSet())) + (bNeedsAdditionalAnswerAAAA) && + (_getResponderIPAddress(enuIPProtocolType::V6).isSet())) { // Additional AAAA u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); @@ -475,8 +475,8 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa // NSEC host (part 2) if ((bResult) && - ((clsSendParameter::enuResponseType::None != p_rSendParameter.m_Response)) && - (u32NSECContent)) + ((clsSendParameter::enuResponseType::None != p_rSendParameter.m_Response)) && + (u32NSECContent)) { // NSEC PTR IPv4/IPv6 are separate answers; make sure, that this is counted for #ifdef MDNS_IPV4_SUPPORT @@ -640,8 +640,8 @@ IPAddress clsLEAMDNSHost::_getResponderIPAddress(enuIPProtocolType p_IPProtocolT { //DEBUG_EX_INFO(if ip6_addr_isvalid(netif_ip6_addr_state(&m_rNetIf, idx)) DEBUG_OUTPUT.printf_P(PSTR("%s _getResponderIPAddress: Checking IPv6 address %s (LL: %s)\n"), _DH(), IPAddress(netif_ip_addr6(m_pNetIf, idx)).toString().c_str(), (bCheckLinkLocal ? "YES" : "NO"));); if ((ip6_addr_isvalid(netif_ip6_addr_state(m_pNetIf, idx))) && - (((!bCheckLinkLocal) || - (ip6_addr_islinklocal(netif_ip6_addr(m_pNetIf, idx)))))) + (((!bCheckLinkLocal) || + (ip6_addr_islinklocal(netif_ip6_addr(m_pNetIf, idx)))))) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _getResponderIPAddress: Selected IPv6 address %s (LL: %s)\n"), _DH(), IPAddress(netif_ip_addr6(m_pNetIf, idx)).toString().c_str(), (bCheckLinkLocal ? "YES" : "NO"));); ipResponder = netif_ip_addr6(m_pNetIf, idx); @@ -713,8 +713,8 @@ bool clsLEAMDNSHost::_readRRAnswer(clsLEAMDNSHost::clsRRAnswer*& p_rpRRAnswer) uint32_t u32TTL; uint16_t u16RDLength; if ((_readRRHeader(header)) && - (_udpRead32(u32TTL)) && - (_udpRead16(u16RDLength))) + (_udpRead32(u32TTL)) && + (_udpRead16(u16RDLength))) { /* DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer: Reading 0x%04X answer (class:0x%04X, TTL:%u, RDLength:%u) for "), header.m_Attributes.m_u16Type, header.m_Attributes.m_u16Class, u32TTL, u16RDLength); @@ -876,7 +876,7 @@ bool clsLEAMDNSHost::_readRRAnswerTXT(clsLEAMDNSHost::clsRRAnswerTXT& p_rRRAnswe const unsigned char* pucCursor = pucBuffer; while ((pucCursor < (pucBuffer + p_u16RDLength)) && - (bResult)) + (bResult)) { bResult = false; @@ -894,7 +894,7 @@ bool clsLEAMDNSHost::_readRRAnswerTXT(clsLEAMDNSHost::clsRRAnswerTXT& p_rRRAnswe unsigned char* pucEqualSign = (unsigned char*)os_strchr((const char*)pucCursor, '='); // Position of the '=' sign unsigned char ucKeyLength; if ((pucEqualSign) && - ((ucKeyLength = (pucEqualSign - pucCursor)))) + ((ucKeyLength = (pucEqualSign - pucCursor)))) { unsigned char ucValueLength = (ucLength - (pucEqualSign - pucCursor + 1)); bResult = (((pTxt = new clsServiceTxt)) && @@ -914,7 +914,7 @@ bool clsLEAMDNSHost::_readRRAnswerTXT(clsLEAMDNSHost::clsRRAnswerTXT& p_rRRAnswe } if ((bResult) && - (pTxt)) + (pTxt)) { // Everythings fine so far // Link TXT item to answer TXTs @@ -1012,13 +1012,13 @@ bool clsLEAMDNSHost::_readRRAnswerSRV(clsLEAMDNSHost::clsRRAnswerSRV& p_rRRAnswe MDNSResponder::_readRRAnswerGeneric */ bool clsLEAMDNSHost::_readRRAnswerGeneric(clsLEAMDNSHost::clsRRAnswerGeneric& p_rRRAnswerGeneric, - uint16_t p_u16RDLength) + uint16_t p_u16RDLength) { bool bResult = (0 == p_u16RDLength); p_rRRAnswerGeneric.clear(); if (((p_rRRAnswerGeneric.m_u16RDLength = p_u16RDLength)) && - ((p_rRRAnswerGeneric.m_pu8RDData = new unsigned char[p_rRRAnswerGeneric.m_u16RDLength]))) + ((p_rRRAnswerGeneric.m_pu8RDData = new unsigned char[p_rRRAnswerGeneric.m_u16RDLength]))) { bResult = _udpReadBuffer(p_rRRAnswerGeneric.m_pu8RDData, p_rRRAnswerGeneric.m_u16RDLength); } @@ -1178,7 +1178,7 @@ bool clsLEAMDNSHost::_readRRAttributes(clsLEAMDNSHost::clsRRAttributes& p_rRRAtt */ bool clsLEAMDNSHost::_buildDomainForHost(const char* p_pcHostName, - clsLEAMDNSHost::clsRRDomain& p_rHostDomain) const + clsLEAMDNSHost::clsRRDomain& p_rHostDomain) const { p_rHostDomain.clear(); @@ -1218,8 +1218,8 @@ bool clsLEAMDNSHost::_buildDomainForDNSSD(clsLEAMDNSHost::clsRRDomain& p_rDNSSDD */ bool clsLEAMDNSHost::_buildDomainForService(const clsLEAMDNSHost::clsService& p_Service, - bool p_bIncludeName, - clsLEAMDNSHost::clsRRDomain& p_rServiceDomain) const + bool p_bIncludeName, + clsLEAMDNSHost::clsRRDomain& p_rServiceDomain) const { p_rServiceDomain.clear(); bool bResult = (((!p_bIncludeName) || @@ -1240,8 +1240,8 @@ bool clsLEAMDNSHost::_buildDomainForService(const clsLEAMDNSHost::clsService& p_ */ bool clsLEAMDNSHost::_buildDomainForService(const char* p_pcServiceType, - const char* p_pcProtocol, - clsLEAMDNSHost::clsRRDomain& p_rServiceDomain) const + const char* p_pcProtocol, + clsLEAMDNSHost::clsRRDomain& p_rServiceDomain) const { p_rServiceDomain.clear(); bool bResult = ((p_pcServiceType) && @@ -1264,7 +1264,7 @@ bool clsLEAMDNSHost::_buildDomainForService(const char* p_pcServiceType, */ bool clsLEAMDNSHost::_buildDomainForReverseIPv4(IPAddress p_IPv4Address, - clsLEAMDNSHost::clsRRDomain& p_rReverseIPv4Domain) const + clsLEAMDNSHost::clsRRDomain& p_rReverseIPv4Domain) const { bool bResult = ((p_IPv4Address.isSet()) && (p_IPv4Address.isV4())); @@ -1296,7 +1296,7 @@ bool clsLEAMDNSHost::_buildDomainForReverseIPv4(IPAddress p_IPv4Address, */ bool clsLEAMDNSHost::_buildDomainForReverseIPv6(IPAddress p_IPv6Address, - clsLEAMDNSHost::clsRRDomain& p_rReverseIPv6Domain) const + clsLEAMDNSHost::clsRRDomain& p_rReverseIPv6Domain) const { bool bResult = ((p_IPv6Address.isSet()) && (p_IPv6Address.isV6())); @@ -1507,12 +1507,12 @@ bool clsLEAMDNSHost::_readMDNSMsgHeader(clsLEAMDNSHost::clsMsgHeader& p_rMsgHead uint8_t u8B1; uint8_t u8B2; if ((_udpRead16(p_rMsgHeader.m_u16ID)) && - (_udpRead8(u8B1)) && - (_udpRead8(u8B2)) && - (_udpRead16(p_rMsgHeader.m_u16QDCount)) && - (_udpRead16(p_rMsgHeader.m_u16ANCount)) && - (_udpRead16(p_rMsgHeader.m_u16NSCount)) && - (_udpRead16(p_rMsgHeader.m_u16ARCount))) + (_udpRead8(u8B1)) && + (_udpRead8(u8B2)) && + (_udpRead16(p_rMsgHeader.m_u16QDCount)) && + (_udpRead16(p_rMsgHeader.m_u16ANCount)) && + (_udpRead16(p_rMsgHeader.m_u16NSCount)) && + (_udpRead16(p_rMsgHeader.m_u16ARCount))) { p_rMsgHeader.m_1bQR = (u8B1 & 0x80); // Query/Responde flag @@ -1584,7 +1584,7 @@ bool clsLEAMDNSHost::_write32(uint32_t p_u32Value, */ bool clsLEAMDNSHost::_writeMDNSMsgHeader(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { /* DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSMsgHeader: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), _DH(), @@ -1615,7 +1615,7 @@ bool clsLEAMDNSHost::_writeMDNSMsgHeader(const clsLEAMDNSHost::clsMsgHeader& p_M */ bool clsLEAMDNSHost::_writeMDNSRRAttributes(const clsLEAMDNSHost::clsRRAttributes& p_Attributes, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { bool bResult = ((_write16(p_Attributes.m_u16Type, p_rSendParameter)) && (_write16(p_Attributes.m_u16Class, p_rSendParameter))); @@ -1654,9 +1654,9 @@ bool clsLEAMDNSHost::_writeMDNSRRDomain(const clsLEAMDNSHost::clsRRDomain& p_Dom */ bool clsLEAMDNSHost::_writeMDNSHostDomain(const char* p_pcHostName, - bool p_bPrependRDLength, - uint16_t p_u16AdditionalLength, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + bool p_bPrependRDLength, + uint16_t p_u16AdditionalLength, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { // The 'skip-compression' version is handled in '_writeMDNSAnswer_SRV' uint16_t u16CachedDomainOffset = p_rSendParameter.findCachedDomainOffset((const void*)p_pcHostName, false); @@ -1694,10 +1694,10 @@ bool clsLEAMDNSHost::_writeMDNSHostDomain(const char* p_pcHostName, */ bool clsLEAMDNSHost::_writeMDNSServiceDomain(const clsLEAMDNSHost::clsService& p_Service, - bool p_bIncludeName, - bool p_bPrependRDLength, - uint16_t p_u16AdditionalLength, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + bool p_bIncludeName, + bool p_bPrependRDLength, + uint16_t p_u16AdditionalLength, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { // The 'skip-compression' version is handled in '_writeMDNSAnswer_SRV' uint16_t u16CachedDomainOffset = p_rSendParameter.findCachedDomainOffset((const void*)&p_Service, p_bIncludeName); @@ -1815,7 +1815,7 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_A(IPAddress p_IPAddress, */ bool clsLEAMDNSHost::_writeMDNSAnswer_PTR_IPv4(IPAddress p_IPAddress, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_IPv4 (%s)%s\n"), p_IPAddress.toString().c_str(), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); @@ -1860,7 +1860,7 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_PTR_IPv4(IPAddress p_IPAddress, */ bool clsLEAMDNSHost::_writeMDNSAnswer_PTR_TYPE(clsLEAMDNSHost::clsService& p_rService, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_TYPE\n"));); @@ -1903,7 +1903,7 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_PTR_TYPE(clsLEAMDNSHost::clsService& p_rSe */ bool clsLEAMDNSHost::_writeMDNSAnswer_PTR_NAME(clsLEAMDNSHost::clsService& p_rService, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_NAME\n"), _DH());); @@ -1947,7 +1947,7 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_PTR_NAME(clsLEAMDNSHost::clsService& p_rSe */ bool clsLEAMDNSHost::_writeMDNSAnswer_TXT(clsLEAMDNSHost::clsService& p_rService, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_TXT%s\n"), (p_rSendParameter.m_bCacheFlush ? "" : " nF"), _DH());); @@ -1957,16 +1957,16 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_TXT(clsLEAMDNSHost::clsService& p_rService ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet if ((_collectServiceTxts(p_rService)) && - (_writeMDNSServiceDomain(p_rService, true, false, 0, p_rSendParameter)) && // MyESP._http._tcp.local - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce - ? 0 - : (p_rSendParameter.m_bLegacyDNSQuery // TTL - ? clsConsts::u32LegacyTTL - : clsConsts::u32ServiceTTL)), p_rSendParameter)) && - (_write16((p_rService.m_Txts.count() // RDLength - ? p_rService.m_Txts.length() // default case - : 1), p_rSendParameter))) // If no TXT records exist, a single 0 byte is sent + (_writeMDNSServiceDomain(p_rService, true, false, 0, p_rSendParameter)) && // MyESP._http._tcp.local + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce + ? 0 + : (p_rSendParameter.m_bLegacyDNSQuery // TTL + ? clsConsts::u32LegacyTTL + : clsConsts::u32ServiceTTL)), p_rSendParameter)) && + (_write16((p_rService.m_Txts.count() // RDLength + ? p_rService.m_Txts.length() // default case + : 1), p_rSendParameter))) // If no TXT records exist, a single 0 byte is sent { bResult = true; // RData Txts @@ -2035,7 +2035,7 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_TXT(clsLEAMDNSHost::clsService& p_rService */ bool clsLEAMDNSHost::_writeMDNSAnswer_AAAA(IPAddress p_IPAddress, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_AAAA (%s)%s\n"), p_IPAddress.toString().c_str(), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); @@ -2077,7 +2077,7 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_AAAA(IPAddress p_IPAddress, */ bool clsLEAMDNSHost::_writeMDNSAnswer_PTR_IPv6(IPAddress p_IPAddress, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_PTR_IPv6%s\n"), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); @@ -2117,13 +2117,13 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_PTR_IPv6(IPAddress p_IPAddress, */ bool clsLEAMDNSHost::_writeMDNSAnswer_SRV(clsLEAMDNSHost::clsService& p_rService, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_SRV%s\n"), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); uint16_t u16CachedDomainOffset = (p_rSendParameter.m_bLegacyDNSQuery - ? 0 - : p_rSendParameter.findCachedDomainOffset((const void*)m_pcHostName, false)); + ? 0 + : p_rSendParameter.findCachedDomainOffset((const void*)m_pcHostName, false)); clsRRAttributes attributes(DNS_RRTYPE_SRV, ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet @@ -2194,7 +2194,7 @@ clsLEAMDNSHost::clsNSECBitmap* clsLEAMDNSHost::_createNSECBitmap(uint32_t p_u32N } #endif if ((p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)) || - (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv6))) + (p_u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv6))) { pNSECBitmap->setBit(DNS_RRTYPE_PTR); // 12/0x0C } @@ -2225,7 +2225,7 @@ clsLEAMDNSHost::clsNSECBitmap* clsLEAMDNSHost::_createNSECBitmap(uint32_t p_u32N */ bool clsLEAMDNSHost::_writeMDNSNSECBitmap(const clsLEAMDNSHost::clsNSECBitmap& p_NSECBitmap, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { /* DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("_writeMDNSNSECBitmap: ")); for (uint16_t u=0; u<p_NSECBitmap.m_u16BitmapLength; ++u) { @@ -2249,7 +2249,7 @@ bool clsLEAMDNSHost::_writeMDNSNSECBitmap(const clsLEAMDNSHost::clsNSECBitmap& p */ bool clsLEAMDNSHost::_writeMDNSAnswer_NSEC(uint32_t p_u32NSECContent, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC (host: %s)%s\n"), _replyFlags2String(p_u32NSECContent), (p_rSendParameter.m_bCacheFlush ? "" : " nF"));); @@ -2298,7 +2298,7 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_NSEC(uint32_t p_u32NSECContent, */ bool clsLEAMDNSHost::_writeMDNSAnswer_NSEC_PTR_IPv4(IPAddress p_IPAddress, - clsSendParameter& p_rSendParameter) + clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC_PTR_IPv4\n"));); @@ -2353,7 +2353,7 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_NSEC_PTR_IPv4(IPAddress p_IPAddress, */ bool clsLEAMDNSHost::_writeMDNSAnswer_NSEC_PTR_IPv6(IPAddress p_IPAddress, - clsSendParameter& p_rSendParameter) + clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC_PTR_IPv6\n"));); @@ -2406,8 +2406,8 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_NSEC_PTR_IPv6(IPAddress p_IPAddress, */ bool clsLEAMDNSHost::_writeMDNSAnswer_NSEC(clsLEAMDNSHost::clsService& p_rService, - uint32_t p_u32NSECContent, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) + uint32_t p_u32NSECContent, + clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_NSEC (service: %s)\n"), _DH(), _replyFlags2String(p_u32NSECContent));); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index 1f5f0422d4..83ecf0c8a4 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -71,7 +71,7 @@ UdpContext* clsLEAMDNSHost::clsBackbone::addHost(clsLEAMDNSHost* p_pHost) UdpContext* pUDPContext = 0; if ((m_pUDPContext) && - (p_pHost)) + (p_pHost)) { m_HostList.push_back(p_pHost); pUDPContext = m_pUDPContext; @@ -89,7 +89,7 @@ bool clsLEAMDNSHost::clsBackbone::removeHost(clsLEAMDNSHost* p_pHost) bool bResult = false; if ((p_pHost) && - (m_HostList.end() != std::find(m_HostList.begin(), m_HostList.end(), p_pHost))) + (m_HostList.end() != std::find(m_HostList.begin(), m_HostList.end(), p_pHost))) { // Remove host object m_HostList.remove(p_pHost); @@ -126,7 +126,7 @@ bool clsLEAMDNSHost::clsBackbone::setDelayUDPProcessing(bool p_bDelayUDPProcessi m_bDelayUDPProcessing = p_bDelayUDPProcessing; if ((!m_bDelayUDPProcessing) && - (m_u32DelayedDatagrams)) + (m_u32DelayedDatagrams)) { DEBUG_EX_INFO2(if (6 <= m_u32DelayedDatagrams) DEBUG_OUTPUT.printf_P(PSTR("%s setDelayUDPProcessing: Processing %u delayed datagram(s)\n"), _DH(), m_u32DelayedDatagrams);); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s setDelayUDPProcessing: Processing %u delayed datagram(s)\n"), _DH(), m_u32DelayedDatagrams);); @@ -215,19 +215,19 @@ bool clsLEAMDNSHost::clsBackbone::_processUDPInput(void) { DEBUG_EX_INFO(uint32_t u32LoopCounter = 0; IPAddress remoteIPAddr;); while ((m_pUDPContext) && - (m_pUDPContext->next())) + (m_pUDPContext->next())) { netif* pNetIf = m_pUDPContext->getInputNetif();//ip_current_input_netif(); // Probably changed inbetween!!!! clsLEAMDNSHost* pHost = 0; if ((pNetIf) && - ((pHost = _findHost(pNetIf)))) + ((pHost = _findHost(pNetIf)))) { DEBUG_EX_INFO( if (u32LoopCounter++) { DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Multi-Loop (%u)!\n"), _DH(), u32LoopCounter); if ((remoteIPAddr.isSet()) && - (remoteIPAddr != m_pUDPContext->getRemoteAddress())) + (remoteIPAddr != m_pUDPContext->getRemoteAddress())) { DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Changed IP address %s->%s!\n"), _DH(), remoteIPAddr.toString().c_str(), m_pUDPContext->getRemoteAddress().toString().c_str()); } @@ -264,7 +264,7 @@ const clsLEAMDNSHost* clsLEAMDNSHost::clsBackbone::_findHost(netif* p_pNetIf) co for (const clsLEAMDNSHost* pHost : m_HostList) { if ((p_pNetIf) && - (pHost->m_pNetIf == p_pNetIf)) + (pHost->m_pNetIf == p_pNetIf)) { pResult = pHost; break; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 040d915905..896018f81d 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -1,1493 +1,1495 @@ -/* - * LEAmDNS2_Legacy.cpp - * - * - */ - -#include "LEAmDNS2_Legacy.h" - - -namespace esp8266 -{ - -/** - * LEAmDNS - */ -namespace MDNSImplementation -{ - -/** - STRINGIZE -*/ -#ifndef STRINGIZE -#define STRINGIZE(x) #x -#endif -#ifndef STRINGIZE_VALUE_OF -#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) -#endif - - -/* - * clsLEAMDNSHost_Legacy::clsLEAMDNSHost_Legacy constructor - * - */ -clsLEAMDNSHost_Legacy::clsLEAMDNSHost_Legacy(void) -{ -} - -/* - * clsLEAMDNSHost_Legacy::clsLEAMDNSHost_Legacy destructor - * - */ -clsLEAMDNSHost_Legacy::~clsLEAMDNSHost_Legacy(void) -{ -} - -/* - * - * HOST SETUP - * - */ - -/* - * clsLEAMDNSHost_Legacy::begin - * - */ -bool clsLEAMDNSHost_Legacy::begin(const char* p_pcHostname) -{ - bool bResult = ( ( (!(WIFI_STA & (WiFiMode_t)wifi_get_opmode())) - || (addHostForNetIf(p_pcHostname, netif_get_by_index(WIFI_STA)))) - && ( (!(WIFI_AP & (WiFiMode_t)wifi_get_opmode())) - || (addHostForNetIf(p_pcHostname, netif_get_by_index(WIFI_AP))))); - return ( (bResult) - && (0 != m_HostInformations.size())); -} - -/* - * clsLEAMDNSHost_Legacy::begin (String) - * - */ -bool clsLEAMDNSHost_Legacy::begin(const String& p_strHostname) -{ - return begin(p_strHostname.c_str()); -} - -/* - * clsLEAMDNSHost_Legacy::begin (Ignored Options) - * - */ -bool clsLEAMDNSHost_Legacy::begin(const char* p_pcHostname, - IPAddress /*p_IPAddress = INADDR_ANY*/, // ignored - uint32_t /*p_u32TTL = 120*/) // ignored -{ - return begin(p_pcHostname); -} - -/* - * clsLEAMDNSHost_Legacy::begin (String & Ignored Options) - * - */ -bool clsLEAMDNSHost_Legacy::begin(const String& p_strHostname, - IPAddress /*p_IPAddress = INADDR_ANY*/, // ignored - uint32_t /*p_u32TTL = 120*/) // ignored -{ - return begin(p_strHostname.c_str()); -} - -/* - * clsLEAMDNSHost_Legacy::close - * - */ -bool clsLEAMDNSHost_Legacy::close(void) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - if ((bResult = (*it).m_pHost->close())) - { - delete (*it).m_pHost; - (*it).m_pHost = 0; - } - } - return ( (bResult) - && (m_HostInformations.clear(), true)); -} - -/* - * clsLEAMDNSHost_Legacy::end - * - */ -bool clsLEAMDNSHost_Legacy::end(void) -{ - return close(); -} - -/* - * clsLEAMDNSHost_Legacy::addHostForNetIf - * - * NEW! - * - */ -bool clsLEAMDNSHost_Legacy::addHostForNetIf(const char* p_pcHostname, - netif* p_pNetIf) -{ - clsLEAMDNSHost* pHost = 0; - - if ( ((pHost = new esp8266::experimental::clsLEAMDNSHost)) - && (!( (pHost->begin(p_pcHostname, p_pNetIf /*, default callback*/)) - && (m_HostInformations.push_back(stcHostInformation(pHost)), true)))) - { - delete pHost; - pHost = 0; - } - return (0 != pHost); -} - -/* - * clsLEAMDNSHost_Legacy::setHostname - * - */ -bool clsLEAMDNSHost_Legacy::setHostname(const char* p_pcHostname) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = (*it).m_pHost->setHostName(p_pcHostname); - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::setHostname - * - */ -bool clsLEAMDNSHost_Legacy::setHostname(String p_strHostname) -{ - return setHostname(p_strHostname.c_str()); -} - -/* - * clsLEAMDNSHost_Legacy::hostname - * - */ -const char* clsLEAMDNSHost_Legacy::hostname(void) const -{ - return (m_HostInformations.empty() - ? 0 - : m_HostInformations.front().m_pHost->hostName()); -} - -/* - * clsLEAMDNSHost_Legacy::status - * - */ -bool clsLEAMDNSHost_Legacy::status(void) const -{ - bool bStatus = true; - - for (const stcHostInformation& hostInformation : m_HostInformations) - { - if (!((bStatus = hostInformation.m_pHost->probeStatus()))) - { - break; - } - } - return bStatus; -} - - -/* - * - * SERVICE MANAGEMENT - * - */ - -/* - * clsLEAMDNSHost_Legacy::addService - * - */ -clsLEAMDNSHost_Legacy::hMDNSService clsLEAMDNSHost_Legacy::addService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port) -{ - hMDNSService hResult = 0; - - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsService* pService = hostInformation.m_pHost->addService(p_pcName, p_pcService, p_pcProtocol, p_u16Port /*, default callback*/); - if (pService) - { - if (!hResult) - { // Store first service handle as result and key - hResult = (hMDNSService)pService; - } - hostInformation.m_HandleToPtr[hResult] = pService; - } - } - return hResult; -} - -/* - * clsLEAMDNSHost_Legacy::addService (String) - * - */ -bool clsLEAMDNSHost_Legacy::addService(String p_strServiceName, - String p_strProtocol, - uint16_t p_u16Port) -{ - return (0 != addService(0, p_strServiceName.c_str(), p_strProtocol.c_str(), p_u16Port)); -} - -/* - * clsLEAMDNSHost_Legacy::removeService (hService) - * - */ -bool clsLEAMDNSHost_Legacy::removeService(const hMDNSService p_hService) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; - if ((bResult = ( (pService) - && ((*it).m_pHost->removeService(pService))))) - { - (*it).m_HandleToPtr.erase(p_hService); - } - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::removeService (name) - * - */ -bool clsLEAMDNSHost_Legacy::removeService(const char* p_pcInstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol) -{ - hMDNSService hService = 0; - return ( ((hService = (m_HostInformations.empty() - ? 0 - : (hMDNSService)m_HostInformations.front().m_pHost->findService(p_pcInstanceName, p_pcServiceName, p_pcProtocol)))) - && (removeService(hService))); -} - -/* - * clsLEAMDNSHost_Legacy::setServiceName - * - */ -bool clsLEAMDNSHost_Legacy::setServiceName(const hMDNSService p_hService, - const char* p_pcInstanceName) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; - bResult = ( (pService) - && (pService->setInstanceName(p_pcInstanceName))); - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::setInstanceName - * - */ -void clsLEAMDNSHost_Legacy::setInstanceName(const char* p_pcInstanceName) -{ - for (stcHostInformation& hostInformation : m_HostInformations) - { - hostInformation.m_pHost->setDefaultInstanceName(p_pcInstanceName); - } -} - -/* - * clsLEAMDNSHost_Legacy::setInstanceName (String) - * - */ -void clsLEAMDNSHost_Legacy::setInstanceName(const String& p_strHostname) -{ - setInstanceName(p_strHostname.c_str()); -} - -/* - * clsLEAMDNSHost_Legacy::serviceName - * - */ -const char* clsLEAMDNSHost_Legacy::serviceName(const hMDNSService p_hService) const -{ - const clsLEAMDNSHost::clsService* pService = 0; - return (m_HostInformations.empty() - ? 0 - : (((pService = (const clsLEAMDNSHost::clsService*)(m_HostInformations.front().m_HandleToPtr.at(p_hService)))) - ? pService->instanceName() - : 0)); -} - -/* - * clsLEAMDNSHost_Legacy::service - * - */ -const char* clsLEAMDNSHost_Legacy::service(const hMDNSService p_hService) const -{ - const clsLEAMDNSHost::clsService* pService = 0; - return (m_HostInformations.empty() - ? 0 - : (((pService = (const clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr.at(p_hService))) - ? pService->type() - : 0)); -} - -/* - * clsLEAMDNSHost_Legacy::serviceProtocol - * - */ -const char* clsLEAMDNSHost_Legacy::serviceProtocol(const hMDNSService p_hService) const -{ - const clsLEAMDNSHost::clsService* pService = 0; - return (m_HostInformations.empty() - ? 0 - : (((pService = (const clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr.at(p_hService))) - ? pService->protocol() - : 0)); -} - -/* - * clsLEAMDNSHost_Legacy::serviceStatus - * - */ -bool clsLEAMDNSHost_Legacy::serviceStatus(const hMDNSService p_hService) const -{ - const clsLEAMDNSHost::clsService* pService = 0; - return (m_HostInformations.empty() - ? false - : (((pService = (const clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr.at(p_hService))) - ? pService->probeStatus() - : false)); -} - - -/* - * - * SERVICE TXT MANAGEMENT - * - */ - -/* - * clsLEAMDNSHost_Legacy::addServiceTxt (char*) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue) -{ - return _addServiceTxt(p_hService, p_pcKey, p_pcValue, false); -} - -/* - * clsLEAMDNSHost_Legacy::addServiceTxt (uint32_t) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_u32Value, false); -} - -/* - * clsLEAMDNSHost_Legacy::addServiceTxt (uint16_t) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_u16Value, false); -} - -/* - * clsLEAMDNSHost_Legacy::addServiceTxt (uint8_t) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_u8Value, false); -} - -/* - * clsLEAMDNSHost_Legacy::addServiceTxt (int32_t) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_i32Value, false); -} - -/* - * clsLEAMDNSHost_Legacy::addServiceTxt (int16_t) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_i16Value, false); -} - -/* - * clsLEAMDNSHost_Legacy::addServiceTxt (int8_t) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_i8Value, false); -} - -/* - * clsLEAMDNSHost_Legacy::addServiceTxt (legacy) - * - */ -bool clsLEAMDNSHost_Legacy::addServiceTxt(const char* p_pcService, - const char* p_pcProtocol, - const char* p_pcKey, - const char* p_pcValue) -{ - hMDNSService hService = 0; - return ( ((hService = (m_HostInformations.empty() - ? 0 - : (hMDNSService)m_HostInformations.front().m_pHost->findService(0, p_pcService, p_pcProtocol)))) - && (_addServiceTxt(hService, p_pcKey, p_pcValue, false))); -} - -/* - * clsLEAMDNSHost_Legacy::addServiceTxt (legacy, String) - * - */ -bool clsLEAMDNSHost_Legacy::addServiceTxt(String p_strService, - String p_strProtocol, - String p_strKey, - String p_strValue) -{ - return addServiceTxt(p_strService.c_str(), p_strProtocol.c_str(), p_strKey.c_str(), p_strValue.c_str()); -} - -/* - * clsLEAMDNSHost_Legacy::removeServiceTxt (hTxt) - * - */ -bool clsLEAMDNSHost_Legacy::removeServiceTxt(const hMDNSService p_hService, - const hMDNSTxt p_hTxt) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; - clsLEAMDNSHost::clsServiceTxt* pTxt = (clsLEAMDNSHost::clsServiceTxt*)(*it).m_HandleToPtr[p_hTxt]; - if ((bResult = ( (pService) - && (pTxt) - && (pService->removeServiceTxt(pTxt))))) - { - (*it).m_HandleToPtr.erase(p_hTxt); - } - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::removeServiceTxt (char*) - * - */ -bool clsLEAMDNSHost_Legacy::removeServiceTxt(const hMDNSService p_hService, - const char* p_pcKey) -{ - clsLEAMDNSHost::clsService* pService = 0; - clsLEAMDNSHost::clsServiceTxt* pTxt = 0; - return ( ((pService = (m_HostInformations.empty() - ? 0 - : (clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr[p_hService]))) - && ((pTxt = pService->findServiceTxt(p_pcKey))) - && (removeServiceTxt(p_hService, (const hMDNSTxt)pTxt))); -} - -/* - * clsLEAMDNSHost_Legacy::removeServiceTxt (char*) - * - */ -bool clsLEAMDNSHost_Legacy::removeServiceTxt(const char* p_pcInstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol, - const char* p_pcKey) -{ - hMDNSService hService = 0; - return ( ((hService = (m_HostInformations.empty() - ? 0 - : (hMDNSService)m_HostInformations.front().m_pHost->findService(p_pcInstanceName, p_pcServiceName, p_pcProtocol)))) - && (removeServiceTxt(hService, p_pcKey))); -} - -/* - * clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback (global) - * - */ -bool clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFn p_fnCallback) -{ - bool bResult = true; - - if ((bResult = m_HostInformations.empty())) - { - // The service handles of the first host are the keys in the HostInformations.HandleToPtr map - for (const clsLEAMDNSHost::clsService* pService : m_HostInformations.front().m_pHost->services()) - { - if (!((bResult = setDynamicServiceTxtCallback((hMDNSService)pService, p_fnCallback)))) - { - break; - } - } - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback (service) - * - */ -bool clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback(const hMDNSService p_hService, - MDNSDynamicServiceTxtCallbackFn p_fnCallback) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; - bResult = pService->setDynamicServiceTxtCallback([p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/)->void - { - if (p_fnCallback) // void(const hMDNSService p_hService) - { - p_fnCallback(p_hService); - } - }); - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (char*) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue) -{ - return _addServiceTxt(p_hService, p_pcKey, p_pcValue, true); -} - -/* - * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (uint32) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_u32Value, true); -} - -/* - * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (uint16) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_u16Value, true); -} - -/* - * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (uint8) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_u8Value, true); -} - -/* - * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (int32) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_i32Value, true); -} - -/* - * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (int16) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_i16Value, true); -} - -/* - * clsLEAMDNSHost_Legacy::addDynamicServiceTxt (int8) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_i8Value, true); -} - - -/* - * - * STATIC QUERY - * - */ - - /* - * clsLEAMDNSHost_Legacy::queryService - * - * This will take p_u16Timeout millisec for every host! - * - */ -uint32_t clsLEAMDNSHost_Legacy::queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) -{ - uint32_t u32Answers = 0; - - for (stcHostInformation& hostInformation : m_HostInformations) - { - u32Answers += (hostInformation.m_pHost->queryService(p_pcService, p_pcProtocol, p_u16Timeout)).size(); - } - return u32Answers; -} - -/* - * clsLEAMDNSHost_Legacy::removeQuery - * - */ -bool clsLEAMDNSHost_Legacy::removeQuery(void) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = (*it).m_pHost->removeQuery(); - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::queryService - * - */ -uint32_t clsLEAMDNSHost_Legacy::queryService(String p_strService, - String p_strProtocol) -{ - return queryService(p_strService.c_str(), p_strProtocol.c_str()); -} - -/* - * clsLEAMDNSHost_Legacy::answerHostname - * - */ -const char* clsLEAMDNSHost_Legacy::answerHostname(const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_u32AnswerIndex); - return (answerAccessor.serviceDomainAvailable() - ? answerAccessor.serviceDomain() - : 0); -} - -/* - * clsLEAMDNSHost_Legacy::answerIP - * - */ -IPAddress clsLEAMDNSHost_Legacy::answerIP(const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_u32AnswerIndex); - return (answerAccessor.IPv4AddressAvailable() - ? answerAccessor.IPv4Addresses()[0] - : IPAddress()); -} - -/* - * clsLEAMDNSHost_Legacy::answerPort - * - */ -uint16_t clsLEAMDNSHost_Legacy::answerPort(const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_u32AnswerIndex); - return (answerAccessor.hostPortAvailable() - ? answerAccessor.hostPort() - : 0); -} - -/* - * clsLEAMDNSHost_Legacy::hostname - * - */ -String clsLEAMDNSHost_Legacy::hostname(const uint32_t p_u32AnswerIndex) -{ - return String(answerHostname(p_u32AnswerIndex)); -} - -/* - * clsLEAMDNSHost_Legacy::IP - * - */ -IPAddress clsLEAMDNSHost_Legacy::IP(const uint32_t p_u32AnswerIndex) -{ - return answerIP(p_u32AnswerIndex); -} - -/* - * clsLEAMDNSHost_Legacy::port - * - */ -uint16_t clsLEAMDNSHost_Legacy::port(const uint32_t p_u32AnswerIndex) -{ - return answerPort(p_u32AnswerIndex); -} - - -/* - * - * DYNAMIC QUERY - * - */ - -/* - * clsLEAMDNSHost_Legacy::installServiceQuery - * - */ -clsLEAMDNSHost_Legacy::hMDNSServiceQuery clsLEAMDNSHost_Legacy::installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - MDNSServiceQueryCallbackFn p_fnCallback) -{ - hMDNSServiceQuery hResult = 0; - - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsQuery* pQuery = hostInformation.m_pHost->installServiceQuery(p_pcService, p_pcProtocol, [this, p_fnCallback](const clsLEAMDNSHost::clsQuery& /*p_Query*/, - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor& p_AnswerAccessor, - clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item - bool p_bSetContent)->void - { - if (p_fnCallback) // void(const stcMDNSServiceInfo& p_MDNSServiceInfo, MDNSResponder::AnswerType p_AnswerType, bool p_bSetContent) - { - p_fnCallback(stcMDNSServiceInfo(p_AnswerAccessor), _answerFlagsToAnswerType(p_QueryAnswerTypeFlags), p_bSetContent); - } - }); - if (pQuery) - { - if (!hResult) - { // Store first query as result and key - hResult = (hMDNSServiceQuery)pQuery; - } - hostInformation.m_HandleToPtr[hResult] = pQuery; - } - } - return hResult; -} - -/* - * clsLEAMDNSHost_Legacy::removeServiceQuery - * - */ -bool clsLEAMDNSHost_Legacy::removeServiceQuery(clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - if ((bResult = (*it).m_pHost->removeQuery((clsLEAMDNSHost::clsQuery*)(*it).m_HandleToPtr[p_hServiceQuery]))) - { - (*it).m_HandleToPtr.erase(p_hServiceQuery); - } - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::answerCount - * - */ -uint32_t clsLEAMDNSHost_Legacy::answerCount(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery) -{ - uint32_t u32AnswerCount = 0; - - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; - if (pQuery) - { - u32AnswerCount += pQuery->answerCount(); - } - else - { - u32AnswerCount = 0; - break; - } - } - return u32AnswerCount; -} - -/* - * clsLEAMDNSHost_Legacy::answerInfo - * - */ -std::vector<clsLEAMDNSHost_Legacy::stcMDNSServiceInfo> clsLEAMDNSHost_Legacy::answerInfo(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery) -{ - std::vector<stcMDNSServiceInfo> serviceInfos; - - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; - if (pQuery) - { - for (clsLEAMDNSHost::clsQuery::clsAnswerAccessor& answerAccessor : pQuery->answerAccessors()) - { - serviceInfos.push_back(stcMDNSServiceInfo(answerAccessor)); - } - } - else - { - serviceInfos.clear(); - break; - } - } - return serviceInfos; -} - -/* - * clsLEAMDNSHost_Legacy::answerServiceDomain - * - */ -const char* clsLEAMDNSHost_Legacy::answerServiceDomain(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.serviceDomainAvailable() - ? answerAccessor.serviceDomain() - : 0); -} - -/* - * clsLEAMDNSHost_Legacy::hasAnswerHostDomain - * - */ -bool clsLEAMDNSHost_Legacy::hasAnswerHostDomain(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).hostDomainAvailable(); -} - -/* - * clsLEAMDNSHost_Legacy::answerHostDomain - * - */ -const char* clsLEAMDNSHost_Legacy::answerHostDomain(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.hostDomainAvailable() - ? answerAccessor.hostDomain() - : 0); -} - -#ifdef MDNS_IP4_SUPPORT -/* - * clsLEAMDNSHost_Legacy::hasAnswerIP4Address - * - */ -bool clsLEAMDNSHost_Legacy::hasAnswerIP4Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).IPv4AddressAvailable(); -} - -/* - * clsLEAMDNSHost_Legacy::answerIP4AddressCount - * - */ -uint32_t clsLEAMDNSHost_Legacy::answerIP4AddressCount(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.IPv4AddressAvailable() - ? answerAccessor.IPv4Addresses().size() - : 0); -} - -/* - * clsLEAMDNSHost_Legacy::answerIP4Address - * - */ -IPAddress clsLEAMDNSHost_Legacy::answerIP4Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.IPv4AddressAvailable() - ? answerAccessor.IPv4Addresses()[p_u32AddressIndex] - : IPAddress()); -} -#endif -#ifdef MDNS_IP6_SUPPORT -/* - * clsLEAMDNSHost_Legacy::hasAnswerIP6Address - * - */ -bool clsLEAMDNSHost_Legacy::hasAnswerIP6Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).IPv6AddressAvailable(); -} - -/* - * clsLEAMDNSHost_Legacy::answerIP6AddressCount - * - */ -uint32_t clsLEAMDNSHost_Legacy::answerIP6AddressCount(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.IPv6AddressAvailable() - ? answerAccessor.IPv6Addresses().size() - : 0); -} - -/* - * clsLEAMDNSHost_Legacy::answerIP6Address - * - */ -IPAddress clsLEAMDNSHost_Legacy::answerIP6Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.IPv6AddressAvailable() - ? answerAccessor.IPv6Addresses()[p_u32AddressIndex] - : IPAddress()); -} -#endif - -/* - * clsLEAMDNSHost_Legacy::hasAnswerPort - * - */ -bool clsLEAMDNSHost_Legacy::hasAnswerPort(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).hostPortAvailable(); -} - -/* - * clsLEAMDNSHost_Legacy::answerPort - * - */ -uint16_t clsLEAMDNSHost_Legacy::answerPort(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.hostPortAvailable() - ? answerAccessor.hostPort() - : 0); -} - -/* - * clsLEAMDNSHost_Legacy::hasAnswerTxts - * - */ -bool clsLEAMDNSHost_Legacy::hasAnswerTxts(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).txtsAvailable(); -} - -/* - * clsLEAMDNSHost_Legacy::answerHostDomain - * - * Get the TXT items as a ';'-separated string - */ -const char* clsLEAMDNSHost_Legacy::answerTxts(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.txtsAvailable() - ? answerAccessor.txts() - : 0); -} - - -/* - * - * HOST/SERVICE PROBE CALLBACKS - * - */ - -/* - * clsLEAMDNSHost_Legacy::setHostProbeResultCallback - * - */ -bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MDNSHostProbeResultCallbackFn p_fnCallback) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = (*it).m_pHost->setProbeResultCallback([p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, - const char* p_pcDomainName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void(const char* p_pcDomainName, bool p_bProbeResult) - { - p_fnCallback(p_pcDomainName, p_bProbeResult); - } - }); - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::setHostProbeResultCallback - * - */ -bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MDNSHostProbeResultCallbackFn2 p_fnCallback) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = (*it).m_pHost->setProbeResultCallback([this, p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, - const char* p_pcDomainName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcDomainName, bool p_bProbeResult) - { - p_fnCallback(this, p_pcDomainName, p_bProbeResult); - } - }); - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::setServiceProbeResultCallback - * - */ -bool clsLEAMDNSHost_Legacy::setServiceProbeResultCallback(const clsLEAMDNSHost_Legacy::hMDNSService p_hService, - clsLEAMDNSHost_Legacy::MDNSServiceProbeResultCallbackFn p_fnCallback) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - clsLEAMDNSHost::clsService* pService = 0; - bResult = ( ((pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService])) - && (pService->setProbeResultCallback([this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, - const char* p_pcInstanceName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void(const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) - { - p_fnCallback(p_pcInstanceName, p_hService, p_bProbeResult); - } - }))); - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::setServiceProbeResultCallback - * - */ -bool clsLEAMDNSHost_Legacy::setServiceProbeResultCallback(const clsLEAMDNSHost_Legacy::hMDNSService p_hService, - clsLEAMDNSHost_Legacy::MDNSServiceProbeResultCallbackFn2 p_fnCallback) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - clsLEAMDNSHost::clsService* pService = 0; - bResult = ( ((pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService])) - && (pService->setProbeResultCallback([this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, - const char* p_pcInstanceName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void((clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) - { - p_fnCallback(this, p_pcInstanceName, p_hService, p_bProbeResult); - } - }))); - } - return bResult; -} - - -/* - * - * PROCESS - * - */ - -/* - * clsLEAMDNSHost_Legacy::notifyAPChange - * - */ -bool clsLEAMDNSHost_Legacy::notifyAPChange(void) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = (*it).m_pHost->restart(); - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::update - * - */ -bool clsLEAMDNSHost_Legacy::update(void) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = (*it).m_pHost->update(); - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::announce - * - */ -bool clsLEAMDNSHost_Legacy::announce(void) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = (*it).m_pHost->announce(true, true); - } - return bResult; -} - -/* - * clsLEAMDNSHost_Legacy::enableArduino - * - */ -clsLEAMDNSHost_Legacy::hMDNSService clsLEAMDNSHost_Legacy::enableArduino(uint16_t p_u16Port, - bool p_bAuthUpload /*= false*/) -{ - hMDNSService hService = addService(0, "arduino", "tcp", p_u16Port); - if (hService) - { - if ( (!addServiceTxt(hService, "tcp_check", "no")) - || (!addServiceTxt(hService, "ssh_upload", "no")) - || (!addServiceTxt(hService, "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD))) - || (!addServiceTxt(hService, "auth_upload", (p_bAuthUpload) ? "yes" : "no"))) - { - removeService(hService); - hService = 0; - } - } - return hService; -} - -/* - * clsLEAMDNSHost_Legacy::indexDomain - * - */ -bool clsLEAMDNSHost_Legacy::indexDomain(char*& p_rpcDomain, - const char* p_pcDivider /*= "-"*/, - const char* p_pcDefaultDomain /*= 0*/) -{ - bool bResult = false; - - const char* cpcDomainName = clsLEAMDNSHost::indexDomainName(p_rpcDomain, p_pcDivider, p_pcDefaultDomain); - delete[] p_rpcDomain; - p_rpcDomain = 0; - if ( (cpcDomainName) - && ((p_rpcDomain = new char[strlen(cpcDomainName) + 1]))) - { - strcpy(p_rpcDomain, cpcDomainName); - bResult = true; - } - return bResult; -} - - -/* - * - * INTERNAL HELPERS - * - */ - -/* - * clsLEAMDNSHost_Legacy::_addServiceTxt (char*) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bDynamic) -{ - hMDNSTxt hResult = 0; - - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsService* pService = 0; - clsLEAMDNSHost::clsServiceTxt* pTxt = 0; - if ( ((pService = (clsLEAMDNSHost::clsService*)hostInformation.m_HandleToPtr[p_hService])) - && ((pTxt = (p_bDynamic - ? pService->addDynamicServiceTxt(p_pcKey, p_pcValue) - : pService->addServiceTxt(p_pcKey, p_pcValue))))) - { - if (!hResult) - { - hResult = (hMDNSTxt)pTxt; - } - hostInformation.m_HandleToPtr[hResult] = pTxt; - } - } - return hResult; -} - -/* - * clsLEAMDNSHost_Legacy::_addServiceTxt (uint32_t) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value, - bool p_bDynamic) -{ - char acValueBuffer[16]; // 32-bit max 10 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%u", p_u32Value); - - return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); -} - -/* - * clsLEAMDNSHost_Legacy::_addServiceTxt (uint16_t) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value, - bool p_bDynamic) -{ - char acValueBuffer[8]; // 16-bit max 5 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%hu", p_u16Value); - - return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); -} - -/* - * clsLEAMDNSHost_Legacy::_addServiceTxt (uint8_t) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value, - bool p_bDynamic) -{ - char acValueBuffer[8]; // 8-bit max 3 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%hhu", p_u8Value); - - return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); -} - -/* - * clsLEAMDNSHost_Legacy::_addServiceTxt (int32_t) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value, - bool p_bDynamic) -{ - char acValueBuffer[16]; // 32-bit max 11 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%i", p_i32Value); - - return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); -} - -/* - * clsLEAMDNSHost_Legacy::_addServiceTxt (int16_t) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value, - bool p_bDynamic) -{ - char acValueBuffer[8]; // 16-bit max 6 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%hi", p_i16Value); - - return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); -} - -/* - * clsLEAMDNSHost_Legacy::_addServiceTxt (int8_t) - * - */ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value, - bool p_bDynamic) -{ - char acValueBuffer[8]; // 8-bit max 4 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%hhi", p_i8Value); - - return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); -} - -/* - * clsLEAMDNSHost_Legacy::_answerFlagsToAnswerType - * - */ -clsLEAMDNSHost_Legacy::AnswerType clsLEAMDNSHost_Legacy::_answerFlagsToAnswerType(clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags) const -{ - AnswerType answerType = AnswerType::Unknown; - - if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Unknown) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::Unknown; - } - else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::ServiceDomain; - } - else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomain) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::HostDomainAndPort; - } - else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Port) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::HostDomainAndPort; - } - else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::Txt; - } -#ifdef MDNS_IP4_SUPPORT - else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::IP4Address; - } -#endif -#ifdef MDNS_IP6_SUPPORT - else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::IP6Address; - } -#endif - return answerType; -} - -/* - * clsLEAMDNSHost_Legacy::_getAnswerAccessor - * - */ -clsLEAMDNSHost_Legacy::clsLEAMDNSHost::clsQuery::clsAnswerAccessor clsLEAMDNSHost_Legacy::_getAnswerAccessor(const uint32_t p_u32AnswerIndex) -{ - uint32_t u32AnswerIndexWithoutOffset = p_u32AnswerIndex; - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsQuery* pQuery = hostInformation.m_pHost->getQuery(); - if (pQuery) - { - if (pQuery->answerCount() > u32AnswerIndexWithoutOffset) - { - return pQuery->answerAccessor(u32AnswerIndexWithoutOffset); - } - else - { - u32AnswerIndexWithoutOffset -= pQuery->answerCount(); - } - } - else - { - break; - } - } - return clsLEAMDNSHost::clsQuery::clsAnswerAccessor(0); -} - -/* - * clsLEAMDNSHost_Legacy::_getAnswerAccessor - * - */ -clsLEAMDNSHost_Legacy::clsLEAMDNSHost::clsQuery::clsAnswerAccessor clsLEAMDNSHost_Legacy::_getAnswerAccessor(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - uint32_t u32AnswerIndexWithoutOffset = p_u32AnswerIndex; - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; - if (pQuery) - { - if (pQuery->answerCount() > u32AnswerIndexWithoutOffset) - { - return pQuery->answerAccessor(u32AnswerIndexWithoutOffset); - } - else - { - u32AnswerIndexWithoutOffset -= pQuery->answerCount(); - } - } - else - { - break; - } - } - return clsLEAMDNSHost::clsQuery::clsAnswerAccessor(0); -} - - -} // namespace MDNSImplementation - - -} // namespace esp8266 - - - - - - +/* + LEAmDNS2_Legacy.cpp + + +*/ + +#include "LEAmDNS2_Legacy.h" + + +namespace esp8266 +{ + +/** + LEAmDNS +*/ +namespace MDNSImplementation +{ + +/** + STRINGIZE +*/ +#ifndef STRINGIZE +#define STRINGIZE(x) #x +#endif +#ifndef STRINGIZE_VALUE_OF +#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) +#endif + + +/* + clsLEAMDNSHost_Legacy::clsLEAMDNSHost_Legacy constructor + +*/ +clsLEAMDNSHost_Legacy::clsLEAMDNSHost_Legacy(void) +{ +} + +/* + clsLEAMDNSHost_Legacy::clsLEAMDNSHost_Legacy destructor + +*/ +clsLEAMDNSHost_Legacy::~clsLEAMDNSHost_Legacy(void) +{ +} + +/* + + HOST SETUP + +*/ + +/* + clsLEAMDNSHost_Legacy::begin + +*/ +bool clsLEAMDNSHost_Legacy::begin(const char* p_pcHostname) +{ + bool bResult = (((!(WIFI_STA & (WiFiMode_t)wifi_get_opmode())) + || (addHostForNetIf(p_pcHostname, netif_get_by_index(WIFI_STA)))) + && ((!(WIFI_AP & (WiFiMode_t)wifi_get_opmode())) + || (addHostForNetIf(p_pcHostname, netif_get_by_index(WIFI_AP))))); + return ((bResult) + && (0 != m_HostInformations.size())); +} + +/* + clsLEAMDNSHost_Legacy::begin (String) + +*/ +bool clsLEAMDNSHost_Legacy::begin(const String& p_strHostname) +{ + return begin(p_strHostname.c_str()); +} + +/* + clsLEAMDNSHost_Legacy::begin (Ignored Options) + +*/ +bool clsLEAMDNSHost_Legacy::begin(const char* p_pcHostname, + IPAddress /*p_IPAddress = INADDR_ANY*/, // ignored + uint32_t /*p_u32TTL = 120*/) // ignored +{ + return begin(p_pcHostname); +} + +/* + clsLEAMDNSHost_Legacy::begin (String & Ignored Options) + +*/ +bool clsLEAMDNSHost_Legacy::begin(const String& p_strHostname, + IPAddress /*p_IPAddress = INADDR_ANY*/, // ignored + uint32_t /*p_u32TTL = 120*/) // ignored +{ + return begin(p_strHostname.c_str()); +} + +/* + clsLEAMDNSHost_Legacy::close + +*/ +bool clsLEAMDNSHost_Legacy::close(void) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + if ((bResult = (*it).m_pHost->close())) + { + delete (*it).m_pHost; + (*it).m_pHost = 0; + } + } + return ((bResult) + && (m_HostInformations.clear(), true)); +} + +/* + clsLEAMDNSHost_Legacy::end + +*/ +bool clsLEAMDNSHost_Legacy::end(void) +{ + return close(); +} + +/* + clsLEAMDNSHost_Legacy::addHostForNetIf + + NEW! + +*/ +bool clsLEAMDNSHost_Legacy::addHostForNetIf(const char* p_pcHostname, + netif* p_pNetIf) +{ + clsLEAMDNSHost* pHost = 0; + + if (((pHost = new esp8266::experimental::clsLEAMDNSHost)) + && (!((pHost->begin(p_pcHostname, p_pNetIf /*, default callback*/)) + && (m_HostInformations.push_back(stcHostInformation(pHost)), true)))) + { + delete pHost; + pHost = 0; + } + return (0 != pHost); +} + +/* + clsLEAMDNSHost_Legacy::setHostname + +*/ +bool clsLEAMDNSHost_Legacy::setHostname(const char* p_pcHostname) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->setHostName(p_pcHostname); + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::setHostname + +*/ +bool clsLEAMDNSHost_Legacy::setHostname(String p_strHostname) +{ + return setHostname(p_strHostname.c_str()); +} + +/* + clsLEAMDNSHost_Legacy::hostname + +*/ +const char* clsLEAMDNSHost_Legacy::hostname(void) const +{ + return (m_HostInformations.empty() + ? 0 + : m_HostInformations.front().m_pHost->hostName()); +} + +/* + clsLEAMDNSHost_Legacy::status + +*/ +bool clsLEAMDNSHost_Legacy::status(void) const +{ + bool bStatus = true; + + for (const stcHostInformation& hostInformation : m_HostInformations) + { + if (!((bStatus = hostInformation.m_pHost->probeStatus()))) + { + break; + } + } + return bStatus; +} + + +/* + + SERVICE MANAGEMENT + +*/ + +/* + clsLEAMDNSHost_Legacy::addService + +*/ +clsLEAMDNSHost_Legacy::hMDNSService clsLEAMDNSHost_Legacy::addService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + uint16_t p_u16Port) +{ + hMDNSService hResult = 0; + + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsService* pService = hostInformation.m_pHost->addService(p_pcName, p_pcService, p_pcProtocol, p_u16Port /*, default callback*/); + if (pService) + { + if (!hResult) + { + // Store first service handle as result and key + hResult = (hMDNSService)pService; + } + hostInformation.m_HandleToPtr[hResult] = pService; + } + } + return hResult; +} + +/* + clsLEAMDNSHost_Legacy::addService (String) + +*/ +bool clsLEAMDNSHost_Legacy::addService(String p_strServiceName, + String p_strProtocol, + uint16_t p_u16Port) +{ + return (0 != addService(0, p_strServiceName.c_str(), p_strProtocol.c_str(), p_u16Port)); +} + +/* + clsLEAMDNSHost_Legacy::removeService (hService) + +*/ +bool clsLEAMDNSHost_Legacy::removeService(const hMDNSService p_hService) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; + if ((bResult = ((pService) + && ((*it).m_pHost->removeService(pService))))) + { + (*it).m_HandleToPtr.erase(p_hService); + } + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::removeService (name) + +*/ +bool clsLEAMDNSHost_Legacy::removeService(const char* p_pcInstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol) +{ + hMDNSService hService = 0; + return (((hService = (m_HostInformations.empty() + ? 0 + : (hMDNSService)m_HostInformations.front().m_pHost->findService(p_pcInstanceName, p_pcServiceName, p_pcProtocol)))) + && (removeService(hService))); +} + +/* + clsLEAMDNSHost_Legacy::setServiceName + +*/ +bool clsLEAMDNSHost_Legacy::setServiceName(const hMDNSService p_hService, + const char* p_pcInstanceName) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; + bResult = ((pService) + && (pService->setInstanceName(p_pcInstanceName))); + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::setInstanceName + +*/ +void clsLEAMDNSHost_Legacy::setInstanceName(const char* p_pcInstanceName) +{ + for (stcHostInformation& hostInformation : m_HostInformations) + { + hostInformation.m_pHost->setDefaultInstanceName(p_pcInstanceName); + } +} + +/* + clsLEAMDNSHost_Legacy::setInstanceName (String) + +*/ +void clsLEAMDNSHost_Legacy::setInstanceName(const String& p_strHostname) +{ + setInstanceName(p_strHostname.c_str()); +} + +/* + clsLEAMDNSHost_Legacy::serviceName + +*/ +const char* clsLEAMDNSHost_Legacy::serviceName(const hMDNSService p_hService) const +{ + const clsLEAMDNSHost::clsService* pService = 0; + return (m_HostInformations.empty() + ? 0 + : (((pService = (const clsLEAMDNSHost::clsService*)(m_HostInformations.front().m_HandleToPtr.at(p_hService)))) + ? pService->instanceName() + : 0)); +} + +/* + clsLEAMDNSHost_Legacy::service + +*/ +const char* clsLEAMDNSHost_Legacy::service(const hMDNSService p_hService) const +{ + const clsLEAMDNSHost::clsService* pService = 0; + return (m_HostInformations.empty() + ? 0 + : (((pService = (const clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr.at(p_hService))) + ? pService->type() + : 0)); +} + +/* + clsLEAMDNSHost_Legacy::serviceProtocol + +*/ +const char* clsLEAMDNSHost_Legacy::serviceProtocol(const hMDNSService p_hService) const +{ + const clsLEAMDNSHost::clsService* pService = 0; + return (m_HostInformations.empty() + ? 0 + : (((pService = (const clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr.at(p_hService))) + ? pService->protocol() + : 0)); +} + +/* + clsLEAMDNSHost_Legacy::serviceStatus + +*/ +bool clsLEAMDNSHost_Legacy::serviceStatus(const hMDNSService p_hService) const +{ + const clsLEAMDNSHost::clsService* pService = 0; + return (m_HostInformations.empty() + ? false + : (((pService = (const clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr.at(p_hService))) + ? pService->probeStatus() + : false)); +} + + +/* + + SERVICE TXT MANAGEMENT + +*/ + +/* + clsLEAMDNSHost_Legacy::addServiceTxt (char*) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + const char* p_pcValue) +{ + return _addServiceTxt(p_hService, p_pcKey, p_pcValue, false); +} + +/* + clsLEAMDNSHost_Legacy::addServiceTxt (uint32_t) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint32_t p_u32Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_u32Value, false); +} + +/* + clsLEAMDNSHost_Legacy::addServiceTxt (uint16_t) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint16_t p_u16Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_u16Value, false); +} + +/* + clsLEAMDNSHost_Legacy::addServiceTxt (uint8_t) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint8_t p_u8Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_u8Value, false); +} + +/* + clsLEAMDNSHost_Legacy::addServiceTxt (int32_t) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int32_t p_i32Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_i32Value, false); +} + +/* + clsLEAMDNSHost_Legacy::addServiceTxt (int16_t) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int16_t p_i16Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_i16Value, false); +} + +/* + clsLEAMDNSHost_Legacy::addServiceTxt (int8_t) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int8_t p_i8Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_i8Value, false); +} + +/* + clsLEAMDNSHost_Legacy::addServiceTxt (legacy) + +*/ +bool clsLEAMDNSHost_Legacy::addServiceTxt(const char* p_pcService, + const char* p_pcProtocol, + const char* p_pcKey, + const char* p_pcValue) +{ + hMDNSService hService = 0; + return (((hService = (m_HostInformations.empty() + ? 0 + : (hMDNSService)m_HostInformations.front().m_pHost->findService(0, p_pcService, p_pcProtocol)))) + && (_addServiceTxt(hService, p_pcKey, p_pcValue, false))); +} + +/* + clsLEAMDNSHost_Legacy::addServiceTxt (legacy, String) + +*/ +bool clsLEAMDNSHost_Legacy::addServiceTxt(String p_strService, + String p_strProtocol, + String p_strKey, + String p_strValue) +{ + return addServiceTxt(p_strService.c_str(), p_strProtocol.c_str(), p_strKey.c_str(), p_strValue.c_str()); +} + +/* + clsLEAMDNSHost_Legacy::removeServiceTxt (hTxt) + +*/ +bool clsLEAMDNSHost_Legacy::removeServiceTxt(const hMDNSService p_hService, + const hMDNSTxt p_hTxt) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; + clsLEAMDNSHost::clsServiceTxt* pTxt = (clsLEAMDNSHost::clsServiceTxt*)(*it).m_HandleToPtr[p_hTxt]; + if ((bResult = ((pService) + && (pTxt) + && (pService->removeServiceTxt(pTxt))))) + { + (*it).m_HandleToPtr.erase(p_hTxt); + } + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::removeServiceTxt (char*) + +*/ +bool clsLEAMDNSHost_Legacy::removeServiceTxt(const hMDNSService p_hService, + const char* p_pcKey) +{ + clsLEAMDNSHost::clsService* pService = 0; + clsLEAMDNSHost::clsServiceTxt* pTxt = 0; + return (((pService = (m_HostInformations.empty() + ? 0 + : (clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr[p_hService]))) + && ((pTxt = pService->findServiceTxt(p_pcKey))) + && (removeServiceTxt(p_hService, (const hMDNSTxt)pTxt))); +} + +/* + clsLEAMDNSHost_Legacy::removeServiceTxt (char*) + +*/ +bool clsLEAMDNSHost_Legacy::removeServiceTxt(const char* p_pcInstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol, + const char* p_pcKey) +{ + hMDNSService hService = 0; + return (((hService = (m_HostInformations.empty() + ? 0 + : (hMDNSService)m_HostInformations.front().m_pHost->findService(p_pcInstanceName, p_pcServiceName, p_pcProtocol)))) + && (removeServiceTxt(hService, p_pcKey))); +} + +/* + clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback (global) + +*/ +bool clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFn p_fnCallback) +{ + bool bResult = true; + + if ((bResult = m_HostInformations.empty())) + { + // The service handles of the first host are the keys in the HostInformations.HandleToPtr map + for (const clsLEAMDNSHost::clsService* pService : m_HostInformations.front().m_pHost->services()) + { + if (!((bResult = setDynamicServiceTxtCallback((hMDNSService)pService, p_fnCallback)))) + { + break; + } + } + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback (service) + +*/ +bool clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback(const hMDNSService p_hService, + MDNSDynamicServiceTxtCallbackFn p_fnCallback) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; + bResult = pService->setDynamicServiceTxtCallback([p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/)->void + { + if (p_fnCallback) // void(const hMDNSService p_hService) + { + p_fnCallback(p_hService); + } + }); + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::addDynamicServiceTxt (char*) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + const char* p_pcValue) +{ + return _addServiceTxt(p_hService, p_pcKey, p_pcValue, true); +} + +/* + clsLEAMDNSHost_Legacy::addDynamicServiceTxt (uint32) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint32_t p_u32Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_u32Value, true); +} + +/* + clsLEAMDNSHost_Legacy::addDynamicServiceTxt (uint16) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint16_t p_u16Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_u16Value, true); +} + +/* + clsLEAMDNSHost_Legacy::addDynamicServiceTxt (uint8) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint8_t p_u8Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_u8Value, true); +} + +/* + clsLEAMDNSHost_Legacy::addDynamicServiceTxt (int32) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int32_t p_i32Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_i32Value, true); +} + +/* + clsLEAMDNSHost_Legacy::addDynamicServiceTxt (int16) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int16_t p_i16Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_i16Value, true); +} + +/* + clsLEAMDNSHost_Legacy::addDynamicServiceTxt (int8) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int8_t p_i8Value) +{ + return _addServiceTxt(p_hService, p_pcKey, p_i8Value, true); +} + + +/* + + STATIC QUERY + +*/ + +/* + clsLEAMDNSHost_Legacy::queryService + + This will take p_u16Timeout millisec for every host! + +*/ +uint32_t clsLEAMDNSHost_Legacy::queryService(const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) +{ + uint32_t u32Answers = 0; + + for (stcHostInformation& hostInformation : m_HostInformations) + { + u32Answers += (hostInformation.m_pHost->queryService(p_pcService, p_pcProtocol, p_u16Timeout)).size(); + } + return u32Answers; +} + +/* + clsLEAMDNSHost_Legacy::removeQuery + +*/ +bool clsLEAMDNSHost_Legacy::removeQuery(void) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->removeQuery(); + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::queryService + +*/ +uint32_t clsLEAMDNSHost_Legacy::queryService(String p_strService, + String p_strProtocol) +{ + return queryService(p_strService.c_str(), p_strProtocol.c_str()); +} + +/* + clsLEAMDNSHost_Legacy::answerHostname + +*/ +const char* clsLEAMDNSHost_Legacy::answerHostname(const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_u32AnswerIndex); + return (answerAccessor.serviceDomainAvailable() + ? answerAccessor.serviceDomain() + : 0); +} + +/* + clsLEAMDNSHost_Legacy::answerIP + +*/ +IPAddress clsLEAMDNSHost_Legacy::answerIP(const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_u32AnswerIndex); + return (answerAccessor.IPv4AddressAvailable() + ? answerAccessor.IPv4Addresses()[0] + : IPAddress()); +} + +/* + clsLEAMDNSHost_Legacy::answerPort + +*/ +uint16_t clsLEAMDNSHost_Legacy::answerPort(const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_u32AnswerIndex); + return (answerAccessor.hostPortAvailable() + ? answerAccessor.hostPort() + : 0); +} + +/* + clsLEAMDNSHost_Legacy::hostname + +*/ +String clsLEAMDNSHost_Legacy::hostname(const uint32_t p_u32AnswerIndex) +{ + return String(answerHostname(p_u32AnswerIndex)); +} + +/* + clsLEAMDNSHost_Legacy::IP + +*/ +IPAddress clsLEAMDNSHost_Legacy::IP(const uint32_t p_u32AnswerIndex) +{ + return answerIP(p_u32AnswerIndex); +} + +/* + clsLEAMDNSHost_Legacy::port + +*/ +uint16_t clsLEAMDNSHost_Legacy::port(const uint32_t p_u32AnswerIndex) +{ + return answerPort(p_u32AnswerIndex); +} + + +/* + + DYNAMIC QUERY + +*/ + +/* + clsLEAMDNSHost_Legacy::installServiceQuery + +*/ +clsLEAMDNSHost_Legacy::hMDNSServiceQuery clsLEAMDNSHost_Legacy::installServiceQuery(const char* p_pcService, + const char* p_pcProtocol, + MDNSServiceQueryCallbackFn p_fnCallback) +{ + hMDNSServiceQuery hResult = 0; + + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsQuery* pQuery = hostInformation.m_pHost->installServiceQuery(p_pcService, p_pcProtocol, [this, p_fnCallback](const clsLEAMDNSHost::clsQuery& /*p_Query*/, + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor & p_AnswerAccessor, + clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)->void + { + if (p_fnCallback) // void(const stcMDNSServiceInfo& p_MDNSServiceInfo, MDNSResponder::AnswerType p_AnswerType, bool p_bSetContent) + { + p_fnCallback(stcMDNSServiceInfo(p_AnswerAccessor), _answerFlagsToAnswerType(p_QueryAnswerTypeFlags), p_bSetContent); + } + }); + if (pQuery) + { + if (!hResult) + { + // Store first query as result and key + hResult = (hMDNSServiceQuery)pQuery; + } + hostInformation.m_HandleToPtr[hResult] = pQuery; + } + } + return hResult; +} + +/* + clsLEAMDNSHost_Legacy::removeServiceQuery + +*/ +bool clsLEAMDNSHost_Legacy::removeServiceQuery(clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + if ((bResult = (*it).m_pHost->removeQuery((clsLEAMDNSHost::clsQuery*)(*it).m_HandleToPtr[p_hServiceQuery]))) + { + (*it).m_HandleToPtr.erase(p_hServiceQuery); + } + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::answerCount + +*/ +uint32_t clsLEAMDNSHost_Legacy::answerCount(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery) +{ + uint32_t u32AnswerCount = 0; + + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; + if (pQuery) + { + u32AnswerCount += pQuery->answerCount(); + } + else + { + u32AnswerCount = 0; + break; + } + } + return u32AnswerCount; +} + +/* + clsLEAMDNSHost_Legacy::answerInfo + +*/ +std::vector<clsLEAMDNSHost_Legacy::stcMDNSServiceInfo> clsLEAMDNSHost_Legacy::answerInfo(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery) +{ + std::vector<stcMDNSServiceInfo> serviceInfos; + + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; + if (pQuery) + { + for (clsLEAMDNSHost::clsQuery::clsAnswerAccessor& answerAccessor : pQuery->answerAccessors()) + { + serviceInfos.push_back(stcMDNSServiceInfo(answerAccessor)); + } + } + else + { + serviceInfos.clear(); + break; + } + } + return serviceInfos; +} + +/* + clsLEAMDNSHost_Legacy::answerServiceDomain + +*/ +const char* clsLEAMDNSHost_Legacy::answerServiceDomain(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.serviceDomainAvailable() + ? answerAccessor.serviceDomain() + : 0); +} + +/* + clsLEAMDNSHost_Legacy::hasAnswerHostDomain + +*/ +bool clsLEAMDNSHost_Legacy::hasAnswerHostDomain(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).hostDomainAvailable(); +} + +/* + clsLEAMDNSHost_Legacy::answerHostDomain + +*/ +const char* clsLEAMDNSHost_Legacy::answerHostDomain(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.hostDomainAvailable() + ? answerAccessor.hostDomain() + : 0); +} + +#ifdef MDNS_IP4_SUPPORT +/* + clsLEAMDNSHost_Legacy::hasAnswerIP4Address + +*/ +bool clsLEAMDNSHost_Legacy::hasAnswerIP4Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).IPv4AddressAvailable(); +} + +/* + clsLEAMDNSHost_Legacy::answerIP4AddressCount + +*/ +uint32_t clsLEAMDNSHost_Legacy::answerIP4AddressCount(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.IPv4AddressAvailable() + ? answerAccessor.IPv4Addresses().size() + : 0); +} + +/* + clsLEAMDNSHost_Legacy::answerIP4Address + +*/ +IPAddress clsLEAMDNSHost_Legacy::answerIP4Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.IPv4AddressAvailable() + ? answerAccessor.IPv4Addresses()[p_u32AddressIndex] + : IPAddress()); +} +#endif +#ifdef MDNS_IP6_SUPPORT +/* + clsLEAMDNSHost_Legacy::hasAnswerIP6Address + +*/ +bool clsLEAMDNSHost_Legacy::hasAnswerIP6Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).IPv6AddressAvailable(); +} + +/* + clsLEAMDNSHost_Legacy::answerIP6AddressCount + +*/ +uint32_t clsLEAMDNSHost_Legacy::answerIP6AddressCount(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.IPv6AddressAvailable() + ? answerAccessor.IPv6Addresses().size() + : 0); +} + +/* + clsLEAMDNSHost_Legacy::answerIP6Address + +*/ +IPAddress clsLEAMDNSHost_Legacy::answerIP6Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.IPv6AddressAvailable() + ? answerAccessor.IPv6Addresses()[p_u32AddressIndex] + : IPAddress()); +} +#endif + +/* + clsLEAMDNSHost_Legacy::hasAnswerPort + +*/ +bool clsLEAMDNSHost_Legacy::hasAnswerPort(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).hostPortAvailable(); +} + +/* + clsLEAMDNSHost_Legacy::answerPort + +*/ +uint16_t clsLEAMDNSHost_Legacy::answerPort(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.hostPortAvailable() + ? answerAccessor.hostPort() + : 0); +} + +/* + clsLEAMDNSHost_Legacy::hasAnswerTxts + +*/ +bool clsLEAMDNSHost_Legacy::hasAnswerTxts(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).txtsAvailable(); +} + +/* + clsLEAMDNSHost_Legacy::answerHostDomain + + Get the TXT items as a ';'-separated string +*/ +const char* clsLEAMDNSHost_Legacy::answerTxts(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); + return (answerAccessor.txtsAvailable() + ? answerAccessor.txts() + : 0); +} + + +/* + + HOST/SERVICE PROBE CALLBACKS + +*/ + +/* + clsLEAMDNSHost_Legacy::setHostProbeResultCallback + +*/ +bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MDNSHostProbeResultCallbackFn p_fnCallback) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->setProbeResultCallback([p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, + const char* p_pcDomainName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void(const char* p_pcDomainName, bool p_bProbeResult) + { + p_fnCallback(p_pcDomainName, p_bProbeResult); + } + }); + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::setHostProbeResultCallback + +*/ +bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MDNSHostProbeResultCallbackFn2 p_fnCallback) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->setProbeResultCallback([this, p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, + const char* p_pcDomainName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcDomainName, bool p_bProbeResult) + { + p_fnCallback(this, p_pcDomainName, p_bProbeResult); + } + }); + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::setServiceProbeResultCallback + +*/ +bool clsLEAMDNSHost_Legacy::setServiceProbeResultCallback(const clsLEAMDNSHost_Legacy::hMDNSService p_hService, + clsLEAMDNSHost_Legacy::MDNSServiceProbeResultCallbackFn p_fnCallback) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + clsLEAMDNSHost::clsService* pService = 0; + bResult = (((pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService])) + && (pService->setProbeResultCallback([this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, + const char* p_pcInstanceName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void(const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) + { + p_fnCallback(p_pcInstanceName, p_hService, p_bProbeResult); + } + }))); + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::setServiceProbeResultCallback + +*/ +bool clsLEAMDNSHost_Legacy::setServiceProbeResultCallback(const clsLEAMDNSHost_Legacy::hMDNSService p_hService, + clsLEAMDNSHost_Legacy::MDNSServiceProbeResultCallbackFn2 p_fnCallback) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + clsLEAMDNSHost::clsService* pService = 0; + bResult = (((pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService])) + && (pService->setProbeResultCallback([this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, + const char* p_pcInstanceName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void((clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) + { + p_fnCallback(this, p_pcInstanceName, p_hService, p_bProbeResult); + } + }))); + } + return bResult; +} + + +/* + + PROCESS + +*/ + +/* + clsLEAMDNSHost_Legacy::notifyAPChange + +*/ +bool clsLEAMDNSHost_Legacy::notifyAPChange(void) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->restart(); + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::update + +*/ +bool clsLEAMDNSHost_Legacy::update(void) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->update(); + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::announce + +*/ +bool clsLEAMDNSHost_Legacy::announce(void) +{ + bool bResult = true; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) + { + bResult = (*it).m_pHost->announce(true, true); + } + return bResult; +} + +/* + clsLEAMDNSHost_Legacy::enableArduino + +*/ +clsLEAMDNSHost_Legacy::hMDNSService clsLEAMDNSHost_Legacy::enableArduino(uint16_t p_u16Port, + bool p_bAuthUpload /*= false*/) +{ + hMDNSService hService = addService(0, "arduino", "tcp", p_u16Port); + if (hService) + { + if ((!addServiceTxt(hService, "tcp_check", "no")) + || (!addServiceTxt(hService, "ssh_upload", "no")) + || (!addServiceTxt(hService, "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD))) + || (!addServiceTxt(hService, "auth_upload", (p_bAuthUpload) ? "yes" : "no"))) + { + removeService(hService); + hService = 0; + } + } + return hService; +} + +/* + clsLEAMDNSHost_Legacy::indexDomain + +*/ +bool clsLEAMDNSHost_Legacy::indexDomain(char*& p_rpcDomain, + const char* p_pcDivider /*= "-"*/, + const char* p_pcDefaultDomain /*= 0*/) +{ + bool bResult = false; + + const char* cpcDomainName = clsLEAMDNSHost::indexDomainName(p_rpcDomain, p_pcDivider, p_pcDefaultDomain); + delete[] p_rpcDomain; + p_rpcDomain = 0; + if ((cpcDomainName) + && ((p_rpcDomain = new char[strlen(cpcDomainName) + 1]))) + { + strcpy(p_rpcDomain, cpcDomainName); + bResult = true; + } + return bResult; +} + + +/* + + INTERNAL HELPERS + +*/ + +/* + clsLEAMDNSHost_Legacy::_addServiceTxt (char*) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bDynamic) +{ + hMDNSTxt hResult = 0; + + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsService* pService = 0; + clsLEAMDNSHost::clsServiceTxt* pTxt = 0; + if (((pService = (clsLEAMDNSHost::clsService*)hostInformation.m_HandleToPtr[p_hService])) + && ((pTxt = (p_bDynamic + ? pService->addDynamicServiceTxt(p_pcKey, p_pcValue) + : pService->addServiceTxt(p_pcKey, p_pcValue))))) + { + if (!hResult) + { + hResult = (hMDNSTxt)pTxt; + } + hostInformation.m_HandleToPtr[hResult] = pTxt; + } + } + return hResult; +} + +/* + clsLEAMDNSHost_Legacy::_addServiceTxt (uint32_t) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint32_t p_u32Value, + bool p_bDynamic) +{ + char acValueBuffer[16]; // 32-bit max 10 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%u", p_u32Value); + + return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); +} + +/* + clsLEAMDNSHost_Legacy::_addServiceTxt (uint16_t) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint16_t p_u16Value, + bool p_bDynamic) +{ + char acValueBuffer[8]; // 16-bit max 5 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%hu", p_u16Value); + + return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); +} + +/* + clsLEAMDNSHost_Legacy::_addServiceTxt (uint8_t) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint8_t p_u8Value, + bool p_bDynamic) +{ + char acValueBuffer[8]; // 8-bit max 3 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%hhu", p_u8Value); + + return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); +} + +/* + clsLEAMDNSHost_Legacy::_addServiceTxt (int32_t) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int32_t p_i32Value, + bool p_bDynamic) +{ + char acValueBuffer[16]; // 32-bit max 11 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%i", p_i32Value); + + return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); +} + +/* + clsLEAMDNSHost_Legacy::_addServiceTxt (int16_t) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int16_t p_i16Value, + bool p_bDynamic) +{ + char acValueBuffer[8]; // 16-bit max 6 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%hi", p_i16Value); + + return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); +} + +/* + clsLEAMDNSHost_Legacy::_addServiceTxt (int8_t) + +*/ +clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int8_t p_i8Value, + bool p_bDynamic) +{ + char acValueBuffer[8]; // 8-bit max 4 digits + *acValueBuffer = 0; + sprintf(acValueBuffer, "%hhi", p_i8Value); + + return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); +} + +/* + clsLEAMDNSHost_Legacy::_answerFlagsToAnswerType + +*/ +clsLEAMDNSHost_Legacy::AnswerType clsLEAMDNSHost_Legacy::_answerFlagsToAnswerType(clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags) const +{ + AnswerType answerType = AnswerType::Unknown; + + if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Unknown) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::Unknown; + } + else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::ServiceDomain; + } + else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomain) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::HostDomainAndPort; + } + else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Port) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::HostDomainAndPort; + } + else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::Txt; + } +#ifdef MDNS_IP4_SUPPORT + else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::IP4Address; + } +#endif +#ifdef MDNS_IP6_SUPPORT + else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address) & p_QueryAnswerTypeFlags) + { + answerType = AnswerType::IP6Address; + } +#endif + return answerType; +} + +/* + clsLEAMDNSHost_Legacy::_getAnswerAccessor + +*/ +clsLEAMDNSHost_Legacy::clsLEAMDNSHost::clsQuery::clsAnswerAccessor clsLEAMDNSHost_Legacy::_getAnswerAccessor(const uint32_t p_u32AnswerIndex) +{ + uint32_t u32AnswerIndexWithoutOffset = p_u32AnswerIndex; + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsQuery* pQuery = hostInformation.m_pHost->getQuery(); + if (pQuery) + { + if (pQuery->answerCount() > u32AnswerIndexWithoutOffset) + { + return pQuery->answerAccessor(u32AnswerIndexWithoutOffset); + } + else + { + u32AnswerIndexWithoutOffset -= pQuery->answerCount(); + } + } + else + { + break; + } + } + return clsLEAMDNSHost::clsQuery::clsAnswerAccessor(0); +} + +/* + clsLEAMDNSHost_Legacy::_getAnswerAccessor + +*/ +clsLEAMDNSHost_Legacy::clsLEAMDNSHost::clsQuery::clsAnswerAccessor clsLEAMDNSHost_Legacy::_getAnswerAccessor(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + uint32_t u32AnswerIndexWithoutOffset = p_u32AnswerIndex; + for (stcHostInformation& hostInformation : m_HostInformations) + { + clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; + if (pQuery) + { + if (pQuery->answerCount() > u32AnswerIndexWithoutOffset) + { + return pQuery->answerAccessor(u32AnswerIndexWithoutOffset); + } + else + { + u32AnswerIndexWithoutOffset -= pQuery->answerCount(); + } + } + else + { + break; + } + } + return clsLEAMDNSHost::clsQuery::clsAnswerAccessor(0); +} + + +} // namespace MDNSImplementation + + +} // namespace esp8266 + + + + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h index 3b37dd5451..be4a731216 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h @@ -1,679 +1,698 @@ -/* - * LEAmDNS2_Legacy.h - * (c) 2020, LaborEtArs - * - * Version 0.9 beta - * - * Some notes (from LaborEtArs, 2018): - * Essentially, this is an rewrite of the original EPS8266 Multicast DNS code (ESP8266mDNS). - * The target of this rewrite was to keep the existing interface as stable as possible while - * adding and extending the supported set of mDNS features. - * A lot of the additions were basicly taken from Erik Ekman's lwIP mdns app code. - * - * Supported mDNS features (in some cases somewhat limited): - * - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service - * - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented - * - Probing host and service domains for uniqueness in the local network - * - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak) - * - Announcing available services after successful probing - * - Using fixed service TXT items or - * - Using dynamic service TXT items for presented services (via callback) - * - Remove services (and un-announcing them to the observers by sending goodbye-messages) - * - Static queries for DNS-SD services (creating a fixed answer set after a certain timeout period) - * - Dynamic queries for DNS-SD services with cached and updated answers and user notifications - * - * - * Usage: - * In most cases, this implementation should work as a 'drop-in' replacement for the original - * ESP8266 Multicast DNS code. Adjustments to the existing code would only be needed, if some - * of the new features should be used. - * - * For presenting services: - * In 'setup()': - * Install a callback for the probing of host (and service) domains via 'MDNS.setProbeResultCallback(probeResultCallback, &userData);' - * Register DNS-SD services with 'clsLEAMDNSHost_Legacy::hMDNSService hService = MDNS.addService("MyESP", "http", "tcp", 5000);' - * (Install additional callbacks for the probing of these service domains via 'MDNS.setServiceProbeResultCallback(hService, probeResultCallback, &userData);') - * Add service TXT items with 'MDNS.addServiceTxt(hService, "c#", "1");' or by installing a service TXT callback - * using 'MDNS.setDynamicServiceTxtCallback(dynamicServiceTxtCallback, &userData);' or service specific - * 'MDNS.setDynamicServiceTxtCallback(hService, dynamicServiceTxtCallback, &userData);' - * Call MDNS.begin("MyHostname"); - * - * In 'probeResultCallback(clsLEAMDNSHost_Legacy* p_MDNSResponder, const char* p_pcDomain, clsLEAMDNSHost_Legacy:hMDNSService p_hService, bool p_bProbeResult, void* p_pUserdata)': - * Check the probe result and update the host or service domain name if the probe failed - * - * In 'dynamicServiceTxtCallback(clsLEAMDNSHost_Legacy* p_MDNSResponder, const hMDNSService p_hService, void* p_pUserdata)': - * Add dynamic TXT items by calling 'MDNS.addDynamicServiceTxt(p_hService, "c#", "1");' - * - * In loop(): - * Call 'MDNS.update();' - * - * - * For querying services: - * Static: - * Call 'uint32_t u32AnswerCount = MDNS.queryService("http", "tcp");' - * Iterate answers by: 'for (uint32_t u=0; u<u32AnswerCount; ++u) { const char* pHostname = MDNS.answerHostname(u); }' - * You should call MDNS.removeQuery() sometimes later (when the answers are nott needed anymore) - * - * Dynamic: - * Install a dynamic query by calling 'DNSResponder::hMDNSServiceQuery hServiceQuery = MDNS.installServiceQuery("http", "tcp", serviceQueryCallback, &userData);' - * The callback 'serviceQueryCallback(clsLEAMDNSHost_Legacy* p_MDNSResponder, const hMDNSServiceQuery p_hServiceQuery, uint32_t p_u32AnswerIndex, - * enuServiceQueryAnswerType p_ServiceQueryAnswerType, bool p_bSetContent, void* p_pUserdata)' - * is called for any change in the answer set. - * Call 'MDNS.removeServiceQuery(hServiceQuery);' when the answers are not needed anymore - * - * - * Reference: - * Used mDNS messages: - * A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 - * AAAA (0x1C): eg. esp8266.local AAAA OP TTL 1234:5678::90 - * PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local - * PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local - * PTR (0x0C, IP4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local - * PTR (0x0C, IP6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local - * SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local - * TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 - * NSEC (0x2F): eg. esp8266.local ... (DNSSEC) - * - * Some NOT used message types: - * OPT (0x29): eDNS - * - * - * License (MIT license): - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -#ifndef __LEAMDNS2HOST_LEGACY_H__ -#define __LEAMDNS2HOST_LEGACY_H__ - -#include "LEAmDNS2Host.h" - - -namespace esp8266 -{ - -namespace MDNSImplementation -{ - -/** - * clsLEAMDNSHost_Legacy - */ -class clsLEAMDNSHost_Legacy -{ - using clsLEAMDNSHost = esp8266::experimental::clsLEAMDNSHost; - - /** - clsConsts - */ - class clsConsts - { - public: - static const uint16_t u16StaticQueryWaitTime = 1000; // Default wait time for query responses - }; - -public: - /* INTERFACE */ - clsLEAMDNSHost_Legacy(void); - virtual ~clsLEAMDNSHost_Legacy(void); - - // Start the MDNS responder by setting the default hostname - // Later call MDNS::update() in every 'loop' to run the process loop - // (probing, announcing, responding, ...) - bool begin(const char* p_pcHostname); - bool begin(const String& p_strHostname); - // for compatibility - bool begin(const char* p_pcHostname, - IPAddress p_IPAddress /*= INADDR_ANY*/, // ignored - uint32_t p_u32TTL /*= 120*/); // ignored - bool begin(const String& p_strHostname, - IPAddress p_IPAddress /*= INADDR_ANY*/, // ignored - uint32_t p_u32TTL /*= 120*/); // ignored - // Finish MDNS processing - bool close(void); - // for ESP32 compatibility - bool end(void); - // NEW! The ESP-default network interfaces are 'auto-added' via 'begin' when active - // Additional netifs may be added, but if done so after calling 'update' for the - // first time, 'notifyAPChange' should be called to restart the probing/announcing process - bool addHostForNetIf(const char* p_pcHostname, - netif* p_pNetIf); - - // Change hostname (probing is restarted) - // Caution! The final hostname (after probing) may be different for every host - bool setHostname(const char* p_pcHostname); - // for compatibility... - bool setHostname(String p_strHostname); - - const char* hostname(void) const; - - bool status(void) const; - - /** - * hMDNSService (opaque handle to access the service) - */ - typedef const void* hMDNSService; - - // Add a new service to the MDNS responder. If no name (instance name) is given (p_pcName = 0) - // the current hostname is used. If the hostname is changed later, the instance names for - // these 'auto-named' services are changed to the new name also (and probing is restarted). - // The usual '_' before p_pcService (eg. http) and protocol (eg. tcp) may be given. - hMDNSService addService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port); - // Removes a service from the MDNS responder - bool removeService(const hMDNSService p_hService); - bool removeService(const char* p_pcInstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol); - // for compatibility... - bool addService(String p_strServiceName, - String p_strProtocol, - uint16_t p_u16Port); - - - // Change the services instance name (and restart probing). - bool setServiceName(const hMDNSService p_hService, - const char* p_pcInstanceName); - //for compatibility - void setInstanceName(const char* p_pcHostname); - - // for ESP32 compatibility - void setInstanceName(const String& p_strHostname); - - const char* serviceName(const hMDNSService p_hService) const; - const char* service(const hMDNSService p_hService) const; - const char* serviceProtocol(const hMDNSService p_hService) const; - - bool serviceStatus(const hMDNSService p_hService) const; - - /** - * hMDNSTxt (opaque handle to access the TXT items) - */ - typedef void* hMDNSTxt; - - // 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); - - // Remove an existing (static) MDNS TXT item from the service - bool removeServiceTxt(const hMDNSService p_hService, - const hMDNSTxt p_hTxt); - bool removeServiceTxt(const hMDNSService p_hService, - const char* p_pcKey); - bool removeServiceTxt(const char* p_pcinstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol, - const char* p_pcKey); - // for compatibility... - bool addServiceTxt(const char* p_pcService, - const char* p_pcProtocol, - const char* p_pcKey, - const char* p_pcValue); - bool addServiceTxt(String p_strService, - String p_strProtocol, - String p_strKey, - String p_strValue); - - /** - * MDNSDynamicServiceTxtCallbackFn - * Callback function for dynamic MDNS TXT items - */ - typedef std::function<void(const hMDNSService p_hService)> MDNSDynamicServiceTxtCallbackFn; - - // Set a global callback for dynamic MDNS TXT items. The callback function is called - // every time, a TXT item is needed for one of the installed services. - bool setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFn p_fnCallback); - - // Set a service specific callback for dynamic MDNS TXT items. The callback function - // is called every time, a TXT item is needed for the given service. - bool setDynamicServiceTxtCallback(const hMDNSService p_hService, - MDNSDynamicServiceTxtCallbackFn p_fnCallback); - - // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service - // Dynamic TXT items are removed right after one-time use. So they need to be added - // every time the value s needed (via callback). - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value); - - // Perform a (static) service query. The function returns after p_u16Timeout milliseconds - // The answers (the number of received answers is returned) can be retrieved by calling - // - answerHostname (or hostname) - // - answerIP (or IP) - // - answerPort (or port) - uint32_t queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout = clsConsts::u16StaticQueryWaitTime); - bool removeQuery(void); - // for compatibility... - uint32_t queryService(String p_strService, - String p_strProtocol); - - const char* answerHostname(const uint32_t p_u32AnswerIndex); - IPAddress answerIP(const uint32_t p_u32AnswerIndex); - uint16_t answerPort(const uint32_t p_u32AnswerIndex); - // for compatibility... - String hostname(const uint32_t p_u32AnswerIndex); - IPAddress IP(const uint32_t p_u32AnswerIndex); - uint16_t port(const uint32_t p_u32AnswerIndex); - - /** - * hMDNSServiceQuery (opaque handle to access dynamic service queries) - */ - typedef const void* hMDNSServiceQuery; - - /** - * enuServiceQueryAnswerType - */ - typedef enum _enuServiceQueryAnswerType { - ServiceQueryAnswerType_Unknown = 0, - ServiceQueryAnswerType_ServiceDomain = (1 << 0), // Service instance name - ServiceQueryAnswerType_HostDomainAndPort = (1 << 1), // Host domain and service port - ServiceQueryAnswerType_Txts = (1 << 2), // TXT items -#ifdef MDNS_IP4_SUPPORT - ServiceQueryAnswerType_IP4Address = (1 << 3), // IP4 address -#endif -#ifdef MDNS_IP6_SUPPORT - ServiceQueryAnswerType_IP6Address = (1 << 4), // IP6 address -#endif - } enuServiceQueryAnswerType; - - /** - * AnswerType (std::map compatible version) - */ - enum class AnswerType : uint32_t { - Unknown = ServiceQueryAnswerType_Unknown, - ServiceDomain = ServiceQueryAnswerType_ServiceDomain, - HostDomainAndPort = ServiceQueryAnswerType_HostDomainAndPort, - Txt = ServiceQueryAnswerType_Txts, -#ifdef MDNS_IP4_SUPPORT - IP4Address = ServiceQueryAnswerType_IP4Address, -#endif -#ifdef MDNS_IP6_SUPPORT - IP6Address = ServiceQueryAnswerType_IP6Address -#endif - }; - - /** - * stcMDNSServiceInfo - */ - struct stcMDNSServiceInfo { - stcMDNSServiceInfo(const clsLEAMDNSHost::clsQuery::clsAnswerAccessor& p_rAnswerAccessor) - : m_rAnswerAccessor(p_rAnswerAccessor) {}; - /** - * stcCompareKey - */ - struct stcCompareKey { - /* - * operator () - */ - bool operator()(char const* p_pA, char const* p_pB) const { - return (0 > strcmp(p_pA, p_pB)); - } - }; - /** - * clsKeyValueMap - */ - using clsKeyValueMap = std::map<const char*, const char*, stcCompareKey>; - - protected: - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor& m_rAnswerAccessor; - clsKeyValueMap m_KeyValueMap; - - public: - /* - * serviceDomain - */ - const char* serviceDomain(void) const { - return (m_rAnswerAccessor.serviceDomainAvailable() - ? m_rAnswerAccessor.serviceDomain() - : nullptr); - } - /* - * hostDomainAvailable - */ - bool hostDomainAvailable(void) const { - return m_rAnswerAccessor.serviceDomainAvailable(); - } - /* - * hostDomain - */ - const char* hostDomain(void) const { - return (hostDomainAvailable() - ? m_rAnswerAccessor.hostDomain() - : nullptr); - } - /* - * hostPortAvailable - */ - bool hostPortAvailable(void) const { - return m_rAnswerAccessor.hostPortAvailable(); - } - /* - * hostPort - */ - uint16_t hostPort(void) const { - return (hostPortAvailable() - ? m_rAnswerAccessor.hostPort() - : 0); - } -#ifdef MDNS_IP4_SUPPORT - /* - * IP4AddressAvailable - */ - bool IP4AddressAvailable(void) const { - return m_rAnswerAccessor.IPv4AddressAvailable(); - } - /* - * IP4Addresses - */ - std::vector<IPAddress> IP4Adresses(void) const { - return (IP4AddressAvailable() - ? m_rAnswerAccessor.IPv4Addresses() - : std::vector<IPAddress>()); - } -#endif -#ifdef MDNS_IP6_SUPPORT - /* - * IP6AddressAvailable - */ - bool IP6AddressAvailable(void) const { - return m_rAnswerAccessor.IPv6AddressAvailable(); - } - /* - * IP6Addresses - */ - std::vector<IPAddress> IP6Adresses(void) const { - return (IP6AddressAvailable() - ? m_rAnswerAccessor.IPv6Addresses() - : std::vector<IPAddress>()); - } -#endif - /* - * txtAvailable - */ - bool txtAvailable(void) const { - return m_rAnswerAccessor.txtsAvailable(); - } - /* - * strKeyValue -> abc=def;hij=klm; - */ - const char* strKeyValue (void) const { - // TODO - return nullptr; - } - /* - * keyValues -> abc=def hij=klm ... - */ - const clsKeyValueMap& keyValues(void) { - if ((txtAvailable()) && - (0 == m_KeyValueMap.size())) { - for (auto kv : m_rAnswerAccessor.txtKeyValues()) - { - m_KeyValueMap.emplace(std::pair<const char*,const char*>(kv.first, kv.second)); - } - //for (auto kv=m_rMDNSResponder._answerKeyValue(m_hServiceQuery, m_u32AnswerIndex); kv!=nullptr; kv=kv->m_pNext) { - // m_KeyValueMap.emplace(std::pair<const char*,const char*>(kv->m_pcKey, kv->m_pcValue)); - //} - } - return m_KeyValueMap; - } - /* - * value (abc)->def - */ - const char* value(const char* p_pcKey) const { - return m_rAnswerAccessor.txtValue(p_pcKey); - } - }; - - /** - * MDNSServiceQueryCallbackFn - * - * Callback function for received answers for dynamic service queries - */ - typedef std::function<void(const stcMDNSServiceInfo& p_MDNSServiceInfo, - AnswerType p_AnswerType, // flags for the updated answer item - bool p_bSetContent // true: Answer component set, false: component deleted - )> MDNSServiceQueryCallbackFn; - - // Install a dynamic service query. For every received answer (part) the given callback - // function is called. The query will be updated every time, the TTL for an answer - // has timed-out. - // The answers can also be retrieved by calling - // - answerCount - // - answerServiceDomain - // - hasAnswerHostDomain/answerHostDomain - // - hasAnswerIP4Address/answerIP4Address - // - hasAnswerIP6Address/answerIP6Address - // - hasAnswerPort/answerPort - // - hasAnswerTxts/answerTxts - hMDNSServiceQuery installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - MDNSServiceQueryCallbackFn p_fnCallback); - // Remove a dynamic service query - bool removeServiceQuery(hMDNSServiceQuery p_hServiceQuery); - - uint32_t answerCount(const hMDNSServiceQuery p_hServiceQuery); - std::vector<stcMDNSServiceInfo> answerInfo(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery); - const char* answerServiceDomain(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerHostDomain(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - const char* answerHostDomain(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); -#ifdef MDNS_IP4_SUPPORT - bool hasAnswerIP4Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIP4AddressCount(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIP4Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); -#endif -#ifdef MDNS_IP6_SUPPORT - bool hasAnswerIP6Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIP6AddressCount(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIP6Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); -#endif - bool hasAnswerPort(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - uint16_t answerPort(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerTxts(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - // Get the TXT items as a ';'-separated string - const char* answerTxts(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - - /** - * MDNSHostProbeResultCallbackFn/2 - * Callback function for host domain probe results - */ - typedef std::function<void(const char* p_pcDomainName, - bool p_bProbeResult)> MDNSHostProbeResultCallbackFn; - - typedef std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, - const char* p_pcDomainName, - bool p_bProbeResult)> MDNSHostProbeResultCallbackFn2; - - // Set a callback function for host probe results - // The callback function is called, when the probeing for the host domain - // succeededs or fails. - // In case of failure, the failed domain name should be changed. - bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn p_fnCallback); - bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn2 p_fnCallback); - - /** - * MDNSServiceProbeResultCallbackFn/2 - * Callback function for service domain probe results - */ - typedef std::function<void(const char* p_pcServiceName, - const hMDNSService p_hMDNSService, - bool p_bProbeResult)> MDNSServiceProbeResultCallbackFn; - - typedef std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, - const char* p_pcServiceName, - const hMDNSService p_hMDNSService, - bool p_bProbeResult)> MDNSServiceProbeResultCallbackFn2; - - // Set a service specific probe result callcack - bool setServiceProbeResultCallback(const hMDNSService p_hService, - MDNSServiceProbeResultCallbackFn p_fnCallback); - bool setServiceProbeResultCallback(const hMDNSService p_hService, - MDNSServiceProbeResultCallbackFn2 p_fnCallback); - - // Application should call this whenever AP is configured/disabled - bool notifyAPChange(void); - - // 'update' should be called in every 'loop' to run the MDNS processing - bool update(void); - - // 'announce' can be called every time, the configuration of some service - // changes. Mainly, this would be changed content of TXT items. - bool announce(void); - - // Enable OTA update - hMDNSService enableArduino(uint16_t p_u16Port, - bool p_bAuthUpload = false); - - // Domain name helper - static bool indexDomain(char*& p_rpcDomain, - const char* p_pcDivider = "-", - const char* p_pcDefaultDomain = 0); - -protected: - /** - * stcHostInformation - */ - struct stcHostInformation - { - /** - * clsHandleToPtrMap - */ - using clsHandleToPtrMap = std::map<const void*, const void*>; - - clsLEAMDNSHost* m_pHost; - clsHandleToPtrMap m_HandleToPtr; - - stcHostInformation(clsLEAMDNSHost* p_pHost) - : m_pHost(p_pHost) - {} - - /** - * list - */ - using list = std::list<stcHostInformation>; - }; - - stcHostInformation::list m_HostInformations; - - // HELPERS - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bDynamic); - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value, - bool p_bDynamic); - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value, - bool p_bDynamic); - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value, - bool p_bDynamic); - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value, - bool p_bDynamic); - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value, - bool p_bDynamic); - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value, - bool p_bDynamic); - - AnswerType _answerFlagsToAnswerType(clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags) const; - - clsLEAMDNSHost::clsQuery::clsAnswerAccessor _getAnswerAccessor(const uint32_t p_u32AnswerIndex); - clsLEAMDNSHost::clsQuery::clsAnswerAccessor _getAnswerAccessor(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - -}; - - -} // namespace MDNSImplementation - - -} // namespace esp8266 - - -#endif // __LEAMDNS2HOST_LEGACY_H__ - - - - - - +/* + LEAmDNS2_Legacy.h + (c) 2020, LaborEtArs + + Version 0.9 beta + + Some notes (from LaborEtArs, 2018): + Essentially, this is an rewrite of the original EPS8266 Multicast DNS code (ESP8266mDNS). + The target of this rewrite was to keep the existing interface as stable as possible while + adding and extending the supported set of mDNS features. + A lot of the additions were basicly taken from Erik Ekman's lwIP mdns app code. + + Supported mDNS features (in some cases somewhat limited): + - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service + - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented + - Probing host and service domains for uniqueness in the local network + - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak) + - Announcing available services after successful probing + - Using fixed service TXT items or + - Using dynamic service TXT items for presented services (via callback) + - Remove services (and un-announcing them to the observers by sending goodbye-messages) + - Static queries for DNS-SD services (creating a fixed answer set after a certain timeout period) + - Dynamic queries for DNS-SD services with cached and updated answers and user notifications + + + Usage: + In most cases, this implementation should work as a 'drop-in' replacement for the original + ESP8266 Multicast DNS code. Adjustments to the existing code would only be needed, if some + of the new features should be used. + + For presenting services: + In 'setup()': + Install a callback for the probing of host (and service) domains via 'MDNS.setProbeResultCallback(probeResultCallback, &userData);' + Register DNS-SD services with 'clsLEAMDNSHost_Legacy::hMDNSService hService = MDNS.addService("MyESP", "http", "tcp", 5000);' + (Install additional callbacks for the probing of these service domains via 'MDNS.setServiceProbeResultCallback(hService, probeResultCallback, &userData);') + Add service TXT items with 'MDNS.addServiceTxt(hService, "c#", "1");' or by installing a service TXT callback + using 'MDNS.setDynamicServiceTxtCallback(dynamicServiceTxtCallback, &userData);' or service specific + 'MDNS.setDynamicServiceTxtCallback(hService, dynamicServiceTxtCallback, &userData);' + Call MDNS.begin("MyHostname"); + + In 'probeResultCallback(clsLEAMDNSHost_Legacy* p_MDNSResponder, const char* p_pcDomain, clsLEAMDNSHost_Legacy:hMDNSService p_hService, bool p_bProbeResult, void* p_pUserdata)': + Check the probe result and update the host or service domain name if the probe failed + + In 'dynamicServiceTxtCallback(clsLEAMDNSHost_Legacy* p_MDNSResponder, const hMDNSService p_hService, void* p_pUserdata)': + Add dynamic TXT items by calling 'MDNS.addDynamicServiceTxt(p_hService, "c#", "1");' + + In loop(): + Call 'MDNS.update();' + + + For querying services: + Static: + Call 'uint32_t u32AnswerCount = MDNS.queryService("http", "tcp");' + Iterate answers by: 'for (uint32_t u=0; u<u32AnswerCount; ++u) { const char* pHostname = MDNS.answerHostname(u); }' + You should call MDNS.removeQuery() sometimes later (when the answers are nott needed anymore) + + Dynamic: + Install a dynamic query by calling 'DNSResponder::hMDNSServiceQuery hServiceQuery = MDNS.installServiceQuery("http", "tcp", serviceQueryCallback, &userData);' + The callback 'serviceQueryCallback(clsLEAMDNSHost_Legacy* p_MDNSResponder, const hMDNSServiceQuery p_hServiceQuery, uint32_t p_u32AnswerIndex, + enuServiceQueryAnswerType p_ServiceQueryAnswerType, bool p_bSetContent, void* p_pUserdata)' + is called for any change in the answer set. + Call 'MDNS.removeServiceQuery(hServiceQuery);' when the answers are not needed anymore + + + Reference: + Used mDNS messages: + A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 + AAAA (0x1C): eg. esp8266.local AAAA OP TTL 1234:5678::90 + PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local + PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local + PTR (0x0C, IP4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local + PTR (0x0C, IP6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local + SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local + TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 + NSEC (0x2F): eg. esp8266.local ... (DNSSEC) + + Some NOT used message types: + OPT (0x29): eDNS + + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#ifndef __LEAMDNS2HOST_LEGACY_H__ +#define __LEAMDNS2HOST_LEGACY_H__ + +#include "LEAmDNS2Host.h" + + +namespace esp8266 +{ + +namespace MDNSImplementation +{ + +/** + clsLEAMDNSHost_Legacy +*/ +class clsLEAMDNSHost_Legacy +{ + using clsLEAMDNSHost = esp8266::experimental::clsLEAMDNSHost; + + /** + clsConsts + */ + class clsConsts + { + public: + static const uint16_t u16StaticQueryWaitTime = 1000; // Default wait time for query responses + }; + +public: + /* INTERFACE */ + clsLEAMDNSHost_Legacy(void); + virtual ~clsLEAMDNSHost_Legacy(void); + + // Start the MDNS responder by setting the default hostname + // Later call MDNS::update() in every 'loop' to run the process loop + // (probing, announcing, responding, ...) + bool begin(const char* p_pcHostname); + bool begin(const String& p_strHostname); + // for compatibility + bool begin(const char* p_pcHostname, + IPAddress p_IPAddress /*= INADDR_ANY*/, // ignored + uint32_t p_u32TTL /*= 120*/); // ignored + bool begin(const String& p_strHostname, + IPAddress p_IPAddress /*= INADDR_ANY*/, // ignored + uint32_t p_u32TTL /*= 120*/); // ignored + // Finish MDNS processing + bool close(void); + // for ESP32 compatibility + bool end(void); + // NEW! The ESP-default network interfaces are 'auto-added' via 'begin' when active + // Additional netifs may be added, but if done so after calling 'update' for the + // first time, 'notifyAPChange' should be called to restart the probing/announcing process + bool addHostForNetIf(const char* p_pcHostname, + netif* p_pNetIf); + + // Change hostname (probing is restarted) + // Caution! The final hostname (after probing) may be different for every host + bool setHostname(const char* p_pcHostname); + // for compatibility... + bool setHostname(String p_strHostname); + + const char* hostname(void) const; + + bool status(void) const; + + /** + hMDNSService (opaque handle to access the service) + */ + typedef const void* hMDNSService; + + // Add a new service to the MDNS responder. If no name (instance name) is given (p_pcName = 0) + // the current hostname is used. If the hostname is changed later, the instance names for + // these 'auto-named' services are changed to the new name also (and probing is restarted). + // The usual '_' before p_pcService (eg. http) and protocol (eg. tcp) may be given. + hMDNSService addService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + uint16_t p_u16Port); + // Removes a service from the MDNS responder + bool removeService(const hMDNSService p_hService); + bool removeService(const char* p_pcInstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol); + // for compatibility... + bool addService(String p_strServiceName, + String p_strProtocol, + uint16_t p_u16Port); + + + // Change the services instance name (and restart probing). + bool setServiceName(const hMDNSService p_hService, + const char* p_pcInstanceName); + //for compatibility + void setInstanceName(const char* p_pcHostname); + + // for ESP32 compatibility + void setInstanceName(const String& p_strHostname); + + const char* serviceName(const hMDNSService p_hService) const; + const char* service(const hMDNSService p_hService) const; + const char* serviceProtocol(const hMDNSService p_hService) const; + + bool serviceStatus(const hMDNSService p_hService) const; + + /** + hMDNSTxt (opaque handle to access the TXT items) + */ + typedef void* hMDNSTxt; + + // 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); + + // Remove an existing (static) MDNS TXT item from the service + bool removeServiceTxt(const hMDNSService p_hService, + const hMDNSTxt p_hTxt); + bool removeServiceTxt(const hMDNSService p_hService, + const char* p_pcKey); + bool removeServiceTxt(const char* p_pcinstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol, + const char* p_pcKey); + // for compatibility... + bool addServiceTxt(const char* p_pcService, + const char* p_pcProtocol, + const char* p_pcKey, + const char* p_pcValue); + bool addServiceTxt(String p_strService, + String p_strProtocol, + String p_strKey, + String p_strValue); + + /** + MDNSDynamicServiceTxtCallbackFn + Callback function for dynamic MDNS TXT items + */ + typedef std::function<void(const hMDNSService p_hService)> MDNSDynamicServiceTxtCallbackFn; + + // Set a global callback for dynamic MDNS TXT items. The callback function is called + // every time, a TXT item is needed for one of the installed services. + bool setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFn p_fnCallback); + + // Set a service specific callback for dynamic MDNS TXT items. The callback function + // is called every time, a TXT item is needed for the given service. + bool setDynamicServiceTxtCallback(const hMDNSService p_hService, + MDNSDynamicServiceTxtCallbackFn p_fnCallback); + + // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service + // Dynamic TXT items are removed right after one-time use. So they need to be added + // every time the value s needed (via callback). + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + const char* p_pcValue); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint32_t p_u32Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint16_t p_u16Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint8_t p_u8Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int32_t p_i32Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int16_t p_i16Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int8_t p_i8Value); + + // Perform a (static) service query. The function returns after p_u16Timeout milliseconds + // The answers (the number of received answers is returned) can be retrieved by calling + // - answerHostname (or hostname) + // - answerIP (or IP) + // - answerPort (or port) + uint32_t queryService(const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout = clsConsts::u16StaticQueryWaitTime); + bool removeQuery(void); + // for compatibility... + uint32_t queryService(String p_strService, + String p_strProtocol); + + const char* answerHostname(const uint32_t p_u32AnswerIndex); + IPAddress answerIP(const uint32_t p_u32AnswerIndex); + uint16_t answerPort(const uint32_t p_u32AnswerIndex); + // for compatibility... + String hostname(const uint32_t p_u32AnswerIndex); + IPAddress IP(const uint32_t p_u32AnswerIndex); + uint16_t port(const uint32_t p_u32AnswerIndex); + + /** + hMDNSServiceQuery (opaque handle to access dynamic service queries) + */ + typedef const void* hMDNSServiceQuery; + + /** + enuServiceQueryAnswerType + */ + typedef enum _enuServiceQueryAnswerType + { + ServiceQueryAnswerType_Unknown = 0, + ServiceQueryAnswerType_ServiceDomain = (1 << 0), // Service instance name + ServiceQueryAnswerType_HostDomainAndPort = (1 << 1), // Host domain and service port + ServiceQueryAnswerType_Txts = (1 << 2), // TXT items +#ifdef MDNS_IP4_SUPPORT + ServiceQueryAnswerType_IP4Address = (1 << 3), // IP4 address +#endif +#ifdef MDNS_IP6_SUPPORT + ServiceQueryAnswerType_IP6Address = (1 << 4), // IP6 address +#endif + } enuServiceQueryAnswerType; + + /** + AnswerType (std::map compatible version) + */ + enum class AnswerType : uint32_t + { + Unknown = ServiceQueryAnswerType_Unknown, + ServiceDomain = ServiceQueryAnswerType_ServiceDomain, + HostDomainAndPort = ServiceQueryAnswerType_HostDomainAndPort, + Txt = ServiceQueryAnswerType_Txts, +#ifdef MDNS_IP4_SUPPORT + IP4Address = ServiceQueryAnswerType_IP4Address, +#endif +#ifdef MDNS_IP6_SUPPORT + IP6Address = ServiceQueryAnswerType_IP6Address +#endif + }; + + /** + stcMDNSServiceInfo + */ + struct stcMDNSServiceInfo + { + stcMDNSServiceInfo(const clsLEAMDNSHost::clsQuery::clsAnswerAccessor& p_rAnswerAccessor) + : m_rAnswerAccessor(p_rAnswerAccessor) {}; + /** + stcCompareKey + */ + struct stcCompareKey + { + /* + operator () + */ + bool operator()(char const* p_pA, char const* p_pB) const + { + return (0 > strcmp(p_pA, p_pB)); + } + }; + /** + clsKeyValueMap + */ + using clsKeyValueMap = std::map<const char*, const char*, stcCompareKey>; + + protected: + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor& m_rAnswerAccessor; + clsKeyValueMap m_KeyValueMap; + + public: + /* + serviceDomain + */ + const char* serviceDomain(void) const + { + return (m_rAnswerAccessor.serviceDomainAvailable() + ? m_rAnswerAccessor.serviceDomain() + : nullptr); + } + /* + hostDomainAvailable + */ + bool hostDomainAvailable(void) const + { + return m_rAnswerAccessor.serviceDomainAvailable(); + } + /* + hostDomain + */ + const char* hostDomain(void) const + { + return (hostDomainAvailable() + ? m_rAnswerAccessor.hostDomain() + : nullptr); + } + /* + hostPortAvailable + */ + bool hostPortAvailable(void) const + { + return m_rAnswerAccessor.hostPortAvailable(); + } + /* + hostPort + */ + uint16_t hostPort(void) const + { + return (hostPortAvailable() + ? m_rAnswerAccessor.hostPort() + : 0); + } +#ifdef MDNS_IP4_SUPPORT + /* + IP4AddressAvailable + */ + bool IP4AddressAvailable(void) const + { + return m_rAnswerAccessor.IPv4AddressAvailable(); + } + /* + IP4Addresses + */ + std::vector<IPAddress> IP4Adresses(void) const + { + return (IP4AddressAvailable() + ? m_rAnswerAccessor.IPv4Addresses() + : std::vector<IPAddress>()); + } +#endif +#ifdef MDNS_IP6_SUPPORT + /* + IP6AddressAvailable + */ + bool IP6AddressAvailable(void) const + { + return m_rAnswerAccessor.IPv6AddressAvailable(); + } + /* + IP6Addresses + */ + std::vector<IPAddress> IP6Adresses(void) const + { + return (IP6AddressAvailable() + ? m_rAnswerAccessor.IPv6Addresses() + : std::vector<IPAddress>()); + } +#endif + /* + txtAvailable + */ + bool txtAvailable(void) const + { + return m_rAnswerAccessor.txtsAvailable(); + } + /* + strKeyValue -> abc=def;hij=klm; + */ + const char* strKeyValue(void) const + { + // TODO + return nullptr; + } + /* + keyValues -> abc=def hij=klm ... + */ + const clsKeyValueMap& keyValues(void) + { + if ((txtAvailable()) && + (0 == m_KeyValueMap.size())) + { + for (auto kv : m_rAnswerAccessor.txtKeyValues()) + { + m_KeyValueMap.emplace(std::pair<const char*, const char*>(kv.first, kv.second)); + } + //for (auto kv=m_rMDNSResponder._answerKeyValue(m_hServiceQuery, m_u32AnswerIndex); kv!=nullptr; kv=kv->m_pNext) { + // m_KeyValueMap.emplace(std::pair<const char*,const char*>(kv->m_pcKey, kv->m_pcValue)); + //} + } + return m_KeyValueMap; + } + /* + value (abc)->def + */ + const char* value(const char* p_pcKey) const + { + return m_rAnswerAccessor.txtValue(p_pcKey); + } + }; + + /** + MDNSServiceQueryCallbackFn + + Callback function for received answers for dynamic service queries + */ + typedef std::function<void(const stcMDNSServiceInfo& p_MDNSServiceInfo, + AnswerType p_AnswerType, // flags for the updated answer item + bool p_bSetContent // true: Answer component set, false: component deleted + )> MDNSServiceQueryCallbackFn; + + // Install a dynamic service query. For every received answer (part) the given callback + // function is called. The query will be updated every time, the TTL for an answer + // has timed-out. + // The answers can also be retrieved by calling + // - answerCount + // - answerServiceDomain + // - hasAnswerHostDomain/answerHostDomain + // - hasAnswerIP4Address/answerIP4Address + // - hasAnswerIP6Address/answerIP6Address + // - hasAnswerPort/answerPort + // - hasAnswerTxts/answerTxts + hMDNSServiceQuery installServiceQuery(const char* p_pcService, + const char* p_pcProtocol, + MDNSServiceQueryCallbackFn p_fnCallback); + // Remove a dynamic service query + bool removeServiceQuery(hMDNSServiceQuery p_hServiceQuery); + + uint32_t answerCount(const hMDNSServiceQuery p_hServiceQuery); + std::vector<stcMDNSServiceInfo> answerInfo(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery); + const char* answerServiceDomain(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + bool hasAnswerHostDomain(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + const char* answerHostDomain(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); +#ifdef MDNS_IP4_SUPPORT + bool hasAnswerIP4Address(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + uint32_t answerIP4AddressCount(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + IPAddress answerIP4Address(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex); +#endif +#ifdef MDNS_IP6_SUPPORT + bool hasAnswerIP6Address(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + uint32_t answerIP6AddressCount(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + IPAddress answerIP6Address(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex); +#endif + bool hasAnswerPort(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + uint16_t answerPort(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + bool hasAnswerTxts(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + // Get the TXT items as a ';'-separated string + const char* answerTxts(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + + /** + MDNSHostProbeResultCallbackFn/2 + Callback function for host domain probe results + */ + typedef std::function<void(const char* p_pcDomainName, + bool p_bProbeResult)> MDNSHostProbeResultCallbackFn; + + typedef std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, + const char* p_pcDomainName, + bool p_bProbeResult)> MDNSHostProbeResultCallbackFn2; + + // Set a callback function for host probe results + // The callback function is called, when the probeing for the host domain + // succeededs or fails. + // In case of failure, the failed domain name should be changed. + bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn p_fnCallback); + bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn2 p_fnCallback); + + /** + MDNSServiceProbeResultCallbackFn/2 + Callback function for service domain probe results + */ + typedef std::function<void(const char* p_pcServiceName, + const hMDNSService p_hMDNSService, + bool p_bProbeResult)> MDNSServiceProbeResultCallbackFn; + + typedef std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, + const char* p_pcServiceName, + const hMDNSService p_hMDNSService, + bool p_bProbeResult)> MDNSServiceProbeResultCallbackFn2; + + // Set a service specific probe result callcack + bool setServiceProbeResultCallback(const hMDNSService p_hService, + MDNSServiceProbeResultCallbackFn p_fnCallback); + bool setServiceProbeResultCallback(const hMDNSService p_hService, + MDNSServiceProbeResultCallbackFn2 p_fnCallback); + + // Application should call this whenever AP is configured/disabled + bool notifyAPChange(void); + + // 'update' should be called in every 'loop' to run the MDNS processing + bool update(void); + + // 'announce' can be called every time, the configuration of some service + // changes. Mainly, this would be changed content of TXT items. + bool announce(void); + + // Enable OTA update + hMDNSService enableArduino(uint16_t p_u16Port, + bool p_bAuthUpload = false); + + // Domain name helper + static bool indexDomain(char*& p_rpcDomain, + const char* p_pcDivider = "-", + const char* p_pcDefaultDomain = 0); + +protected: + /** + stcHostInformation + */ + struct stcHostInformation + { + /** + clsHandleToPtrMap + */ + using clsHandleToPtrMap = std::map<const void*, const void*>; + + clsLEAMDNSHost* m_pHost; + clsHandleToPtrMap m_HandleToPtr; + + stcHostInformation(clsLEAMDNSHost* p_pHost) + : m_pHost(p_pHost) + {} + + /** + list + */ + using list = std::list<stcHostInformation>; + }; + + stcHostInformation::list m_HostInformations; + + // HELPERS + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bDynamic); + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint32_t p_u32Value, + bool p_bDynamic); + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint16_t p_u16Value, + bool p_bDynamic); + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + uint8_t p_u8Value, + bool p_bDynamic); + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int32_t p_i32Value, + bool p_bDynamic); + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int16_t p_i16Value, + bool p_bDynamic); + hMDNSTxt _addServiceTxt(const hMDNSService p_hService, + const char* p_pcKey, + int8_t p_i8Value, + bool p_bDynamic); + + AnswerType _answerFlagsToAnswerType(clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags) const; + + clsLEAMDNSHost::clsQuery::clsAnswerAccessor _getAnswerAccessor(const uint32_t p_u32AnswerIndex); + clsLEAMDNSHost::clsQuery::clsAnswerAccessor _getAnswerAccessor(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + +}; + + +} // namespace MDNSImplementation + + +} // namespace esp8266 + + +#endif // __LEAMDNS2HOST_LEGACY_H__ + + + + + + From 1910848a029db8b72994a95dd9b3e298b34741df Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 8 May 2020 15:49:38 +0200 Subject: [PATCH 005/152] two interface example is working (also with IPv6) --- .../{src => OLDmDNS}/ESP8266mDNS_Legacy.cpp | 0 .../{src => OLDmDNS}/ESP8266mDNS_Legacy.h | 0 .../ESP8266mDNS/{src => OLDmDNS}/LEAmDNS.cpp | 0 .../ESP8266mDNS/{src => OLDmDNS}/LEAmDNS.h | 0 .../{src => OLDmDNS}/LEAmDNS_Control.cpp | 0 .../{src => OLDmDNS}/LEAmDNS_Helpers.cpp | 0 .../{src => OLDmDNS}/LEAmDNS_Priv.h | 0 .../{src => OLDmDNS}/LEAmDNS_Structs.cpp | 0 .../{src => OLDmDNS}/LEAmDNS_Transfer.cpp | 0 .../{src => OLDmDNS}/LEAmDNS_lwIPdefs.h | 0 .../LEAmDNS/TwoInterfaces/TwoInterfaces.ino | 24 +++++++++++++------ libraries/ESP8266mDNS/src/ESP8266mDNS.h | 5 ++-- 12 files changed, 20 insertions(+), 9 deletions(-) rename libraries/ESP8266mDNS/{src => OLDmDNS}/ESP8266mDNS_Legacy.cpp (100%) rename libraries/ESP8266mDNS/{src => OLDmDNS}/ESP8266mDNS_Legacy.h (100%) rename libraries/ESP8266mDNS/{src => OLDmDNS}/LEAmDNS.cpp (100%) rename libraries/ESP8266mDNS/{src => OLDmDNS}/LEAmDNS.h (100%) rename libraries/ESP8266mDNS/{src => OLDmDNS}/LEAmDNS_Control.cpp (100%) rename libraries/ESP8266mDNS/{src => OLDmDNS}/LEAmDNS_Helpers.cpp (100%) rename libraries/ESP8266mDNS/{src => OLDmDNS}/LEAmDNS_Priv.h (100%) rename libraries/ESP8266mDNS/{src => OLDmDNS}/LEAmDNS_Structs.cpp (100%) rename libraries/ESP8266mDNS/{src => OLDmDNS}/LEAmDNS_Transfer.cpp (100%) rename libraries/ESP8266mDNS/{src => OLDmDNS}/LEAmDNS_lwIPdefs.h (100%) diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp b/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.cpp similarity index 100% rename from libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp rename to libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.cpp diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h b/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.h similarity index 100% rename from libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h rename to libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.h diff --git a/libraries/ESP8266mDNS/src/LEAmDNS.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.cpp similarity index 100% rename from libraries/ESP8266mDNS/src/LEAmDNS.cpp rename to libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.cpp diff --git a/libraries/ESP8266mDNS/src/LEAmDNS.h b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.h similarity index 100% rename from libraries/ESP8266mDNS/src/LEAmDNS.h rename to libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.h diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Control.cpp similarity index 100% rename from libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp rename to libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Control.cpp diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Helpers.cpp similarity index 100% rename from libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp rename to libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Helpers.cpp diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Priv.h b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Priv.h similarity index 100% rename from libraries/ESP8266mDNS/src/LEAmDNS_Priv.h rename to libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Priv.h diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Structs.cpp similarity index 100% rename from libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp rename to libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Structs.cpp diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Transfer.cpp similarity index 100% rename from libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp rename to libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Transfer.cpp diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_lwIPdefs.h b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_lwIPdefs.h similarity index 100% rename from libraries/ESP8266mDNS/src/LEAmDNS_lwIPdefs.h rename to libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_lwIPdefs.h diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino index 3f06f543b7..4bbdbd157b 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino @@ -5,9 +5,18 @@ #include <ESP8266mDNS.h> #include <ESP8266WebServer.h> - -clsMDNSHost mDNSHost_AP; -clsMDNSHost mDNSHost_STA; +#ifndef STASSID +#define STASSID "ssid" +#define STAPSK "12345678" +#endif + +#ifndef APSSID +#define APSSID "espap" +#define APPSK "12345678" +#endif + +clsMDNSHost mDNSHost_AP; +clsMDNSHost mDNSHost_STA; ESP8266WebServer server(80); void connectToWiFi(const char* p_pcSSID, @@ -43,7 +52,7 @@ void setup(void) { // Setup WiFi and AP WiFi.setAutoConnect(false); WiFi.mode(WIFI_AP_STA); - WiFi.softAP("ESP8266", "12345678"); + WiFi.softAP(APSSID, APPSK); Serial.print("Created AP "); Serial.println("ESP8266"); Serial.print("AP-IP address: "); @@ -62,8 +71,9 @@ void setup(void) { Serial.println("FAILED to start mDNS-AP"); } - // Connect to WiFi network, with WRONG password - connectToWiFi("AP8", "WRONG_PW", 5); + // Connect to WiFi network, with WRONG password (timeout 5 seconds) + // (good password will be given in `loop()`) + connectToWiFi(STASSID, "WRONG_PW", 5); if (mDNSHost_STA.begin("esp8266", WIFI_STA, [](clsMDNSHost & p_rMDNSHost, const char* p_pcDomainName, @@ -125,7 +135,7 @@ void loop(void) { static esp8266::polledTimeout::oneShotMs timer2(esp8266::polledTimeout::oneShotMs::alwaysExpired); if (timer2) { Serial.println("FIX PASSWORD"); - connectToWiFi("AP8", "_______"); + connectToWiFi(STASSID, STAPSK); timer2.reset(esp8266::polledTimeout::oneShotMs::neverExpires); } diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index fdcf489fb0..467367b564 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -42,8 +42,8 @@ */ -#include "ESP8266mDNS_Legacy.h" -#include "LEAmDNS.h" +//#include "ESP8266mDNS_Legacy.h" +//#include "LEAmDNS.h" #include "LEAmDNS2Host.h" @@ -53,6 +53,7 @@ //using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; //new //using MDNSResponder = esp8266::experimental::MDNSResponder; //new^2 not compatible using clsMDNSHost = esp8266::experimental::clsLEAMDNSHost; +using MDNSResponder = esp8266::experimental::clsLEAMDNSHost; //extern MDNSResponder MDNS; #endif From c19266751dc14c6b402f5782157e02f3d1268d5d Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 8 May 2020 18:43:47 +0200 Subject: [PATCH 006/152] restored former versions (legacy, LEAv1), clock example for new API --- .../LEAmDNS/TwoInterfaces/TwoInterfaces.ino | 2 + .../LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 241 ++ libraries/ESP8266mDNS/src/ESP8266mDNS.h | 18 +- .../ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp | 1523 ++++++++++ .../ESP8266mDNS/src/ESP8266mDNS_Legacy.h | 169 ++ libraries/ESP8266mDNS/src/LEAmDNS.cpp | 1382 +++++++++ libraries/ESP8266mDNS/src/LEAmDNS.h | 1464 ++++++++++ libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 1 + libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 12 +- .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 1 + .../ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp | 1 + .../ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 1 + .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 2 +- .../ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 1 + libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 1 + libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp | 2135 ++++++++++++++ libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp | 851 ++++++ libraries/ESP8266mDNS/src/LEAmDNS_Priv.h | 182 ++ libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp | 2477 +++++++++++++++++ .../ESP8266mDNS/src/LEAmDNS_Transfer.cpp | 1780 ++++++++++++ libraries/ESP8266mDNS/src/LEAmDNS_lwIPdefs.h | 44 + 21 files changed, 12274 insertions(+), 14 deletions(-) create mode 100644 libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino create mode 100644 libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp create mode 100644 libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS.cpp create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS.h create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS_Priv.h create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS_lwIPdefs.h diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino index 4bbdbd157b..f561b867f6 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino @@ -15,6 +15,8 @@ #define APPSK "12345678" #endif +// uses API MDNSApiVersion::LEAv2 + clsMDNSHost mDNSHost_AP; clsMDNSHost mDNSHost_STA; ESP8266WebServer server(80); diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino new file mode 100644 index 0000000000..5c429226f4 --- /dev/null +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -0,0 +1,241 @@ +/* + ESP8266 mDNS responder clock + + This example demonstrates two features of the LEA clsMDNSHost: + 1. The host and service domain negotiation process that ensures + the uniqueness of the finally choosen host and service domain name. + 2. The dynamic MDNS service TXT feature + + A 'clock' service in announced via the MDNS responder and the current + time is set as a TXT item (eg. 'curtime=Mon Oct 15 19:54:35 2018'). + The time value is updated every second! + + The ESP is initially announced to clients as 'esp8266.local', if this host domain + is already used in the local network, another host domain is negociated. Keep an + eye to the serial output to learn the final host domain for the clock service. + The service itself is is announced as 'host domain'._espclk._tcp.local. + As the service uses port 80, a very simple HTTP server is installed also to deliver + a small web page containing a greeting and the current time (not updated). + The web server code is taken nearly 1:1 from the 'mDNS_Web_Server.ino' example. + Point your browser to 'host domain'.local to see this web page. + + Instructions: + - Update WiFi SSID and password as necessary. + - Flash the sketch to the ESP8266 board + - Install host software: + - For Linux, install Avahi (http://avahi.org/). + - For Windows, install Bonjour (http://www.apple.com/support/bonjour/). + - For Mac OSX and iOS support is built in through Bonjour already. + - Use a MDNS/Bonjour browser like 'Discovery' to find the clock service in your local + network and see the current time updates. + +*/ + + +#include <ESP8266WiFi.h> +#include <WiFiClient.h> +#include <ESP8266WebServer.h> +#include <time.h> + +// uses API MDNSApiVersion::LEAv2 + +/* + Include the clsMDNSHost (the library needs to be included also) + As LEA clsMDNSHost is experimantal in the ESP8266 environment currently, the + legacy clsMDNSHost is defaulted in th include file. + There are two ways to access LEA clsMDNSHost: + 1. Prepend every declaration and call to global declarations or functions with the namespace, like: + 'LEAmDNS::clsMDNSHost::hMDNSService hMDNSService;' + This way is used in the example. But be careful, if the namespace declaration is missing + somewhere, the call might go to the legacy implementation... + 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. + +*/ +#include <ESP8266mDNS.h> +#include <PolledTimeout.h> +/* + Global defines and vars +*/ + + +#define TIMEZONE_OFFSET 1 // CET +#define DST_OFFSET 1 // CEST +#define UPDATE_CYCLE (1 * 1000) // every second + +#define SERVICE_PORT 80 // HTTP port + +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* ssid = STASSID; +const char* password = STAPSK; + +clsMDNSHost responder; // MDNS responder +bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain +clsMDNSHost::clsService* hMDNSService = 0; // The handle of the clock service in the MDNS responder + +// HTTP server at port 'SERVICE_PORT' will respond to HTTP requests +ESP8266WebServer server(SERVICE_PORT); + +/* + getTimeString +*/ +const char* getTimeString(void) { + + static char acTimeString[32]; + time_t now = time(nullptr); + ctime_r(&now, acTimeString); + size_t stLength; + while (((stLength = strlen(acTimeString))) && + ('\n' == acTimeString[stLength - 1])) { + acTimeString[stLength - 1] = 0; // Remove trailing line break... + } + return acTimeString; +} + + +/* + setClock + + Set time via NTP +*/ +void setClock(void) { + configTime((TIMEZONE_OFFSET * 3600), (DST_OFFSET * 3600), "pool.ntp.org", "time.nist.gov", "time.windows.com"); + + Serial.print("Waiting for NTP time sync: "); + time_t now = time(nullptr); // Secs since 01.01.1970 (when uninitalized starts with (8 * 3600 = 28800) + while (now < 8 * 3600 * 2) { // Wait for realistic value + delay(500); + Serial.print("."); + now = time(nullptr); + } + Serial.println(""); + Serial.printf("Current time: %s\n", getTimeString()); +} + + +/* + setStationHostname +*/ +bool setStationHostname(const char* p_pcHostname) { + + if (p_pcHostname) { + WiFi.hostname(p_pcHostname); + Serial.printf("setDeviceHostname: Station hostname is set to '%s'\n", p_pcHostname); + } + return true; +} + + +/* + MDNSDynamicServiceTxtCallback + + Add a dynamic MDNS TXT item 'ct' to the clock service. + The callback function is called every time, the TXT items for the clock service + are needed. + This can be triggered by calling responder.announce(). + +*/ +void MDNSDynamicServiceTxtCallback(const clsMDNSHost::hMDNSService& p_hService) { + Serial.println("MDNSDynamicServiceTxtCallback"); + + if (hMDNSService == &p_hService) { + Serial.printf("Updating curtime TXT item to: %s\n", getTimeString()); + hMDNSService->addDynamicServiceTxt("curtime", getTimeString()); + } +} + + +/* + handleHTTPClient +*/ + +void handleHTTPRequest() { + Serial.println(""); + Serial.println("HTTP Request"); + + // Get current time + time_t now = time(nullptr);; + struct tm timeinfo; + gmtime_r(&now, &timeinfo); + + String s; + + s = "<!DOCTYPE HTML>\r\n<html>Hello from "; + s += WiFi.hostname() + " at " + WiFi.localIP().toString(); + // Simple addition of the current time + s += "\r\nCurrent time is: "; + s += getTimeString(); + // done :-) + s += "</html>\r\n\r\n"; + Serial.println("Sending 200"); + server.send(200, "text/html", s); +} + +/* + setup +*/ +void setup(void) { + Serial.begin(115200); + + // Connect to WiFi network + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + // Sync clock + setClock(); + + // Setup MDNS responder + // Init the (currently empty) host domain string with 'esp8266' + if (responder.begin("ESP8266", WIFI_STA, [](clsMDNSHost & p_rMDNSHost, + const char* p_pcDomainName, + bool p_bProbeResult)->void { + Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); + // Unattended added service + p_rMDNSHost.addService(0, "http", "tcp", 80); + })) { + Serial.println("mDNS-AP started"); + } else { + Serial.println("FAILED to start mDNS-AP"); + } + + // Setup HTTP server + server.on("/", handleHTTPRequest); + server.begin(); + Serial.println("HTTP server started"); +} + +/* + loop +*/ +void loop(void) { + + // Check if a request has come in + server.handleClient(); + // Allow MDNS processing + responder.update(); + + static esp8266::polledTimeout::periodicMs timeout(UPDATE_CYCLE); + if (timeout.expired()) { + + if (hMDNSService) { + // Just trigger a new MDNS announcement, this will lead to a call to + // 'MDNSDynamicServiceTxtCallback', which will update the time TXT item + responder.announce(); + } + } +} diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index 467367b564..c3713c6689 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -42,19 +42,19 @@ */ -//#include "ESP8266mDNS_Legacy.h" -//#include "LEAmDNS.h" -#include "LEAmDNS2Host.h" +enum class MDNSApiVersion { Legacy, LEA, LEAv2 }; +#include "ESP8266mDNS_Legacy.h" +#include "LEAmDNS.h" +#include "LEAmDNS2Host.h" +using clsMDNSHost = esp8266::experimental::clsLEAMDNSHost; #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) // Maps the implementation to use to the global namespace type -//using MDNSResponder = Legacy_MDNSResponder::MDNSResponder; //legacy -//using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; //new -//using MDNSResponder = esp8266::experimental::MDNSResponder; //new^2 not compatible -using clsMDNSHost = esp8266::experimental::clsLEAMDNSHost; -using MDNSResponder = esp8266::experimental::clsLEAMDNSHost; +//using MDNSResponder = Legacy_MDNSResponder::MDNSResponder; // Legacy +using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA +//using MDNSResponder = clsMDNSHost; // LEAv2 -//extern MDNSResponder MDNS; +extern MDNSResponder MDNS; #endif diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp b/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp new file mode 100644 index 0000000000..8791195523 --- /dev/null +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp @@ -0,0 +1,1523 @@ +/* + + ESP8266 Multicast DNS (port of CC3000 Multicast DNS library) + Version 1.1 + Copyright (c) 2013 Tony DiCola (tony@tonydicola.com) + ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com) + MDNS-SD Suport 2015 Hristo Gochkov + Extended MDNS-SD support 2016 Lars Englund (lars.englund@gmail.com) + + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +// Important RFC's for reference: +// - DNS request and response: http://www.ietf.org/rfc/rfc1035.txt +// - Multicast DNS: http://www.ietf.org/rfc/rfc6762.txt +// - MDNS-SD: https://tools.ietf.org/html/rfc6763 + +#ifndef LWIP_OPEN_SRC +#define LWIP_OPEN_SRC +#endif + +#include "ESP8266mDNS.h" +#include <functional> + +#include "debug.h" + +extern "C" { +#include "osapi.h" +#include "ets_sys.h" +#include "user_interface.h" +} + +#include "WiFiUdp.h" +#include "lwip/opt.h" +#include "lwip/udp.h" +#include "lwip/inet.h" +#include "lwip/igmp.h" +#include "lwip/mem.h" +#include "include/UdpContext.h" + + + +namespace Legacy_MDNSResponder +{ + + +#ifdef DEBUG_ESP_MDNS +#define DEBUG_ESP_MDNS_ERR +#define DEBUG_ESP_MDNS_TX +#define DEBUG_ESP_MDNS_RX +#endif + +#define MDNS_NAME_REF 0xC000 + +#define MDNS_TYPE_AAAA 0x001C +#define MDNS_TYPE_A 0x0001 +#define MDNS_TYPE_PTR 0x000C +#define MDNS_TYPE_SRV 0x0021 +#define MDNS_TYPE_TXT 0x0010 + +#define MDNS_CLASS_IN 0x0001 +#define MDNS_CLASS_IN_FLUSH_CACHE 0x8001 + +#define MDNS_ANSWERS_ALL 0x0F +#define MDNS_ANSWER_PTR 0x08 +#define MDNS_ANSWER_TXT 0x04 +#define MDNS_ANSWER_SRV 0x02 +#define MDNS_ANSWER_A 0x01 + +#define _conn_read32() (((uint32_t)_conn->read() << 24) | ((uint32_t)_conn->read() << 16) | ((uint32_t)_conn->read() << 8) | _conn->read()) +#define _conn_read16() (((uint16_t)_conn->read() << 8) | _conn->read()) +#define _conn_read8() _conn->read() +#define _conn_readS(b,l) _conn->read((char*)(b),l); + +static const IPAddress MDNS_MULTICAST_ADDR(224, 0, 0, 251); +static const int MDNS_MULTICAST_TTL = 1; +static const int MDNS_PORT = 5353; + +struct MDNSService +{ + MDNSService* _next; + char _name[32]; + char _proto[4]; + uint16_t _port; + uint16_t _txtLen; // length of all txts + struct MDNSTxt * _txts; +}; + +struct MDNSTxt +{ + MDNSTxt * _next; + String _txt; +}; + +struct MDNSAnswer +{ + MDNSAnswer* next; + uint8_t ip[4]; + uint16_t port; + char *hostname; +}; + +struct MDNSQuery +{ + char _service[32]; + char _proto[4]; +}; + + +MDNSResponder::MDNSResponder() : _conn(0) +{ + _services = 0; + _instanceName = ""; + _answers = 0; + _query = 0; + _newQuery = false; + _waitingForAnswers = false; +} +MDNSResponder::~MDNSResponder() +{ + if (_query != 0) + { + os_free(_query); + _query = 0; + } + + // Clear answer list + MDNSAnswer *answer; + int numAnswers = _getNumAnswers(); + for (int n = numAnswers - 1; n >= 0; n--) + { + answer = _getAnswerFromIdx(n); + os_free(answer->hostname); + os_free(answer); + answer = 0; + } + _answers = 0; + + if (_conn) + { + _conn->unref(); + } +} + +bool MDNSResponder::begin(const char* hostname) +{ + size_t n = strlen(hostname); + if (n > 63) // max size for a single label. + { + return false; + } + + // Copy in hostname characters as lowercase + _hostName = hostname; + _hostName.toLowerCase(); + + // If instance name is not already set copy hostname to instance name + if (_instanceName.equals("")) + { + _instanceName = hostname; + } + + _gotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP & event) + { + (void) event; + _restart(); + }); + + _disconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected & event) + { + (void) event; + _restart(); + }); + + return _listen(); +} + +void MDNSResponder::notifyAPChange() +{ + _restart(); +} + +void MDNSResponder::_restart() +{ + if (_conn) + { + _conn->unref(); + _conn = nullptr; + } + _listen(); +} + +bool MDNSResponder::_listen() +{ + // Open the MDNS socket if it isn't already open. + if (!_conn) + { +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.println("MDNS listening"); +#endif + + IPAddress mdns(MDNS_MULTICAST_ADDR); + + if (igmp_joingroup(IP4_ADDR_ANY4, mdns) != ERR_OK) + { + return false; + } + + _conn = new UdpContext; + _conn->ref(); + + if (!_conn->listen(IP_ADDR_ANY, MDNS_PORT)) + { + return false; + } + _conn->setMulticastTTL(MDNS_MULTICAST_TTL); + _conn->onRx(std::bind(&MDNSResponder::update, this)); + _conn->connect(mdns, MDNS_PORT); + } + return true; +} + +void MDNSResponder::update() +{ + if (!_conn || !_conn->next()) + { + return; + } + _parsePacket(); +} + + +void MDNSResponder::setInstanceName(String name) +{ + if (name.length() > 63) + { + return; + } + _instanceName = name; +} + + +bool MDNSResponder::addServiceTxt(char *name, char *proto, char *key, char *value) +{ + MDNSService* servicePtr; + + uint8_t txtLen = os_strlen(key) + os_strlen(value) + 1; // Add one for equals sign + txtLen += 1; //accounts for length byte added when building the txt responce + //Find the service + for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) + { + //Checking Service names + if (strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) + { + //found a service name match + if (servicePtr->_txtLen + txtLen > 1300) + { + return false; //max txt record size + } + MDNSTxt *newtxt = new MDNSTxt; + newtxt->_txt = String(key) + '=' + String(value); + newtxt->_next = 0; + if (servicePtr->_txts == 0) //no services have been added + { + //Adding First TXT to service + servicePtr->_txts = newtxt; + servicePtr->_txtLen += txtLen; + return true; + } + else + { + MDNSTxt * txtPtr = servicePtr->_txts; + while (txtPtr->_next != 0) + { + txtPtr = txtPtr->_next; + } + //adding another TXT to service + txtPtr->_next = newtxt; + servicePtr->_txtLen += txtLen; + return true; + } + } + } + return false; +} + +void MDNSResponder::addService(char *name, char *proto, uint16_t port) +{ + if (_getServicePort(name, proto) != 0) + { + return; + } + if (os_strlen(name) > 32 || os_strlen(proto) != 3) + { + return; //bad arguments + } + struct MDNSService *srv = (struct MDNSService*)(os_malloc(sizeof(struct MDNSService))); + os_strcpy(srv->_name, name); + os_strcpy(srv->_proto, proto); + srv->_port = port; + srv->_next = 0; + srv->_txts = 0; + srv->_txtLen = 0; + + if (_services == 0) + { + _services = srv; + } + else + { + MDNSService* servicePtr = _services; + while (servicePtr->_next != 0) + { + servicePtr = servicePtr->_next; + } + servicePtr->_next = srv; + } + +} + +int MDNSResponder::queryService(char *service, char *proto) +{ +#ifdef DEBUG_ESP_MDNS_TX + DEBUG_ESP_PORT.printf("queryService %s %s\n", service, proto); +#endif + while (_answers != 0) + { + MDNSAnswer *currAnswer = _answers; + _answers = _answers->next; + os_free(currAnswer->hostname); + os_free(currAnswer); + currAnswer = 0; + } + if (_query != 0) + { + os_free(_query); + _query = 0; + } + _query = (struct MDNSQuery*)(os_malloc(sizeof(struct MDNSQuery))); + os_strcpy(_query->_service, service); + os_strcpy(_query->_proto, proto); + _newQuery = true; + + char underscore[] = "_"; + + // build service name with _ + char serviceName[os_strlen(service) + 2]; + os_strcpy(serviceName, underscore); + os_strcat(serviceName, service); + size_t serviceNameLen = os_strlen(serviceName); + + //build proto name with _ + char protoName[5]; + os_strcpy(protoName, underscore); + os_strcat(protoName, proto); + size_t protoNameLen = 4; + + //local string + char localName[] = "local"; + size_t localNameLen = 5; + + //terminator + char terminator[] = "\0"; + + // Only supports sending one PTR query + uint8_t questionCount = 1; + + _waitingForAnswers = true; + for (int itfn = 0; itfn < 2; itfn++) + { + struct ip_info ip_info; + + wifi_get_ip_info((!itfn) ? SOFTAP_IF : STATION_IF, &ip_info); + if (!ip_info.ip.addr) + { + continue; + } + _conn->setMulticastInterface(IPAddress(ip_info.ip.addr)); + + // Write the header + _conn->flush(); + uint8_t head[12] = + { + 0x00, 0x00, //ID = 0 + 0x00, 0x00, //Flags = response + authoritative answer + 0x00, questionCount, //Question count + 0x00, 0x00, //Answer count + 0x00, 0x00, //Name server records + 0x00, 0x00 //Additional records + }; + _conn->append(reinterpret_cast<const char*>(head), 12); + + // Only supports sending one PTR query + // Send the Name field (eg. "_http._tcp.local") + _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // lenght of "_" + service + _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_" + service + _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // lenght of "_" + proto + _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_" + proto + _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // lenght of "local" + _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" + _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator + + //Send the type and class + uint8_t ptrAttrs[4] = + { + 0x00, 0x0c, //PTR record query + 0x00, 0x01 //Class IN + }; + _conn->append(reinterpret_cast<const char*>(ptrAttrs), 4); + _conn->send(); + } + +#ifdef DEBUG_ESP_MDNS_TX + DEBUG_ESP_PORT.println("Waiting for answers.."); +#endif + delay(1000); + + _waitingForAnswers = false; + + return _getNumAnswers(); +} + +String MDNSResponder::hostname(int idx) +{ + MDNSAnswer *answer = _getAnswerFromIdx(idx); + if (answer == 0) + { + return String(); + } + return answer->hostname; +} + +IPAddress MDNSResponder::IP(int idx) +{ + MDNSAnswer *answer = _getAnswerFromIdx(idx); + if (answer == 0) + { + return IPAddress(); + } + return IPAddress(answer->ip); +} + +uint16_t MDNSResponder::port(int idx) +{ + MDNSAnswer *answer = _getAnswerFromIdx(idx); + if (answer == 0) + { + return 0; + } + return answer->port; +} + +MDNSAnswer* MDNSResponder::_getAnswerFromIdx(int idx) +{ + MDNSAnswer *answer = _answers; + while (answer != 0 && idx-- > 0) + { + answer = answer->next; + } + if (idx > 0) + { + return 0; + } + return answer; +} + +int MDNSResponder::_getNumAnswers() +{ + int numAnswers = 0; + MDNSAnswer *answer = _answers; + while (answer != 0) + { + numAnswers++; + answer = answer->next; + } + return numAnswers; +} + +MDNSTxt * MDNSResponder::_getServiceTxt(char *name, char *proto) +{ + MDNSService* servicePtr; + for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) + { + if (servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) + { + if (servicePtr->_txts == 0) + { + return nullptr; + } + return servicePtr->_txts; + } + } + return nullptr; +} + +uint16_t MDNSResponder::_getServiceTxtLen(char *name, char *proto) +{ + MDNSService* servicePtr; + for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) + { + if (servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) + { + if (servicePtr->_txts == 0) + { + return false; + } + return servicePtr->_txtLen; + } + } + return 0; +} + +uint16_t MDNSResponder::_getServicePort(char *name, char *proto) +{ + MDNSService* servicePtr; + for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) + { + if (servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) + { + return servicePtr->_port; + } + } + return 0; +} + +IPAddress MDNSResponder::_getRequestMulticastInterface() +{ + struct ip_info ip_info; + bool match_ap = false; + if (wifi_get_opmode() & SOFTAP_MODE) + { + const IPAddress& remote_ip = _conn->getRemoteAddress(); + wifi_get_ip_info(SOFTAP_IF, &ip_info); + IPAddress infoIp(ip_info.ip); + IPAddress infoMask(ip_info.netmask); + if (ip_info.ip.addr && ip_addr_netcmp((const ip_addr_t*)remote_ip, (const ip_addr_t*)infoIp, ip_2_ip4((const ip_addr_t*)infoMask))) + { + match_ap = true; + } + } + if (!match_ap) + { + wifi_get_ip_info(STATION_IF, &ip_info); + } + return IPAddress(ip_info.ip.addr); +} + +void MDNSResponder::_parsePacket() +{ + int i; + char tmp; + bool serviceParsed = false; + bool protoParsed = false; + bool localParsed = false; + + char hostName[255]; + uint8_t hostNameLen; + + char serviceName[32]; + uint8_t serviceNameLen; + uint16_t servicePort = 0; + + char protoName[32]; + protoName[0] = 0; + uint8_t protoNameLen = 0; + + uint16_t packetHeader[6]; + + for (i = 0; i < 6; i++) + { + packetHeader[i] = _conn_read16(); + } + + if ((packetHeader[1] & 0x8000) != 0) // Read answers + { +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.printf("Reading answers RX: REQ, ID:%u, Q:%u, A:%u, NS:%u, ADD:%u\n", packetHeader[0], packetHeader[2], packetHeader[3], packetHeader[4], packetHeader[5]); +#endif + + if (!_waitingForAnswers) + { +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.println("Not expecting any answers right now, returning"); +#endif + _conn->flush(); + return; + } + + int numAnswers = packetHeader[3] + packetHeader[5]; + // Assume that the PTR answer always comes first and that it is always accompanied by a TXT, SRV, AAAA (optional) and A answer in the same packet. + if (numAnswers < 4) + { +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.printf("Expected a packet with 4 or more answers, got %u\n", numAnswers); +#endif + _conn->flush(); + return; + } + + uint8_t tmp8; + uint16_t answerPort = 0; + uint8_t answerIp[4] = { 0, 0, 0, 0 }; + char answerHostName[255]; + bool serviceMatch = false; + MDNSAnswer *answer; + uint8_t partsCollected = 0; + uint8_t stringsRead = 0; + + answerHostName[0] = '\0'; + + // Clear answer list + if (_newQuery) + { + int oldAnswers = _getNumAnswers(); + for (int n = oldAnswers - 1; n >= 0; n--) + { + answer = _getAnswerFromIdx(n); + os_free(answer->hostname); + os_free(answer); + answer = 0; + } + _answers = 0; + _newQuery = false; + } + + while (numAnswers--) + { + // Read name + stringsRead = 0; + size_t last_bufferpos = 0; + do + { + tmp8 = _conn_read8(); + if (tmp8 == 0x00) // End of name + { + break; + } + if (tmp8 & 0xC0) // Compressed pointer + { + uint16_t offset = ((((uint16_t)tmp8) & ~0xC0) << 8) | _conn_read8(); + if (_conn->isValidOffset(offset)) + { + if (0 == last_bufferpos) + { + last_bufferpos = _conn->tell(); + } +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.print("Compressed pointer, jumping from "); + DEBUG_ESP_PORT.print(last_bufferpos); + DEBUG_ESP_PORT.print(" to "); + DEBUG_ESP_PORT.println(offset); +#endif + _conn->seek(offset); + tmp8 = _conn_read8(); + } + else + { +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.print("Skipping malformed compressed pointer"); +#endif + tmp8 = _conn_read8(); + break; + } + } + if (stringsRead > 3) + { +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.println("failed to read the response name"); +#endif + _conn->flush(); + return; + } + _conn_readS(serviceName, tmp8); + serviceName[tmp8] = '\0'; +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.printf(" %d ", tmp8); + for (int n = 0; n < tmp8; n++) + { + DEBUG_ESP_PORT.printf("%c", serviceName[n]); + } + DEBUG_ESP_PORT.println(); +#endif + if (serviceName[0] == '_') + { + if (strcmp(&serviceName[1], _query->_service) == 0) + { + serviceMatch = true; +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.printf("found matching service: %s\n", _query->_service); +#endif + } + } + stringsRead++; + } while (true); + if (last_bufferpos > 0) + { + _conn->seek(last_bufferpos); +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.print("Compressed pointer, jumping back to "); + DEBUG_ESP_PORT.println(last_bufferpos); +#endif + } + + uint16_t answerType = _conn_read16(); // Read type + uint16_t answerClass = _conn_read16(); // Read class + uint32_t answerTtl = _conn_read32(); // Read ttl + uint16_t answerRdlength = _conn_read16(); // Read rdlength + + (void) answerClass; + (void) answerTtl; + + if (answerRdlength > 255) + { + if (answerType == MDNS_TYPE_TXT && answerRdlength < 1460) + { + while (--answerRdlength) + { + _conn->read(); + } + } + else + { +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.printf("Data len too long! %u\n", answerRdlength); +#endif + _conn->flush(); + return; + } + } + +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.printf("type: %04x rdlength: %d\n", answerType, answerRdlength); +#endif + + if (answerType == MDNS_TYPE_PTR) + { + partsCollected |= 0x01; + _conn_readS(hostName, answerRdlength); // Read rdata + if (hostName[answerRdlength - 2] & 0xc0) + { + memcpy(answerHostName, hostName + 1, answerRdlength - 3); + answerHostName[answerRdlength - 3] = '\0'; + } +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.printf("PTR %d ", answerRdlength); + for (int n = 0; n < answerRdlength; n++) + { + DEBUG_ESP_PORT.printf("%c", hostName[n]); + } + DEBUG_ESP_PORT.println(); +#endif + } + + else if (answerType == MDNS_TYPE_TXT) + { + partsCollected |= 0x02; + _conn_readS(hostName, answerRdlength); // Read rdata +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.printf("TXT %d ", answerRdlength); + for (int n = 0; n < answerRdlength; n++) + { + DEBUG_ESP_PORT.printf("%c", hostName[n]); + } + DEBUG_ESP_PORT.println(); +#endif + } + + else if (answerType == MDNS_TYPE_SRV) + { + partsCollected |= 0x04; + uint16_t answerPrio = _conn_read16(); // Read priority + uint16_t answerWeight = _conn_read16(); // Read weight + answerPort = _conn_read16(); // Read port + last_bufferpos = 0; + + (void) answerPrio; + (void) answerWeight; + + // Read hostname + tmp8 = _conn_read8(); + if (tmp8 & 0xC0) // Compressed pointer + { + uint16_t offset = ((((uint16_t)tmp8) & ~0xC0) << 8) | _conn_read8(); + if (_conn->isValidOffset(offset)) + { + last_bufferpos = _conn->tell(); +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.print("Compressed pointer, jumping from "); + DEBUG_ESP_PORT.print(last_bufferpos); + DEBUG_ESP_PORT.print(" to "); + DEBUG_ESP_PORT.println(offset); +#endif + _conn->seek(offset); + tmp8 = _conn_read8(); + } + else + { +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.print("Skipping malformed compressed pointer"); +#endif + tmp8 = _conn_read8(); + break; + } + } + _conn_readS(answerHostName, tmp8); + answerHostName[tmp8] = '\0'; +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.printf("SRV %d ", tmp8); + for (int n = 0; n < tmp8; n++) + { + DEBUG_ESP_PORT.printf("%02x ", answerHostName[n]); + } + DEBUG_ESP_PORT.printf("\n%s\n", answerHostName); +#endif + if (last_bufferpos > 0) + { + _conn->seek(last_bufferpos); + tmp8 = 2; // Size of compression octets +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.print("Compressed pointer, jumping back to "); + DEBUG_ESP_PORT.println(last_bufferpos); +#endif + } + if (answerRdlength - (6 + 1 + tmp8) > 0) // Skip any remaining rdata + { + _conn_readS(hostName, answerRdlength - (6 + 1 + tmp8)); + } + } + + else if (answerType == MDNS_TYPE_A) + { + partsCollected |= 0x08; + for (int i = 0; i < 4; i++) + { + answerIp[i] = _conn_read8(); + } + } + else + { +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.printf("Ignoring unsupported type %02x\n", tmp8); +#endif + for (int n = 0; n < answerRdlength; n++) + { + (void)_conn_read8(); + } + } + + if ((partsCollected == 0x0F) && serviceMatch) + { +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.println("All answers parsed, adding to _answers list.."); +#endif + // Add new answer to answer list + if (_answers == 0) + { + _answers = (struct MDNSAnswer*)(os_malloc(sizeof(struct MDNSAnswer))); + answer = _answers; + } + else + { + answer = _answers; + while (answer->next != 0) + { + answer = answer->next; + } + answer->next = (struct MDNSAnswer*)(os_malloc(sizeof(struct MDNSAnswer))); + answer = answer->next; + } + answer->next = 0; + answer->hostname = 0; + + // Populate new answer + answer->port = answerPort; + for (int i = 0; i < 4; i++) + { + answer->ip[i] = answerIp[i]; + } + answer->hostname = (char *)os_malloc(strlen(answerHostName) + 1); + os_strcpy(answer->hostname, answerHostName); + _conn->flush(); + return; + } + } + + _conn->flush(); + return; + } + + // PARSE REQUEST NAME + + hostNameLen = _conn_read8() % 255; + _conn_readS(hostName, hostNameLen); + hostName[hostNameLen] = '\0'; + + if (hostName[0] == '_') + { + serviceParsed = true; + memcpy(serviceName, hostName + 1, hostNameLen); + serviceNameLen = hostNameLen - 1; + hostNameLen = 0; + } + + if (hostNameLen > 0 && !_hostName.equals(hostName) && !_instanceName.equals(hostName)) + { +#ifdef DEBUG_ESP_MDNS_ERR + DEBUG_ESP_PORT.printf("ERR_NO_HOST: %s\n", hostName); + DEBUG_ESP_PORT.printf("hostname: %s\n", _hostName.c_str()); + DEBUG_ESP_PORT.printf("instance: %s\n", _instanceName.c_str()); +#endif + _conn->flush(); + return; + } + + if (!serviceParsed) + { + serviceNameLen = _conn_read8() % 255; + _conn_readS(serviceName, serviceNameLen); + serviceName[serviceNameLen] = '\0'; + + if (serviceName[0] == '_') + { + memmove(serviceName, serviceName + 1, serviceNameLen); + serviceNameLen--; + serviceParsed = true; + } + else if (serviceNameLen == 5 && strcmp("local", serviceName) == 0) + { + tmp = _conn_read8(); + if (tmp == 0) + { + serviceParsed = true; + serviceNameLen = 0; + protoParsed = true; + protoNameLen = 0; + localParsed = true; + } + else + { +#ifdef DEBUG_ESP_MDNS_ERR + DEBUG_ESP_PORT.printf("ERR_FQDN: %s\n", serviceName); +#endif + _conn->flush(); + return; + } + } + else + { +#ifdef DEBUG_ESP_MDNS_ERR + DEBUG_ESP_PORT.printf("ERR_SERVICE: %s\n", serviceName); +#endif + _conn->flush(); + return; + } + } + + if (!protoParsed) + { + protoNameLen = _conn_read8() % 255; + _conn_readS(protoName, protoNameLen); + protoName[protoNameLen] = '\0'; + if (protoNameLen == 4 && protoName[0] == '_') + { + memmove(protoName, protoName + 1, protoNameLen); + protoNameLen--; + protoParsed = true; + } + else if (strcmp("services", serviceName) == 0 && strcmp("_dns-sd", protoName) == 0) + { + _conn->flush(); + IPAddress interface = _getRequestMulticastInterface(); + _replyToTypeEnumRequest(interface); + return; + } + else + { +#ifdef DEBUG_ESP_MDNS_ERR + DEBUG_ESP_PORT.printf("ERR_PROTO: %s\n", protoName); +#endif + _conn->flush(); + return; + } + } + + if (!localParsed) + { + char localName[32]; + uint8_t localNameLen = _conn_read8() % 31; + _conn_readS(localName, localNameLen); + localName[localNameLen] = '\0'; + tmp = _conn_read8(); + if (localNameLen == 5 && strcmp("local", localName) == 0 && tmp == 0) + { + localParsed = true; + } + else + { +#ifdef DEBUG_ESP_MDNS_ERR + DEBUG_ESP_PORT.printf("ERR_FQDN: %s\n", localName); +#endif + _conn->flush(); + return; + } + } + + if (serviceNameLen > 0 && protoNameLen > 0) + { + servicePort = _getServicePort(serviceName, protoName); + if (servicePort == 0) + { +#ifdef DEBUG_ESP_MDNS_ERR + DEBUG_ESP_PORT.printf("ERR_NO_SERVICE: %s\n", serviceName); +#endif + _conn->flush(); + return; + } + } + else if (serviceNameLen > 0 || protoNameLen > 0) + { +#ifdef DEBUG_ESP_MDNS_ERR + DEBUG_ESP_PORT.printf("ERR_SERVICE_PROTO: %s\n", serviceName); +#endif + _conn->flush(); + return; + } + + // RESPOND + +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.printf("RX: REQ, ID:%u, Q:%u, A:%u, NS:%u, ADD:%u\n", packetHeader[0], packetHeader[2], packetHeader[3], packetHeader[4], packetHeader[5]); +#endif + + uint16_t currentType; + uint16_t currentClass; + + int numQuestions = packetHeader[2]; + if (numQuestions > 4) + { + numQuestions = 4; + } + uint16_t questions[4]; + int question = 0; + + while (numQuestions--) + { + currentType = _conn_read16(); + if (currentType & MDNS_NAME_REF) //new header handle it better! + { + currentType = _conn_read16(); + } + currentClass = _conn_read16(); + if (currentClass & MDNS_CLASS_IN) + { + questions[question++] = currentType; + } + + if (numQuestions > 0) + { + if (_conn_read16() != 0xC00C) //new question but for another host/service + { + _conn->flush(); + numQuestions = 0; + } + } + +#ifdef DEBUG_ESP_MDNS_RX + DEBUG_ESP_PORT.printf("REQ: "); + if (hostNameLen > 0) + { + DEBUG_ESP_PORT.printf("%s.", hostName); + } + if (serviceNameLen > 0) + { + DEBUG_ESP_PORT.printf("_%s.", serviceName); + } + if (protoNameLen > 0) + { + DEBUG_ESP_PORT.printf("_%s.", protoName); + } + DEBUG_ESP_PORT.printf("local. "); + + if (currentType == MDNS_TYPE_AAAA) + { + DEBUG_ESP_PORT.printf(" AAAA "); + } + else if (currentType == MDNS_TYPE_A) + { + DEBUG_ESP_PORT.printf(" A "); + } + else if (currentType == MDNS_TYPE_PTR) + { + DEBUG_ESP_PORT.printf(" PTR "); + } + else if (currentType == MDNS_TYPE_SRV) + { + DEBUG_ESP_PORT.printf(" SRV "); + } + else if (currentType == MDNS_TYPE_TXT) + { + DEBUG_ESP_PORT.printf(" TXT "); + } + else + { + DEBUG_ESP_PORT.printf(" 0x%04X ", currentType); + } + + if (currentClass == MDNS_CLASS_IN) + { + DEBUG_ESP_PORT.printf(" IN "); + } + else if (currentClass == MDNS_CLASS_IN_FLUSH_CACHE) + { + DEBUG_ESP_PORT.printf(" IN[F] "); + } + else + { + DEBUG_ESP_PORT.printf(" 0x%04X ", currentClass); + } + + DEBUG_ESP_PORT.printf("\n"); +#endif + } + uint8_t questionMask = 0; + uint8_t responseMask = 0; + for (i = 0; i < question; i++) + { + if (questions[i] == MDNS_TYPE_A) + { + questionMask |= 0x1; + responseMask |= 0x1; + } + else if (questions[i] == MDNS_TYPE_SRV) + { + questionMask |= 0x2; + responseMask |= 0x3; + } + else if (questions[i] == MDNS_TYPE_TXT) + { + questionMask |= 0x4; + responseMask |= 0x4; + } + else if (questions[i] == MDNS_TYPE_PTR) + { + questionMask |= 0x8; + responseMask |= 0xF; + } + } + + IPAddress interface = _getRequestMulticastInterface(); + return _replyToInstanceRequest(questionMask, responseMask, serviceName, protoName, servicePort, interface); +} + + +/** + STRINGIZE +*/ +#ifndef STRINGIZE +#define STRINGIZE(x) #x +#endif +#ifndef STRINGIZE_VALUE_OF +#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) +#endif + + +void MDNSResponder::enableArduino(uint16_t port, bool auth) +{ + + addService("arduino", "tcp", port); + addServiceTxt("arduino", "tcp", "tcp_check", "no"); + addServiceTxt("arduino", "tcp", "ssh_upload", "no"); + addServiceTxt("arduino", "tcp", "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD)); + addServiceTxt("arduino", "tcp", "auth_upload", (auth) ? "yes" : "no"); +} + +void MDNSResponder::_replyToTypeEnumRequest(IPAddress multicastInterface) +{ + MDNSService* servicePtr; + for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) + { + if (servicePtr->_port > 0) + { + char *service = servicePtr->_name; + char *proto = servicePtr->_proto; + //uint16_t port = servicePtr->_port; + +#ifdef DEBUG_ESP_MDNS_TX + DEBUG_ESP_PORT.printf("TX: service:%s, proto:%s\n", service, proto); +#endif + + char sdHostName[] = "_services"; + size_t sdHostNameLen = 9; + char sdServiceName[] = "_dns-sd"; + size_t sdServiceNameLen = 7; + char sdProtoName[] = "_udp"; + size_t sdProtoNameLen = 4; + + char underscore[] = "_"; + + // build service name with _ + char serviceName[os_strlen(service) + 2]; + os_strcpy(serviceName, underscore); + os_strcat(serviceName, service); + size_t serviceNameLen = os_strlen(serviceName); + + //build proto name with _ + char protoName[5]; + os_strcpy(protoName, underscore); + os_strcat(protoName, proto); + size_t protoNameLen = 4; + + //local string + char localName[] = "local"; + size_t localNameLen = 5; + + //terminator + char terminator[] = "\0"; + + //Write the header + _conn->flush(); + uint8_t head[12] = + { + 0x00, 0x00, //ID = 0 + 0x84, 0x00, //Flags = response + authoritative answer + 0x00, 0x00, //Question count + 0x00, 0x01, //Answer count + 0x00, 0x00, //Name server records + 0x00, 0x00, //Additional records + }; + _conn->append(reinterpret_cast<const char*>(head), 12); + + // Send the Name field (ie. "_services._dns-sd._udp.local") + _conn->append(reinterpret_cast<const char*>(&sdHostNameLen), 1); // length of "_services" + _conn->append(reinterpret_cast<const char*>(sdHostName), sdHostNameLen); // "_services" + _conn->append(reinterpret_cast<const char*>(&sdServiceNameLen), 1); // length of "_dns-sd" + _conn->append(reinterpret_cast<const char*>(sdServiceName), sdServiceNameLen);// "_dns-sd" + _conn->append(reinterpret_cast<const char*>(&sdProtoNameLen), 1); // length of "_udp" + _conn->append(reinterpret_cast<const char*>(sdProtoName), sdProtoNameLen); // "_udp" + _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" + _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" + _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator + + //Send the type, class, ttl and rdata length + uint8_t ptrDataLen = serviceNameLen + protoNameLen + localNameLen + 4; // 4 is three label sizes and the terminator + uint8_t ptrAttrs[10] = + { + 0x00, 0x0c, //PTR record query + 0x00, 0x01, //Class IN + 0x00, 0x00, 0x11, 0x94, //TTL 4500 + 0x00, ptrDataLen, //RData length + }; + _conn->append(reinterpret_cast<const char*>(ptrAttrs), 10); + + //Send the RData (ie. "_http._tcp.local") + _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" + _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" + _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" + _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" + _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" + _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" + _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator + + _conn->setMulticastInterface(multicastInterface); + _conn->send(); + } + } +} + +void MDNSResponder::_replyToInstanceRequest(uint8_t questionMask, uint8_t responseMask, char * service, char *proto, uint16_t port, IPAddress multicastInterface) +{ + int i; + if (questionMask == 0) + { + return; + } + if (responseMask == 0) + { + return; + } + +#ifdef DEBUG_ESP_MDNS_TX + DEBUG_ESP_PORT.printf("TX: qmask:%01X, rmask:%01X, service:%s, proto:%s, port:%u\n", questionMask, responseMask, service, proto, port); +#endif + + + String instanceName = _instanceName; + size_t instanceNameLen = instanceName.length(); + + String hostName = _hostName; + size_t hostNameLen = hostName.length(); + + char underscore[] = "_"; + + // build service name with _ + char serviceName[os_strlen(service) + 2]; + os_strcpy(serviceName, underscore); + os_strcat(serviceName, service); + size_t serviceNameLen = os_strlen(serviceName); + + //build proto name with _ + char protoName[5]; + os_strcpy(protoName, underscore); + os_strcat(protoName, proto); + size_t protoNameLen = 4; + + //local string + char localName[] = "local"; + size_t localNameLen = 5; + + //terminator + char terminator[] = "\0"; + + uint8_t answerMask = responseMask & questionMask; + uint8_t answerCount = 0; + uint8_t additionalMask = responseMask & ~questionMask; + uint8_t additionalCount = 0; + for (i = 0; i < 4; i++) + { + if (answerMask & (1 << i)) + { + answerCount++; + } + if (additionalMask & (1 << i)) + { + additionalCount++; + } + } + + + //Write the header + _conn->flush(); + uint8_t head[12] = + { + 0x00, 0x00, //ID = 0 + 0x84, 0x00, //Flags = response + authoritative answer + 0x00, 0x00, //Question count + 0x00, answerCount, //Answer count + 0x00, 0x00, //Name server records + 0x00, additionalCount, //Additional records + }; + _conn->append(reinterpret_cast<const char*>(head), 12); + + for (int responseSection = 0; responseSection < 2; ++responseSection) + { + + // PTR Response + if ((responseSection == 0 ? answerMask : additionalMask) & 0x8) + { + // Send the Name field (ie. "_http._tcp.local") + _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" + _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" + _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" + _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" + _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" + _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" + _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator + + //Send the type, class, ttl and rdata length + uint8_t ptrDataLen = instanceNameLen + serviceNameLen + protoNameLen + localNameLen + 5; // 5 is four label sizes and the terminator + uint8_t ptrAttrs[10] = + { + 0x00, 0x0c, //PTR record query + 0x00, 0x01, //Class IN + 0x00, 0x00, 0x00, 0x78, //TTL 120 + 0x00, ptrDataLen, //RData length + }; + _conn->append(reinterpret_cast<const char*>(ptrAttrs), 10); + + //Send the RData (ie. "My IOT device._http._tcp.local") + _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // length of "My IOT device" + _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" + _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" + _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" + _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" + _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" + _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" + _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" + _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator + } + + //TXT Responce + if ((responseSection == 0 ? answerMask : additionalMask) & 0x4) + { + //Send the name field (ie. "My IOT device._http._tcp.local") + _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // length of "My IOT device" + _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" + _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" + _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" + _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" + _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" + _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" + _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" + _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator + + //Send the type, class, ttl and rdata length + uint8_t txtDataLen = _getServiceTxtLen(service, proto); + uint8_t txtAttrs[10] = + { + 0x00, 0x10, //TXT record query + 0x80, 0x01, //Class IN, with cache flush + 0x00, 0x00, 0x11, 0x94, //TTL 4500 + 0x00, txtDataLen, //RData length + }; + _conn->append(reinterpret_cast<const char*>(txtAttrs), 10); + + //Send the RData + MDNSTxt * txtPtr = _getServiceTxt(service, proto); + while (txtPtr != 0) + { + uint8_t txtLen = txtPtr->_txt.length(); + _conn->append(reinterpret_cast<const char*>(&txtLen), 1); // length of txt + _conn->append(reinterpret_cast<const char*>(txtPtr->_txt.c_str()), txtLen);// the txt + txtPtr = txtPtr->_next; + } + } + + + //SRV Responce + if ((responseSection == 0 ? answerMask : additionalMask) & 0x2) + { + //Send the name field (ie. "My IOT device._http._tcp.local") + _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // length of "My IOT device" + _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" + _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" + _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" + _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" + _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" + _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" + _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" + _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator + + //Send the type, class, ttl, rdata length, priority and weight + uint8_t srvDataSize = hostNameLen + localNameLen + 3; // 3 is 2 lable size bytes and the terminator + srvDataSize += 6; // Size of Priority, weight and port + uint8_t srvAttrs[10] = + { + 0x00, 0x21, //Type SRV + 0x80, 0x01, //Class IN, with cache flush + 0x00, 0x00, 0x00, 0x78, //TTL 120 + 0x00, srvDataSize, //RData length + }; + _conn->append(reinterpret_cast<const char*>(srvAttrs), 10); + + //Send the RData Priority weight and port + uint8_t srvRData[6] = + { + 0x00, 0x00, //Priority 0 + 0x00, 0x00, //Weight 0 + (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF) + }; + _conn->append(reinterpret_cast<const char*>(srvRData), 6); + //Send the RData (ie. "esp8266.local") + _conn->append(reinterpret_cast<const char*>(&hostNameLen), 1); // length of "esp8266" + _conn->append(reinterpret_cast<const char*>(hostName.c_str()), hostNameLen);// "esp8266" + _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" + _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" + _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator + + } + + // A Response + if ((responseSection == 0 ? answerMask : additionalMask) & 0x1) + { + //Send the RData (ie. "esp8266.local") + _conn->append(reinterpret_cast<const char*>(&hostNameLen), 1); // length of "esp8266" + _conn->append(reinterpret_cast<const char*>(hostName.c_str()), hostNameLen);// "esp8266" + _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" + _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" + _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator + + uint8_t aaaAttrs[10] = + { + 0x00, 0x01, //TYPE A + 0x80, 0x01, //Class IN, with cache flush + 0x00, 0x00, 0x00, 0x78, //TTL 120 + 0x00, 0x04, //DATA LEN + }; + _conn->append(reinterpret_cast<const char*>(aaaAttrs), 10); + + // Send RData + uint32_t ip = multicastInterface; + uint8_t aaaRData[4] = + { + (uint8_t)(ip & 0xFF), //IP first octet + (uint8_t)((ip >> 8) & 0xFF), //IP second octet + (uint8_t)((ip >> 16) & 0xFF), //IP third octet + (uint8_t)((ip >> 24) & 0xFF) //IP fourth octet + }; + _conn->append(reinterpret_cast<const char*>(aaaRData), 4); + } + } + + _conn->setMulticastInterface(multicastInterface); + _conn->send(); +} + +#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) +MDNSResponder MDNS; +#endif + +} // namespace Legacy_MDNSResponder + + + + diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h b/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h new file mode 100644 index 0000000000..0a66a7fd32 --- /dev/null +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h @@ -0,0 +1,169 @@ +/* + ESP8266 Multicast DNS (port of CC3000 Multicast DNS library) + Version 1.1 + Copyright (c) 2013 Tony DiCola (tony@tonydicola.com) + ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com) + Extended MDNS-SD support 2016 Lars Englund (lars.englund@gmail.com) + + This is a simple implementation of multicast DNS query support for an Arduino + running on ESP8266 chip. Only support for resolving address queries is currently + implemented. + + Requirements: + - ESP8266WiFi library + + Usage: + - Include the ESP8266 Multicast DNS library in the sketch. + - Call the begin method in the sketch's setup and provide a domain name (without + the '.local' suffix, i.e. just provide 'foo' to resolve 'foo.local'), and the + Adafruit CC3000 class instance. Optionally provide a time to live (in seconds) + for the DNS record--the default is 1 hour. + - Call the update method in each iteration of the sketch's loop function. + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ +#ifndef ESP8266MDNS_LEGACY_H +#define ESP8266MDNS_LEGACY_H + +#include "ESP8266WiFi.h" +#include "WiFiUdp.h" + +//this should be defined at build time +#ifndef ARDUINO_BOARD +#define ARDUINO_BOARD "generic" +#endif + +class UdpContext; + + +namespace Legacy_MDNSResponder +{ + + +struct MDNSService; +struct MDNSTxt; +struct MDNSAnswer; + +class MDNSResponder +{ +public: + + static constexpr auto ApiVersion = MDNSApiVersion::Legacy; + + MDNSResponder(); + ~MDNSResponder(); + bool begin(const char* hostName); + bool begin(const String& hostName) + { + return begin(hostName.c_str()); + } + //for compatibility + bool begin(const char* hostName, IPAddress ip, uint32_t ttl = 120) + { + (void) ip; + (void) ttl; + return begin(hostName); + } + bool begin(const String& hostName, IPAddress ip, uint32_t ttl = 120) + { + return begin(hostName.c_str(), ip, ttl); + } + /* Application should call this whenever AP is configured/disabled */ + void notifyAPChange(); + void update(); + + void addService(char *service, char *proto, uint16_t port); + void addService(const char *service, const char *proto, uint16_t port) + { + addService((char *)service, (char *)proto, port); + } + void addService(const String& service, const String& proto, uint16_t port) + { + addService(service.c_str(), proto.c_str(), port); + } + + bool addServiceTxt(char *name, char *proto, char * key, char * value); + bool addServiceTxt(const char *name, const char *proto, const char *key, const char * value) + { + return addServiceTxt((char *)name, (char *)proto, (char *)key, (char *)value); + } + bool addServiceTxt(const String& name, const String& proto, const String& key, const String& value) + { + return addServiceTxt(name.c_str(), proto.c_str(), key.c_str(), value.c_str()); + } + + int queryService(char *service, char *proto); + int queryService(const char *service, const char *proto) + { + return queryService((char *)service, (char *)proto); + } + int queryService(const String& service, const String& proto) + { + return queryService(service.c_str(), proto.c_str()); + } + String hostname(int idx); + IPAddress IP(int idx); + uint16_t port(int idx); + + void enableArduino(uint16_t port, bool auth = false); + + void setInstanceName(String name); + void setInstanceName(const char * name) + { + setInstanceName(String(name)); + } + void setInstanceName(char * name) + { + setInstanceName(String(name)); + } + +private: + struct MDNSService * _services; + UdpContext* _conn; + String _hostName; + String _instanceName; + struct MDNSAnswer * _answers; + struct MDNSQuery * _query; + bool _newQuery; + bool _waitingForAnswers; + WiFiEventHandler _disconnectedHandler; + WiFiEventHandler _gotIPHandler; + + + uint16_t _getServicePort(char *service, char *proto); + MDNSTxt * _getServiceTxt(char *name, char *proto); + uint16_t _getServiceTxtLen(char *name, char *proto); + IPAddress _getRequestMulticastInterface(); + void _parsePacket(); + void _replyToTypeEnumRequest(IPAddress multicastInterface); + void _replyToInstanceRequest(uint8_t questionMask, uint8_t responseMask, char * service, char *proto, uint16_t port, IPAddress multicastInterface); + MDNSAnswer* _getAnswerFromIdx(int idx); + int _getNumAnswers(); + bool _listen(); + void _restart(); +}; + +} // namespace Legacy_MDNSResponder + +#endif //ESP8266MDNS_H + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS.cpp b/libraries/ESP8266mDNS/src/LEAmDNS.cpp new file mode 100644 index 0000000000..9e784bfe97 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS.cpp @@ -0,0 +1,1382 @@ +/* + LEAmDNS.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#include <Schedule.h> +#include <AddrList.h> + +#include "ESP8266mDNS.h" +#include "LEAmDNS_Priv.h" + + +namespace esp8266 +{ + +/* + LEAmDNS +*/ +namespace MDNSImplementation +{ + +/** + STRINGIZE +*/ +#ifndef STRINGIZE +#define STRINGIZE(x) #x +#endif +#ifndef STRINGIZE_VALUE_OF +#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) +#endif + + +/** + INTERFACE +*/ + +/** + MDNSResponder::MDNSResponder +*/ +MDNSResponder::MDNSResponder(void) + : m_pServices(0), + m_pUDPContext(0), + m_pcHostname(0), + m_pServiceQueries(0), + m_fnServiceTxtCallback(0), +#ifdef ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE + m_bPassivModeEnabled(true), +#else + m_bPassivModeEnabled(false), +#endif + m_netif(nullptr) +{ +} + +/* + MDNSResponder::~MDNSResponder +*/ +MDNSResponder::~MDNSResponder(void) +{ + + _resetProbeStatus(false); + _releaseServiceQueries(); + _releaseHostname(); + _releaseUDPContext(); + _releaseServices(); +} + +/* + MDNSResponder::begin + + Set the host domain (for probing) and install WiFi event handlers for + IP assignment and disconnection management. In both cases, the MDNS responder + is restarted (reset and restart probe status) + Finally the responder is (re)started + +*/ +bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& p_IPAddress, uint32_t p_u32TTL) +{ + + (void)p_u32TTL; // ignored + bool bResult = false; + + if (0 == m_pUDPContext) + { + if (_setHostname(p_pcHostname)) + { + + //// select interface + + m_netif = nullptr; + IPAddress ipAddress = p_IPAddress; + + if (!ipAddress.isSet()) + { + + IPAddress sta = WiFi.localIP(); + IPAddress ap = WiFi.softAPIP(); + + if (sta.isSet()) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] STA interface selected\n"))); + ipAddress = sta; + } + else if (ap.isSet()) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] AP interface selected\n"))); + ipAddress = ap; + } + else + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] standard interfaces are not up, please specify one in ::begin()\n"))); + return false; + } + + // continue to ensure interface is UP + } + + // check existence of this IP address in the interface list + bool found = false; + m_netif = nullptr; + for (auto a : addrList) + if (ipAddress == a.addr()) + { + if (a.ifUp()) + { + found = true; + m_netif = a.interface(); + break; + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] found interface for IP '%s' but it is not UP\n"), ipAddress.toString().c_str());); + } + if (!found) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] interface defined by IP '%s' not found\n"), ipAddress.toString().c_str());); + return false; + } + + //// done selecting the interface + + if (m_netif->num == STATION_IF) + { + + m_GotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP & pEvent) + { + (void) pEvent; + // Ensure that _restart() runs in USER context + schedule_function([this]() + { + MDNSResponder::_restart(); + }); + }); + + m_DisconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected & pEvent) + { + (void) pEvent; + // Ensure that _restart() runs in USER context + schedule_function([this]() + { + MDNSResponder::_restart(); + }); + }); + } + + bResult = _restart(); + } + DEBUG_EX_ERR(if (!bResult) + { + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] begin: FAILED for '%s'!\n"), (p_pcHostname ? : "-")); + }); + } + else + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] begin: Ignoring multiple calls to begin (Ignored host domain: '%s')!\n"), (p_pcHostname ? : "-"));); + } + return bResult; +} + +/* + MDNSResponder::close + + Ends the MDNS responder. + Announced services are unannounced (by multicasting a goodbye message) + +*/ +bool MDNSResponder::close(void) +{ + bool bResult = false; + + if (0 != m_pUDPContext) + { + m_GotIPHandler.reset(); // reset WiFi event callbacks. + m_DisconnectedHandler.reset(); + + _announce(false, true); + _resetProbeStatus(false); // Stop probing + _releaseServiceQueries(); + _releaseUDPContext(); + _releaseHostname(); + + bResult = true; + } + else + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] close: Ignoring call to close!\n"));); + } + return bResult; +} + +/* + MDNSResponder::end + + Ends the MDNS responder. + for compatibility with esp32 + +*/ + +bool MDNSResponder::end(void) +{ + return close(); +} + +/* + MDNSResponder::setHostname + + Replaces the current hostname and restarts probing. + For services without own instance name (when the host name was used a instance + name), the instance names are replaced also (and the probing is restarted). + +*/ +bool MDNSResponder::setHostname(const char* p_pcHostname) +{ + + bool bResult = false; + + if (_setHostname(p_pcHostname)) + { + m_HostProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart; + + // Replace 'auto-set' service names + bResult = true; + for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + { + if (pService->m_bAutoName) + { + bResult = pService->setName(p_pcHostname); + pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart; + } + } + } + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setHostname: FAILED for '%s'!\n"), (p_pcHostname ? : "-")); + }); + return bResult; +} + +/* + MDNSResponder::setHostname (LEGACY) +*/ +bool MDNSResponder::setHostname(const String& p_strHostname) +{ + + return setHostname(p_strHostname.c_str()); +} + + +/* + SERVICES +*/ + +/* + MDNSResponder::addService + + Add service; using hostname if no name is explicitly provided for the service + The usual '_' underline, which is prepended to service and protocol, eg. _http, + may be given. If not, it is added automatically. + +*/ +MDNSResponder::hMDNSService MDNSResponder::addService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + uint16_t p_u16Port) +{ + + hMDNSService hResult = 0; + + if (((!p_pcName) || // NO name OR + (MDNS_DOMAIN_LABEL_MAXLENGTH >= os_strlen(p_pcName))) && // Fitting name + (p_pcService) && + (MDNS_SERVICE_NAME_LENGTH >= os_strlen(p_pcService)) && + (p_pcProtocol) && + ((MDNS_SERVICE_PROTOCOL_LENGTH - 1) != os_strlen(p_pcProtocol)) && + (p_u16Port)) + { + + if (!_findService((p_pcName ? : m_pcHostname), p_pcService, p_pcProtocol)) // Not already used + { + if (0 != (hResult = (hMDNSService)_allocService(p_pcName, p_pcService, p_pcProtocol, p_u16Port))) + { + + // Start probing + ((stcMDNSService*)hResult)->m_ProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart; + } + } + } // else: bad arguments + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addService: %s to add '%s.%s.%s'!\n"), (hResult ? "Succeeded" : "FAILED"), (p_pcName ? : "-"), p_pcService, p_pcProtocol);); + DEBUG_EX_ERR(if (!hResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addService: FAILED to add '%s.%s.%s'!\n"), (p_pcName ? : "-"), p_pcService, p_pcProtocol); + }); + return hResult; +} + +/* + MDNSResponder::removeService + + Unanounce a service (by sending a goodbye message) and remove it + from the MDNS responder + +*/ +bool MDNSResponder::removeService(const MDNSResponder::hMDNSService p_hService) +{ + + stcMDNSService* pService = 0; + bool bResult = (((pService = _findService(p_hService))) && + (_announceService(*pService, false)) && + (_releaseService(pService))); + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeService: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::removeService +*/ +bool MDNSResponder::removeService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol) +{ + + return removeService((hMDNSService)_findService((p_pcName ? : m_pcHostname), p_pcService, p_pcProtocol)); +} + +/* + MDNSResponder::addService (LEGACY) +*/ +bool MDNSResponder::addService(const String& p_strService, + const String& p_strProtocol, + uint16_t p_u16Port) +{ + + return (0 != addService(m_pcHostname, p_strService.c_str(), p_strProtocol.c_str(), p_u16Port)); +} + +/* + MDNSResponder::setServiceName +*/ +bool MDNSResponder::setServiceName(const MDNSResponder::hMDNSService p_hService, + const char* p_pcInstanceName) +{ + + stcMDNSService* pService = 0; + bool bResult = (((!p_pcInstanceName) || + (MDNS_DOMAIN_LABEL_MAXLENGTH >= os_strlen(p_pcInstanceName))) && + ((pService = _findService(p_hService))) && + (pService->setName(p_pcInstanceName)) && + ((pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart))); + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setServiceName: FAILED for '%s'!\n"), (p_pcInstanceName ? : "-")); + }); + return bResult; +} + +/* + SERVICE TXT +*/ + +/* + MDNSResponder::addServiceTxt + + Add a static service TXT item ('Key'='Value') to a service. + +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + const char* p_pcValue) +{ + + hMDNSTxt hTxt = 0; + stcMDNSService* pService = _findService(p_hService); + if (pService) + { + hTxt = (hMDNSTxt)_addServiceTxt(pService, p_pcKey, p_pcValue, false); + } + DEBUG_EX_ERR(if (!hTxt) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addServiceTxt: FAILED for '%s=%s'!\n"), (p_pcKey ? : "-"), (p_pcValue ? : "-")); + }); + return hTxt; +} + +/* + MDNSResponder::addServiceTxt (uint32_t) + + Formats: http://www.cplusplus.com/reference/cstdio/printf/ +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + uint32_t p_u32Value) +{ + char acBuffer[32]; *acBuffer = 0; + sprintf(acBuffer, "%u", p_u32Value); + + return addServiceTxt(p_hService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addServiceTxt (uint16_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + uint16_t p_u16Value) +{ + char acBuffer[16]; *acBuffer = 0; + sprintf(acBuffer, "%hu", p_u16Value); + + return addServiceTxt(p_hService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addServiceTxt (uint8_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + uint8_t p_u8Value) +{ + char acBuffer[8]; *acBuffer = 0; + sprintf(acBuffer, "%hhu", p_u8Value); + + return addServiceTxt(p_hService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addServiceTxt (int32_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + int32_t p_i32Value) +{ + char acBuffer[32]; *acBuffer = 0; + sprintf(acBuffer, "%i", p_i32Value); + + return addServiceTxt(p_hService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addServiceTxt (int16_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + int16_t p_i16Value) +{ + char acBuffer[16]; *acBuffer = 0; + sprintf(acBuffer, "%hi", p_i16Value); + + return addServiceTxt(p_hService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addServiceTxt (int8_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + int8_t p_i8Value) +{ + char acBuffer[8]; *acBuffer = 0; + sprintf(acBuffer, "%hhi", p_i8Value); + + return addServiceTxt(p_hService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::removeServiceTxt + + Remove a static service TXT item from a service. +*/ +bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSService p_hService, + const MDNSResponder::hMDNSTxt p_hTxt) +{ + + bool bResult = false; + + stcMDNSService* pService = _findService(p_hService); + if (pService) + { + stcMDNSServiceTxt* pTxt = _findServiceTxt(pService, p_hTxt); + if (pTxt) + { + bResult = _releaseServiceTxt(pService, pTxt); + } + } + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeServiceTxt: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::removeServiceTxt +*/ +bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSService p_hService, + const char* p_pcKey) +{ + + bool bResult = false; + + stcMDNSService* pService = _findService(p_hService); + if (pService) + { + stcMDNSServiceTxt* pTxt = _findServiceTxt(pService, p_pcKey); + if (pTxt) + { + bResult = _releaseServiceTxt(pService, pTxt); + } + } + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeServiceTxt: FAILED for '%s'!\n"), (p_pcKey ? : "-")); + }); + return bResult; +} + +/* + MDNSResponder::removeServiceTxt +*/ +bool MDNSResponder::removeServiceTxt(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + const char* p_pcKey) +{ + + bool bResult = false; + + stcMDNSService* pService = _findService((p_pcName ? : m_pcHostname), p_pcService, p_pcProtocol); + if (pService) + { + stcMDNSServiceTxt* pTxt = _findServiceTxt(pService, p_pcKey); + if (pTxt) + { + bResult = _releaseServiceTxt(pService, pTxt); + } + } + return bResult; +} + +/* + MDNSResponder::addServiceTxt (LEGACY) +*/ +bool MDNSResponder::addServiceTxt(const char* p_pcService, + const char* p_pcProtocol, + const char* p_pcKey, + const char* p_pcValue) +{ + + return (0 != _addServiceTxt(_findService(m_pcHostname, p_pcService, p_pcProtocol), p_pcKey, p_pcValue, false)); +} + +/* + MDNSResponder::addServiceTxt (LEGACY) +*/ +bool MDNSResponder::addServiceTxt(const String& p_strService, + const String& p_strProtocol, + const String& p_strKey, + const String& p_strValue) +{ + + return (0 != _addServiceTxt(_findService(m_pcHostname, p_strService.c_str(), p_strProtocol.c_str()), p_strKey.c_str(), p_strValue.c_str(), false)); +} + +/* + MDNSResponder::setDynamicServiceTxtCallback (global) + + Set a global callback for dynamic service TXT items. The callback is called, whenever + service TXT items are needed. + +*/ +bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::MDNSDynamicServiceTxtCallbackFunc p_fnCallback) +{ + + m_fnServiceTxtCallback = p_fnCallback; + + return true; +} + +/* + MDNSResponder::setDynamicServiceTxtCallback (service specific) + + Set a service specific callback for dynamic service TXT items. The callback is called, whenever + service TXT items are needed for the given service. + +*/ +bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::hMDNSService p_hService, + MDNSResponder::MDNSDynamicServiceTxtCallbackFunc p_fnCallback) +{ + + bool bResult = false; + + stcMDNSService* pService = _findService(p_hService); + if (pService) + { + pService->m_fnTxtCallback = p_fnCallback; + + bResult = true; + } + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setDynamicServiceTxtCallback: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::addDynamicServiceTxt +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + const char* p_pcValue) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addDynamicServiceTxt (%s=%s)\n"), p_pcKey, p_pcValue);); + + hMDNSTxt hTxt = 0; + + stcMDNSService* pService = _findService(p_hService); + if (pService) + { + hTxt = _addServiceTxt(pService, p_pcKey, p_pcValue, true); + } + DEBUG_EX_ERR(if (!hTxt) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addDynamicServiceTxt: FAILED for '%s=%s'!\n"), (p_pcKey ? : "-"), (p_pcValue ? : "-")); + }); + return hTxt; +} + +/* + MDNSResponder::addDynamicServiceTxt (uint32_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + uint32_t p_u32Value) +{ + + char acBuffer[32]; *acBuffer = 0; + sprintf(acBuffer, "%u", p_u32Value); + + return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addDynamicServiceTxt (uint16_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + uint16_t p_u16Value) +{ + + char acBuffer[16]; *acBuffer = 0; + sprintf(acBuffer, "%hu", p_u16Value); + + return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addDynamicServiceTxt (uint8_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + uint8_t p_u8Value) +{ + + char acBuffer[8]; *acBuffer = 0; + sprintf(acBuffer, "%hhu", p_u8Value); + + return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addDynamicServiceTxt (int32_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + int32_t p_i32Value) +{ + + char acBuffer[32]; *acBuffer = 0; + sprintf(acBuffer, "%i", p_i32Value); + + return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addDynamicServiceTxt (int16_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + int16_t p_i16Value) +{ + + char acBuffer[16]; *acBuffer = 0; + sprintf(acBuffer, "%hi", p_i16Value); + + return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); +} + +/* + MDNSResponder::addDynamicServiceTxt (int8_t) +*/ +MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, + const char* p_pcKey, + int8_t p_i8Value) +{ + + char acBuffer[8]; *acBuffer = 0; + sprintf(acBuffer, "%hhi", p_i8Value); + + return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); +} + + +/** + STATIC SERVICE QUERY (LEGACY) +*/ + +/* + MDNSResponder::queryService + + Perform a (blocking) static service query. + The arrived answers can be queried by calling: + - answerHostname (or 'hostname') + - answerIP (or 'IP') + - answerPort (or 'port') + +*/ +uint32_t MDNSResponder::queryService(const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) +{ + if (0 == m_pUDPContext) + { + // safeguard against misuse + return 0; + } + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService '%s.%s'\n"), p_pcService, p_pcProtocol);); + + uint32_t u32Result = 0; + + stcMDNSServiceQuery* pServiceQuery = 0; + if ((p_pcService) && + (os_strlen(p_pcService)) && + (p_pcProtocol) && + (os_strlen(p_pcProtocol)) && + (p_u16Timeout) && + (_removeLegacyServiceQuery()) && + ((pServiceQuery = _allocServiceQuery())) && + (_buildDomainForService(p_pcService, p_pcProtocol, pServiceQuery->m_ServiceTypeDomain))) + { + + pServiceQuery->m_bLegacyQuery = true; + + if (_sendMDNSServiceQuery(*pServiceQuery)) + { + // Wait for answers to arrive + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService: Waiting %u ms for answers...\n"), p_u16Timeout);); + delay(p_u16Timeout); + + // All answers should have arrived by now -> stop adding new answers + pServiceQuery->m_bAwaitingAnswers = false; + u32Result = pServiceQuery->answerCount(); + } + else // FAILED to send query + { + _removeServiceQuery(pServiceQuery); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService: INVALID input data!\n"));); + } + return u32Result; +} + +/* + MDNSResponder::removeQuery + + Remove the last static service query (and all answers). + +*/ +bool MDNSResponder::removeQuery(void) +{ + + return _removeLegacyServiceQuery(); +} + +/* + MDNSResponder::queryService (LEGACY) +*/ +uint32_t MDNSResponder::queryService(const String& p_strService, + const String& p_strProtocol) +{ + + return queryService(p_strService.c_str(), p_strProtocol.c_str()); +} + +/* + MDNSResponder::answerHostname +*/ +const char* MDNSResponder::answerHostname(const uint32_t p_u32AnswerIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery(); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + + if ((pSQAnswer) && + (pSQAnswer->m_HostDomain.m_u16NameLength) && + (!pSQAnswer->m_pcHostDomain)) + { + + char* pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); + if (pcHostDomain) + { + pSQAnswer->m_HostDomain.c_str(pcHostDomain); + } + } + return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); +} + +#ifdef MDNS_IP4_SUPPORT +/* + MDNSResponder::answerIP +*/ +IPAddress MDNSResponder::answerIP(const uint32_t p_u32AnswerIndex) +{ + + const stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery(); + const stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + const stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address = (((pSQAnswer) && (pSQAnswer->m_pIP4Addresses)) ? pSQAnswer->IP4AddressAtIndex(0) : 0); + return (pIP4Address ? pIP4Address->m_IPAddress : IPAddress()); +} +#endif + +#ifdef MDNS_IP6_SUPPORT +/* + MDNSResponder::answerIP6 +*/ +IPAddress MDNSResponder::answerIP6(const uint32_t p_u32AnswerIndex) +{ + + const stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery(); + const stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + const stcMDNSServiceQuery::stcAnswer::stcIP6Address* pIP6Address = (((pSQAnswer) && (pSQAnswer->m_pIP6Addresses)) ? pSQAnswer->IP6AddressAtIndex(0) : 0); + return (pIP6Address ? pIP6Address->m_IPAddress : IP6Address()); +} +#endif + +/* + MDNSResponder::answerPort +*/ +uint16_t MDNSResponder::answerPort(const uint32_t p_u32AnswerIndex) +{ + + const stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery(); + const stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return (pSQAnswer ? pSQAnswer->m_u16Port : 0); +} + +/* + MDNSResponder::hostname (LEGACY) +*/ +String MDNSResponder::hostname(const uint32_t p_u32AnswerIndex) +{ + + return String(answerHostname(p_u32AnswerIndex)); +} + +/* + MDNSResponder::IP (LEGACY) +*/ +IPAddress MDNSResponder::IP(const uint32_t p_u32AnswerIndex) +{ + + return answerIP(p_u32AnswerIndex); +} + +/* + MDNSResponder::port (LEGACY) +*/ +uint16_t MDNSResponder::port(const uint32_t p_u32AnswerIndex) +{ + + return answerPort(p_u32AnswerIndex); +} + + +/** + DYNAMIC SERVICE QUERY +*/ + +/* + MDNSResponder::installServiceQuery + + Add a dynamic service query and a corresponding callback to the MDNS responder. + The callback will be called for every answer update. + The answers can also be queried by calling: + - answerServiceDomain + - answerHostDomain + - answerIP4Address/answerIP6Address + - answerPort + - answerTxts + +*/ +MDNSResponder::hMDNSServiceQuery MDNSResponder::installServiceQuery(const char* p_pcService, + const char* p_pcProtocol, + MDNSResponder::MDNSServiceQueryCallbackFunc p_fnCallback) +{ + hMDNSServiceQuery hResult = 0; + + stcMDNSServiceQuery* pServiceQuery = 0; + if ((p_pcService) && + (os_strlen(p_pcService)) && + (p_pcProtocol) && + (os_strlen(p_pcProtocol)) && + (p_fnCallback) && + ((pServiceQuery = _allocServiceQuery())) && + (_buildDomainForService(p_pcService, p_pcProtocol, pServiceQuery->m_ServiceTypeDomain))) + { + + pServiceQuery->m_fnCallback = p_fnCallback; + pServiceQuery->m_bLegacyQuery = false; + + if (_sendMDNSServiceQuery(*pServiceQuery)) + { + pServiceQuery->m_u8SentCount = 1; + pServiceQuery->m_ResendTimeout.reset(MDNS_DYNAMIC_QUERY_RESEND_DELAY); + + hResult = (hMDNSServiceQuery)pServiceQuery; + } + else + { + _removeServiceQuery(pServiceQuery); + } + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] installServiceQuery: %s for '%s.%s'!\n\n"), (hResult ? "Succeeded" : "FAILED"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); + DEBUG_EX_ERR(if (!hResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] installServiceQuery: FAILED for '%s.%s'!\n\n"), (p_pcService ? : "-"), (p_pcProtocol ? : "-")); + }); + return hResult; +} + +/* + MDNSResponder::removeServiceQuery + + Remove a dynamic service query (and all collected answers) from the MDNS responder + +*/ +bool MDNSResponder::removeServiceQuery(MDNSResponder::hMDNSServiceQuery p_hServiceQuery) +{ + + stcMDNSServiceQuery* pServiceQuery = 0; + bool bResult = (((pServiceQuery = _findServiceQuery(p_hServiceQuery))) && + (_removeServiceQuery(pServiceQuery))); + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeServiceQuery: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::answerCount +*/ +uint32_t MDNSResponder::answerCount(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + return (pServiceQuery ? pServiceQuery->answerCount() : 0); +} + +std::vector<MDNSResponder::MDNSServiceInfo> MDNSResponder::answerInfo(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery) +{ + std::vector<MDNSResponder::MDNSServiceInfo> tempVector; + for (uint32_t i = 0; i < answerCount(p_hServiceQuery); i++) + { + tempVector.emplace_back(*this, p_hServiceQuery, i); + } + return tempVector; +} + +/* + MDNSResponder::answerServiceDomain + + Returns the domain for the given service. + If not already existing, the string is allocated, filled and attached to the answer. + +*/ +const char* MDNSResponder::answerServiceDomain(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + // Fill m_pcServiceDomain (if not already done) + if ((pSQAnswer) && + (pSQAnswer->m_ServiceDomain.m_u16NameLength) && + (!pSQAnswer->m_pcServiceDomain)) + { + + pSQAnswer->m_pcServiceDomain = pSQAnswer->allocServiceDomain(pSQAnswer->m_ServiceDomain.c_strLength()); + if (pSQAnswer->m_pcServiceDomain) + { + pSQAnswer->m_ServiceDomain.c_str(pSQAnswer->m_pcServiceDomain); + } + } + return (pSQAnswer ? pSQAnswer->m_pcServiceDomain : 0); +} + +/* + MDNSResponder::hasAnswerHostDomain +*/ +bool MDNSResponder::hasAnswerHostDomain(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_HostDomainAndPort)); +} + +/* + MDNSResponder::answerHostDomain + + Returns the host domain for the given service. + If not already existing, the string is allocated, filled and attached to the answer. + +*/ +const char* MDNSResponder::answerHostDomain(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + // Fill m_pcHostDomain (if not already done) + if ((pSQAnswer) && + (pSQAnswer->m_HostDomain.m_u16NameLength) && + (!pSQAnswer->m_pcHostDomain)) + { + + pSQAnswer->m_pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); + if (pSQAnswer->m_pcHostDomain) + { + pSQAnswer->m_HostDomain.c_str(pSQAnswer->m_pcHostDomain); + } + } + return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); +} + +#ifdef MDNS_IP4_SUPPORT +/* + MDNSResponder::hasAnswerIP4Address +*/ +bool MDNSResponder::hasAnswerIP4Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_IP4Address)); +} + +/* + MDNSResponder::answerIP4AddressCount +*/ +uint32_t MDNSResponder::answerIP4AddressCount(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return (pSQAnswer ? pSQAnswer->IP4AddressCount() : 0); +} + +/* + MDNSResponder::answerIP4Address +*/ +IPAddress MDNSResponder::answerIP4Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address = (pSQAnswer ? pSQAnswer->IP4AddressAtIndex(p_u32AddressIndex) : 0); + return (pIP4Address ? pIP4Address->m_IPAddress : IPAddress()); +} +#endif + +#ifdef MDNS_IP6_SUPPORT +/* + MDNSResponder::hasAnswerIP6Address +*/ +bool MDNSResponder::hasAnswerIP6Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_HostIP6Address)); +} + +/* + MDNSResponder::answerIP6AddressCount +*/ +uint32_t MDNSResponder::answerIP6AddressCount(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return (pSQAnswer ? pSQAnswer->IP6AddressCount() : 0); +} + +/* + MDNSResponder::answerIP6Address +*/ +IPAddress MDNSResponder::answerIP6Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + stcMDNSServiceQuery::stcAnswer::stcIP6Address* pIP6Address = (pSQAnswer ? pSQAnswer->IP6AddressAtIndex(p_u32AddressIndex) : 0); + return (pIP6Address ? pIP6Address->m_IPAddress : IPAddress()); +} +#endif + +/* + MDNSResponder::hasAnswerPort +*/ +bool MDNSResponder::hasAnswerPort(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_HostDomainAndPort)); +} + +/* + MDNSResponder::answerPort +*/ +uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return (pSQAnswer ? pSQAnswer->m_u16Port : 0); +} + +/* + MDNSResponder::hasAnswerTxts +*/ +bool MDNSResponder::hasAnswerTxts(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + return ((pSQAnswer) && + (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_Txts)); +} + +/* + MDNSResponder::answerTxts + + Returns all TXT items for the given service as a ';'-separated string. + If not already existing; the string is alloced, filled and attached to the answer. + +*/ +const char* MDNSResponder::answerTxts(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + // Fill m_pcTxts (if not already done) + if ((pSQAnswer) && + (pSQAnswer->m_Txts.m_pTxts) && + (!pSQAnswer->m_pcTxts)) + { + + pSQAnswer->m_pcTxts = pSQAnswer->allocTxts(pSQAnswer->m_Txts.c_strLength()); + if (pSQAnswer->m_pcTxts) + { + pSQAnswer->m_Txts.c_str(pSQAnswer->m_pcTxts); + } + } + return (pSQAnswer ? pSQAnswer->m_pcTxts : 0); +} + +/* + PROBING +*/ + +/* + MDNSResponder::setProbeResultCallback + + Set a global callback for probe results. The callback is called, when probing + for the host domain (or a service domain, without specific probe result callback) + failes or succeedes. + In the case of failure, the domain name should be changed via 'setHostname' or 'setServiceName'. + When succeeded, the host or service domain will be announced by the MDNS responder. + +*/ +bool MDNSResponder::setHostProbeResultCallback(MDNSResponder::MDNSHostProbeFn p_fnCallback) +{ + + m_HostProbeInformation.m_fnHostProbeResultCallback = p_fnCallback; + + return true; +} + +bool MDNSResponder::setHostProbeResultCallback(MDNSHostProbeFn1 pfn) +{ + using namespace std::placeholders; + return setHostProbeResultCallback([this, pfn](const char* p_pcDomainName, bool p_bProbeResult) + { + pfn(*this, p_pcDomainName, p_bProbeResult); + }); +} + +/* + MDNSResponder::setServiceProbeResultCallback + + Set a service specific callback for probe results. The callback is called, when probing + for the service domain failes or succeedes. + In the case of failure, the service name should be changed via 'setServiceName'. + When succeeded, the service domain will be announced by the MDNS responder. + +*/ +bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService, + MDNSResponder::MDNSServiceProbeFn p_fnCallback) +{ + + bool bResult = false; + + stcMDNSService* pService = _findService(p_hService); + if (pService) + { + pService->m_ProbeInformation.m_fnServiceProbeResultCallback = p_fnCallback; + + bResult = true; + } + return bResult; +} + +bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService, + MDNSResponder::MDNSServiceProbeFn1 p_fnCallback) +{ + using namespace std::placeholders; + return setServiceProbeResultCallback(p_hService, [this, p_fnCallback](const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) + { + p_fnCallback(*this, p_pcServiceName, p_hMDNSService, p_bProbeResult); + }); +} + + +/* + MISC +*/ + +/* + MDNSResponder::notifyAPChange + + Should be called, whenever the AP for the MDNS responder changes. + A bit of this is caught by the event callbacks installed in the constructor. + +*/ +bool MDNSResponder::notifyAPChange(void) +{ + + return _restart(); +} + +/* + MDNSResponder::update + + Should be called in every 'loop'. + +*/ +bool MDNSResponder::update(void) +{ + + if (m_bPassivModeEnabled) + { + m_bPassivModeEnabled = false; + } + return _process(true); +} + +/* + MDNSResponder::announce + + Should be called, if the 'configuration' changes. Mainly this will be changes in the TXT items... +*/ +bool MDNSResponder::announce(void) +{ + + return (_announce(true, true)); +} + +/* + MDNSResponder::enableArduino + + Enable the OTA update service. + +*/ +MDNSResponder::hMDNSService MDNSResponder::enableArduino(uint16_t p_u16Port, + bool p_bAuthUpload /*= false*/) +{ + + hMDNSService hService = addService(0, "arduino", "tcp", p_u16Port); + if (hService) + { + if ((!addServiceTxt(hService, "tcp_check", "no")) || + (!addServiceTxt(hService, "ssh_upload", "no")) || + (!addServiceTxt(hService, "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD))) || + (!addServiceTxt(hService, "auth_upload", (p_bAuthUpload) ? "yes" : "no"))) + { + + removeService(hService); + hService = 0; + } + } + return hService; +} + + +} //namespace MDNSImplementation + +} //namespace esp8266 + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS.h b/libraries/ESP8266mDNS/src/LEAmDNS.h new file mode 100644 index 0000000000..e10080adf3 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS.h @@ -0,0 +1,1464 @@ +/* + LEAmDNS.h + (c) 2018, LaborEtArs + + Version 0.9 beta + + Some notes (from LaborEtArs, 2018): + Essentially, this is an rewrite of the original EPS8266 Multicast DNS code (ESP8266mDNS). + The target of this rewrite was to keep the existing interface as stable as possible while + adding and extending the supported set of mDNS features. + A lot of the additions were basicly taken from Erik Ekman's lwIP mdns app code. + + Supported mDNS features (in some cases somewhat limited): + - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service + - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented + - Probing host and service domains for uniqueness in the local network + - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak) + - Announcing available services after successful probing + - Using fixed service TXT items or + - Using dynamic service TXT items for presented services (via callback) + - Remove services (and un-announcing them to the observers by sending goodbye-messages) + - Static queries for DNS-SD services (creating a fixed answer set after a certain timeout period) + - Dynamic queries for DNS-SD services with cached and updated answers and user notifications + + + Usage: + In most cases, this implementation should work as a 'drop-in' replacement for the original + ESP8266 Multicast DNS code. Adjustments to the existing code would only be needed, if some + of the new features should be used. + + For presenting services: + In 'setup()': + Install a callback for the probing of host (and service) domains via 'MDNS.setProbeResultCallback(probeResultCallback, &userData);' + Register DNS-SD services with 'MDNSResponder::hMDNSService hService = MDNS.addService("MyESP", "http", "tcp", 5000);' + (Install additional callbacks for the probing of these service domains via 'MDNS.setServiceProbeResultCallback(hService, probeResultCallback, &userData);') + Add service TXT items with 'MDNS.addServiceTxt(hService, "c#", "1");' or by installing a service TXT callback + using 'MDNS.setDynamicServiceTxtCallback(dynamicServiceTxtCallback, &userData);' or service specific + 'MDNS.setDynamicServiceTxtCallback(hService, dynamicServiceTxtCallback, &userData);' + Call MDNS.begin("MyHostname"); + + In 'probeResultCallback(MDNSResponder* p_MDNSResponder, const char* p_pcDomain, MDNSResponder:hMDNSService p_hService, bool p_bProbeResult, void* p_pUserdata)': + Check the probe result and update the host or service domain name if the probe failed + + In 'dynamicServiceTxtCallback(MDNSResponder* p_MDNSResponder, const hMDNSService p_hService, void* p_pUserdata)': + Add dynamic TXT items by calling 'MDNS.addDynamicServiceTxt(p_hService, "c#", "1");' + + In loop(): + Call 'MDNS.update();' + + + For querying services: + Static: + Call 'uint32_t u32AnswerCount = MDNS.queryService("http", "tcp");' + Iterate answers by: 'for (uint32_t u=0; u<u32AnswerCount; ++u) { const char* pHostname = MDNS.answerHostname(u); }' + You should call MDNS.removeQuery() sometimes later (when the answers are nott needed anymore) + + Dynamic: + Install a dynamic query by calling 'DNSResponder::hMDNSServiceQuery hServiceQuery = MDNS.installServiceQuery("http", "tcp", serviceQueryCallback, &userData);' + The callback 'serviceQueryCallback(MDNSResponder* p_MDNSResponder, const hMDNSServiceQuery p_hServiceQuery, uint32_t p_u32AnswerIndex, + enuServiceQueryAnswerType p_ServiceQueryAnswerType, bool p_bSetContent, void* p_pUserdata)' + is called for any change in the answer set. + Call 'MDNS.removeServiceQuery(hServiceQuery);' when the answers are not needed anymore + + + Reference: + Used mDNS messages: + A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 + AAAA (0x1C): eg. esp8266.local AAAA OP TTL 1234:5678::90 + PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local + PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local + PTR (0x0C, IP4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local + PTR (0x0C, IP6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local + SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local + TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 + + Some NOT used message types: + OPT (0x29): eDNS + NSEC (0x2F): DNSSEC + + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#ifndef MDNS_H +#define MDNS_H + +#include <functional> // for UdpContext.h +#include "WiFiUdp.h" +#include "lwip/udp.h" +#include "debug.h" +#include "include/UdpContext.h" +#include <limits> +#include <PolledTimeout.h> +#include <map> + + +#include "ESP8266WiFi.h" + + +namespace esp8266 +{ + +/** + LEAmDNS +*/ +namespace MDNSImplementation +{ + +//this should be defined at build time +#ifndef ARDUINO_BOARD +#define ARDUINO_BOARD "generic" +#endif + +#define MDNS_IP4_SUPPORT +//#define MDNS_IP6_SUPPORT + + +#ifdef MDNS_IP4_SUPPORT +#define MDNS_IP4_SIZE 4 +#endif +#ifdef MDNS_IP6_SUPPORT +#define MDNS_IP6_SIZE 16 +#endif +/* + Maximum length for all service txts for one service +*/ +#define MDNS_SERVICE_TXT_MAXLENGTH 1300 +/* + Maximum length for a full domain name eg. MyESP._http._tcp.local +*/ +#define MDNS_DOMAIN_MAXLENGTH 256 +/* + Maximum length of on label in a domain name (length info fits into 6 bits) +*/ +#define MDNS_DOMAIN_LABEL_MAXLENGTH 63 +/* + Maximum length of a service name eg. http +*/ +#define MDNS_SERVICE_NAME_LENGTH 15 +/* + Maximum length of a service protocol name eg. tcp +*/ +#define MDNS_SERVICE_PROTOCOL_LENGTH 3 +/* + Default timeout for static service queries +*/ +#define MDNS_QUERYSERVICES_WAIT_TIME 1000 + + +/** + MDNSResponder +*/ +class MDNSResponder +{ +public: + /* INTERFACE */ + + static constexpr auto ApiVersion = MDNSApiVersion::LEA; + + MDNSResponder(void); + virtual ~MDNSResponder(void); + + // Start the MDNS responder by setting the default hostname + // Later call MDNS::update() in every 'loop' to run the process loop + // (probing, announcing, responding, ...) + // if interfaceAddress is not specified, default interface is STA, or AP when STA is not set + bool begin(const char* p_pcHostname, const IPAddress& p_IPAddress = INADDR_ANY, uint32_t p_u32TTL = 120 /*ignored*/); + bool begin(const String& p_strHostname, const IPAddress& p_IPAddress = INADDR_ANY, uint32_t p_u32TTL = 120 /*ignored*/) + { + return begin(p_strHostname.c_str(), p_IPAddress, p_u32TTL); + } + + // Finish MDNS processing + bool close(void); + // for esp32 compatability + bool end(void); + // Change hostname (probing is restarted) + bool setHostname(const char* p_pcHostname); + // for compatibility... + bool setHostname(const String& p_strHostname); + + bool isRunning(void) + { + return (m_pUDPContext != 0); + } + + /** + hMDNSService (opaque handle to access the service) + */ + typedef const void* hMDNSService; + + // Add a new service to the MDNS responder. If no name (instance name) is given (p_pcName = 0) + // the current hostname is used. If the hostname is changed later, the instance names for + // these 'auto-named' services are changed to the new name also (and probing is restarted). + // The usual '_' before p_pcService (eg. http) and protocol (eg. tcp) may be given. + hMDNSService addService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + uint16_t p_u16Port); + // Removes a service from the MDNS responder + bool removeService(const hMDNSService p_hService); + bool removeService(const char* p_pcInstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol); + // for compatibility... + bool addService(const String& p_strServiceName, + const String& p_strProtocol, + uint16_t p_u16Port); + + + // Change the services instance name (and restart probing). + bool setServiceName(const hMDNSService p_hService, + const char* p_pcInstanceName); + //for compatibility + //Warning: this has the side effect of changing the hostname. + //TODO: implement instancename different from hostname + void setInstanceName(const char* p_pcHostname) + { + setHostname(p_pcHostname); + } + // for esp32 compatibilty + void setInstanceName(const String& s_pcHostname) + { + setInstanceName(s_pcHostname.c_str()); + } + + /** + hMDNSTxt (opaque handle to access the TXT items) + */ + typedef void* hMDNSTxt; + + // 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); + + // Remove an existing (static) MDNS TXT item from the service + bool removeServiceTxt(const hMDNSService p_hService, + const hMDNSTxt p_hTxt); + bool removeServiceTxt(const hMDNSService p_hService, + const char* p_pcKey); + bool removeServiceTxt(const char* p_pcinstanceName, + const char* p_pcServiceName, + const char* p_pcProtocol, + const char* p_pcKey); + // for compatibility... + bool addServiceTxt(const char* p_pcService, + const char* p_pcProtocol, + const char* p_pcKey, + const char* p_pcValue); + bool addServiceTxt(const String& p_strService, + const String& p_strProtocol, + const String& p_strKey, + const String& p_strValue); + + /** + MDNSDynamicServiceTxtCallbackFn + Callback function for dynamic MDNS TXT items + */ + + typedef std::function<void(const hMDNSService p_hService)> MDNSDynamicServiceTxtCallbackFunc; + + // Set a global callback for dynamic MDNS TXT items. The callback function is called + // every time, a TXT item is needed for one of the installed services. + bool setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFunc p_fnCallback); + // Set a service specific callback for dynamic MDNS TXT items. The callback function + // is called every time, a TXT item is needed for the given service. + bool setDynamicServiceTxtCallback(const hMDNSService p_hService, + MDNSDynamicServiceTxtCallbackFunc p_fnCallback); + + // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service + // Dynamic TXT items are removed right after one-time use. So they need to be added + // every time the value s needed (via callback). + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + const char* p_pcValue); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint32_t p_u32Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint16_t p_u16Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + uint8_t p_u8Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int32_t p_i32Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int16_t p_i16Value); + hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, + const char* p_pcKey, + int8_t p_i8Value); + + // Perform a (static) service query. The function returns after p_u16Timeout milliseconds + // The answers (the number of received answers is returned) can be retrieved by calling + // - answerHostname (or hostname) + // - answerIP (or IP) + // - answerPort (or port) + uint32_t queryService(const char* p_pcService, + const char* p_pcProtocol, + const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); + bool removeQuery(void); + // for compatibility... + uint32_t queryService(const String& p_strService, + const String& p_strProtocol); + + const char* answerHostname(const uint32_t p_u32AnswerIndex); + IPAddress answerIP(const uint32_t p_u32AnswerIndex); + uint16_t answerPort(const uint32_t p_u32AnswerIndex); + // for compatibility... + String hostname(const uint32_t p_u32AnswerIndex); + IPAddress IP(const uint32_t p_u32AnswerIndex); + uint16_t port(const uint32_t p_u32AnswerIndex); + + /** + hMDNSServiceQuery (opaque handle to access dynamic service queries) + */ + typedef const void* hMDNSServiceQuery; + + /** + enuServiceQueryAnswerType + */ + typedef enum _enuServiceQueryAnswerType + { + ServiceQueryAnswerType_ServiceDomain = (1 << 0), // Service instance name + ServiceQueryAnswerType_HostDomainAndPort = (1 << 1), // Host domain and service port + ServiceQueryAnswerType_Txts = (1 << 2), // TXT items +#ifdef MDNS_IP4_SUPPORT + ServiceQueryAnswerType_IP4Address = (1 << 3), // IP4 address +#endif +#ifdef MDNS_IP6_SUPPORT + ServiceQueryAnswerType_IP6Address = (1 << 4), // IP6 address +#endif + } enuServiceQueryAnswerType; + + enum class AnswerType : uint32_t + { + Unknown = 0, + ServiceDomain = ServiceQueryAnswerType_ServiceDomain, + HostDomainAndPort = ServiceQueryAnswerType_HostDomainAndPort, + Txt = ServiceQueryAnswerType_Txts, +#ifdef MDNS_IP4_SUPPORT + IP4Address = ServiceQueryAnswerType_IP4Address, +#endif +#ifdef MDNS_IP6_SUPPORT + IP6Address = ServiceQueryAnswerType_IP6Address, +#endif + }; + + /** + MDNSServiceQueryCallbackFn + Callback function for received answers for dynamic service queries + */ + struct MDNSServiceInfo; // forward declaration + typedef std::function<void(const MDNSServiceInfo& mdnsServiceInfo, + AnswerType answerType, // flag for the updated answer item + bool p_bSetContent // true: Answer component set, false: component deleted + )> MDNSServiceQueryCallbackFunc; + + // Install a dynamic service query. For every received answer (part) the given callback + // function is called. The query will be updated every time, the TTL for an answer + // has timed-out. + // The answers can also be retrieved by calling + // - answerCount + // - answerServiceDomain + // - hasAnswerHostDomain/answerHostDomain + // - hasAnswerIP4Address/answerIP4Address + // - hasAnswerIP6Address/answerIP6Address + // - hasAnswerPort/answerPort + // - hasAnswerTxts/answerTxts + hMDNSServiceQuery installServiceQuery(const char* p_pcService, + const char* p_pcProtocol, + MDNSServiceQueryCallbackFunc p_fnCallback); + // Remove a dynamic service query + bool removeServiceQuery(hMDNSServiceQuery p_hServiceQuery); + + uint32_t answerCount(const hMDNSServiceQuery p_hServiceQuery); + std::vector<MDNSResponder::MDNSServiceInfo> answerInfo(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery); + + const char* answerServiceDomain(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + bool hasAnswerHostDomain(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + const char* answerHostDomain(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); +#ifdef MDNS_IP4_SUPPORT + bool hasAnswerIP4Address(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + uint32_t answerIP4AddressCount(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + IPAddress answerIP4Address(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex); +#endif +#ifdef MDNS_IP6_SUPPORT + bool hasAnswerIP6Address(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + uint32_t answerIP6AddressCount(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + IPAddress answerIP6Address(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex, + const uint32_t p_u32AddressIndex); +#endif + bool hasAnswerPort(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + uint16_t answerPort(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + bool hasAnswerTxts(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + // Get the TXT items as a ';'-separated string + const char* answerTxts(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + + /** + MDNSProbeResultCallbackFn + Callback function for (host and service domain) probe results + */ + typedef std::function<void(const char* p_pcDomainName, + bool p_bProbeResult)> MDNSHostProbeFn; + + typedef std::function<void(MDNSResponder& resp, + const char* p_pcDomainName, + bool p_bProbeResult)> MDNSHostProbeFn1; + + typedef std::function<void(const char* p_pcServiceName, + const hMDNSService p_hMDNSService, + bool p_bProbeResult)> MDNSServiceProbeFn; + + typedef std::function<void(MDNSResponder& resp, + const char* p_pcServiceName, + const hMDNSService p_hMDNSService, + bool p_bProbeResult)> MDNSServiceProbeFn1; + + // Set a global callback function for host and service probe results + // The callback function is called, when the probing for the host domain + // (or a service domain, which hasn't got a service specific callback) + // Succeeds or fails. + // In case of failure, the failed domain name should be changed. + bool setHostProbeResultCallback(MDNSHostProbeFn p_fnCallback); + bool setHostProbeResultCallback(MDNSHostProbeFn1 p_fnCallback); + + // Set a service specific probe result callback + bool setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService, + MDNSServiceProbeFn p_fnCallback); + bool setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService, + MDNSServiceProbeFn1 p_fnCallback); + + // Application should call this whenever AP is configured/disabled + bool notifyAPChange(void); + + // 'update' should be called in every 'loop' to run the MDNS processing + bool update(void); + + // 'announce' can be called every time, the configuration of some service + // changes. Mainly, this would be changed content of TXT items. + bool announce(void); + + // Enable OTA update + hMDNSService enableArduino(uint16_t p_u16Port, + bool p_bAuthUpload = false); + + // Domain name helper + static bool indexDomain(char*& p_rpcDomain, + const char* p_pcDivider = "-", + const char* p_pcDefaultDomain = 0); + + /** STRUCTS **/ + +public: + /** + MDNSServiceInfo, used in application callbacks + */ + struct MDNSServiceInfo + { + MDNSServiceInfo(MDNSResponder& p_pM, MDNSResponder::hMDNSServiceQuery p_hS, uint32_t p_u32A) + : p_pMDNSResponder(p_pM), + p_hServiceQuery(p_hS), + p_u32AnswerIndex(p_u32A) + {}; + struct CompareKey + { + bool operator()(char const *a, char const *b) const + { + return strcmp(a, b) < 0; + } + }; + using KeyValueMap = std::map<const char*, const char*, CompareKey>; + protected: + MDNSResponder& p_pMDNSResponder; + MDNSResponder::hMDNSServiceQuery p_hServiceQuery; + uint32_t p_u32AnswerIndex; + KeyValueMap keyValueMap; + public: + const char* serviceDomain() + { + return p_pMDNSResponder.answerServiceDomain(p_hServiceQuery, p_u32AnswerIndex); + }; + bool hostDomainAvailable() + { + return (p_pMDNSResponder.hasAnswerHostDomain(p_hServiceQuery, p_u32AnswerIndex)); + } + const char* hostDomain() + { + return (hostDomainAvailable()) ? + p_pMDNSResponder.answerHostDomain(p_hServiceQuery, p_u32AnswerIndex) : nullptr; + }; + bool hostPortAvailable() + { + return (p_pMDNSResponder.hasAnswerPort(p_hServiceQuery, p_u32AnswerIndex)); + } + uint16_t hostPort() + { + return (hostPortAvailable()) ? + p_pMDNSResponder.answerPort(p_hServiceQuery, p_u32AnswerIndex) : 0; + }; + bool IP4AddressAvailable() + { + return (p_pMDNSResponder.hasAnswerIP4Address(p_hServiceQuery, p_u32AnswerIndex)); + } + std::vector<IPAddress> IP4Adresses() + { + std::vector<IPAddress> internalIP; + if (IP4AddressAvailable()) + { + uint16_t cntIP4Adress = p_pMDNSResponder.answerIP4AddressCount(p_hServiceQuery, p_u32AnswerIndex); + for (uint32_t u2 = 0; u2 < cntIP4Adress; ++u2) + { + internalIP.emplace_back(p_pMDNSResponder.answerIP4Address(p_hServiceQuery, p_u32AnswerIndex, u2)); + } + } + return internalIP; + }; + bool txtAvailable() + { + return (p_pMDNSResponder.hasAnswerTxts(p_hServiceQuery, p_u32AnswerIndex)); + } + const char* strKeyValue() + { + return (txtAvailable()) ? + p_pMDNSResponder.answerTxts(p_hServiceQuery, p_u32AnswerIndex) : nullptr; + }; + const KeyValueMap& keyValues() + { + if (txtAvailable() && keyValueMap.size() == 0) + { + for (auto kv = p_pMDNSResponder._answerKeyValue(p_hServiceQuery, p_u32AnswerIndex); kv != nullptr; kv = kv->m_pNext) + { + keyValueMap.emplace(std::pair<const char*, const char*>(kv->m_pcKey, kv->m_pcValue)); + } + } + return keyValueMap; + } + const char* value(const char* key) + { + char* result = nullptr; + + for (stcMDNSServiceTxt* pTxt = p_pMDNSResponder._answerKeyValue(p_hServiceQuery, p_u32AnswerIndex); pTxt; pTxt = pTxt->m_pNext) + { + if ((key) && + (0 == strcmp(pTxt->m_pcKey, key))) + { + result = pTxt->m_pcValue; + break; + } + } + return result; + } + }; +protected: + + /** + stcMDNSServiceTxt + */ + struct stcMDNSServiceTxt + { + stcMDNSServiceTxt* m_pNext; + char* m_pcKey; + char* m_pcValue; + bool m_bTemp; + + stcMDNSServiceTxt(const char* p_pcKey = 0, + const char* p_pcValue = 0, + bool p_bTemp = false); + stcMDNSServiceTxt(const stcMDNSServiceTxt& p_Other); + ~stcMDNSServiceTxt(void); + + stcMDNSServiceTxt& operator=(const stcMDNSServiceTxt& p_Other); + bool clear(void); + + char* allocKey(size_t p_stLength); + bool setKey(const char* p_pcKey, + size_t p_stLength); + bool setKey(const char* p_pcKey); + bool releaseKey(void); + + char* allocValue(size_t p_stLength); + bool setValue(const char* p_pcValue, + size_t p_stLength); + bool setValue(const char* p_pcValue); + bool releaseValue(void); + + bool set(const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp = false); + + bool update(const char* p_pcValue); + + size_t length(void) const; + }; + + /** + stcMDNSTxts + */ + struct stcMDNSServiceTxts + { + stcMDNSServiceTxt* m_pTxts; + + stcMDNSServiceTxts(void); + stcMDNSServiceTxts(const stcMDNSServiceTxts& p_Other); + ~stcMDNSServiceTxts(void); + + stcMDNSServiceTxts& operator=(const stcMDNSServiceTxts& p_Other); + + bool clear(void); + + bool add(stcMDNSServiceTxt* p_pTxt); + bool remove(stcMDNSServiceTxt* p_pTxt); + + bool removeTempTxts(void); + + stcMDNSServiceTxt* find(const char* p_pcKey); + const stcMDNSServiceTxt* find(const char* p_pcKey) const; + stcMDNSServiceTxt* find(const stcMDNSServiceTxt* p_pTxt); + + uint16_t length(void) const; + + size_t c_strLength(void) const; + bool c_str(char* p_pcBuffer); + + size_t bufferLength(void) const; + bool buffer(char* p_pcBuffer); + + bool compare(const stcMDNSServiceTxts& p_Other) const; + bool operator==(const stcMDNSServiceTxts& p_Other) const; + bool operator!=(const stcMDNSServiceTxts& p_Other) const; + }; + + /** + enuContentFlags + */ + typedef enum _enuContentFlags + { + // Host + ContentFlag_A = 0x01, + ContentFlag_PTR_IP4 = 0x02, + ContentFlag_PTR_IP6 = 0x04, + ContentFlag_AAAA = 0x08, + // Service + ContentFlag_PTR_TYPE = 0x10, + ContentFlag_PTR_NAME = 0x20, + ContentFlag_TXT = 0x40, + ContentFlag_SRV = 0x80, + } enuContentFlags; + + /** + stcMDNS_MsgHeader + */ + struct stcMDNS_MsgHeader + { + uint16_t m_u16ID; // Identifier + bool m_1bQR : 1; // Query/Response flag + unsigned char m_4bOpcode : 4; // Operation code + bool m_1bAA : 1; // Authoritative Answer flag + bool m_1bTC : 1; // Truncation flag + bool m_1bRD : 1; // Recursion desired + bool m_1bRA : 1; // Recursion available + unsigned char m_3bZ : 3; // Zero + unsigned char m_4bRCode : 4; // Response code + uint16_t m_u16QDCount; // Question count + uint16_t m_u16ANCount; // Answer count + uint16_t m_u16NSCount; // Authority Record count + uint16_t m_u16ARCount; // Additional Record count + + stcMDNS_MsgHeader(uint16_t p_u16ID = 0, + bool p_bQR = false, + unsigned char p_ucOpcode = 0, + bool p_bAA = false, + bool p_bTC = false, + bool p_bRD = false, + bool p_bRA = false, + unsigned char p_ucRCode = 0, + uint16_t p_u16QDCount = 0, + uint16_t p_u16ANCount = 0, + uint16_t p_u16NSCount = 0, + uint16_t p_u16ARCount = 0); + }; + + /** + stcMDNS_RRDomain + */ + struct stcMDNS_RRDomain + { + char m_acName[MDNS_DOMAIN_MAXLENGTH]; // Encoded domain name + uint16_t m_u16NameLength; // Length (incl. '\0') + + stcMDNS_RRDomain(void); + stcMDNS_RRDomain(const stcMDNS_RRDomain& p_Other); + + stcMDNS_RRDomain& operator=(const stcMDNS_RRDomain& p_Other); + + bool clear(void); + + bool addLabel(const char* p_pcLabel, + bool p_bPrependUnderline = false); + + bool compare(const stcMDNS_RRDomain& p_Other) const; + bool operator==(const stcMDNS_RRDomain& p_Other) const; + bool operator!=(const stcMDNS_RRDomain& p_Other) const; + bool operator>(const stcMDNS_RRDomain& p_Other) const; + + size_t c_strLength(void) const; + bool c_str(char* p_pcBuffer); + }; + + /** + stcMDNS_RRAttributes + */ + struct stcMDNS_RRAttributes + { + uint16_t m_u16Type; // Type + uint16_t m_u16Class; // Class, nearly always 'IN' + + stcMDNS_RRAttributes(uint16_t p_u16Type = 0, + uint16_t p_u16Class = 1 /*DNS_RRCLASS_IN Internet*/); + stcMDNS_RRAttributes(const stcMDNS_RRAttributes& p_Other); + + stcMDNS_RRAttributes& operator=(const stcMDNS_RRAttributes& p_Other); + }; + + /** + stcMDNS_RRHeader + */ + struct stcMDNS_RRHeader + { + stcMDNS_RRDomain m_Domain; + stcMDNS_RRAttributes m_Attributes; + + stcMDNS_RRHeader(void); + stcMDNS_RRHeader(const stcMDNS_RRHeader& p_Other); + + stcMDNS_RRHeader& operator=(const stcMDNS_RRHeader& p_Other); + + bool clear(void); + }; + + /** + stcMDNS_RRQuestion + */ + struct stcMDNS_RRQuestion + { + stcMDNS_RRQuestion* m_pNext; + stcMDNS_RRHeader m_Header; + bool m_bUnicast; // Unicast reply requested + + stcMDNS_RRQuestion(void); + }; + + /** + enuAnswerType + */ + typedef enum _enuAnswerType + { + AnswerType_A, + AnswerType_PTR, + AnswerType_TXT, + AnswerType_AAAA, + AnswerType_SRV, + AnswerType_Generic + } enuAnswerType; + + /** + stcMDNS_RRAnswer + */ + struct stcMDNS_RRAnswer + { + stcMDNS_RRAnswer* m_pNext; + const enuAnswerType m_AnswerType; + stcMDNS_RRHeader m_Header; + bool m_bCacheFlush; // Cache flush command bit + uint32_t m_u32TTL; // Validity time in seconds + + virtual ~stcMDNS_RRAnswer(void); + + enuAnswerType answerType(void) const; + + bool clear(void); + + protected: + stcMDNS_RRAnswer(enuAnswerType p_AnswerType, + const stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL); + }; + +#ifdef MDNS_IP4_SUPPORT + /** + stcMDNS_RRAnswerA + */ + struct stcMDNS_RRAnswerA : public stcMDNS_RRAnswer + { + IPAddress m_IPAddress; + + stcMDNS_RRAnswerA(const stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL); + ~stcMDNS_RRAnswerA(void); + + bool clear(void); + }; +#endif + + /** + stcMDNS_RRAnswerPTR + */ + struct stcMDNS_RRAnswerPTR : public stcMDNS_RRAnswer + { + stcMDNS_RRDomain m_PTRDomain; + + stcMDNS_RRAnswerPTR(const stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL); + ~stcMDNS_RRAnswerPTR(void); + + bool clear(void); + }; + + /** + stcMDNS_RRAnswerTXT + */ + struct stcMDNS_RRAnswerTXT : public stcMDNS_RRAnswer + { + stcMDNSServiceTxts m_Txts; + + stcMDNS_RRAnswerTXT(const stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL); + ~stcMDNS_RRAnswerTXT(void); + + bool clear(void); + }; + +#ifdef MDNS_IP6_SUPPORT + /** + stcMDNS_RRAnswerAAAA + */ + struct stcMDNS_RRAnswerAAAA : public stcMDNS_RRAnswer + { + //TODO: IP6Address m_IPAddress; + + stcMDNS_RRAnswerAAAA(const stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL); + ~stcMDNS_RRAnswerAAAA(void); + + bool clear(void); + }; +#endif + + /** + stcMDNS_RRAnswerSRV + */ + struct stcMDNS_RRAnswerSRV : public stcMDNS_RRAnswer + { + uint16_t m_u16Priority; + uint16_t m_u16Weight; + uint16_t m_u16Port; + stcMDNS_RRDomain m_SRVDomain; + + stcMDNS_RRAnswerSRV(const stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL); + ~stcMDNS_RRAnswerSRV(void); + + bool clear(void); + }; + + /** + stcMDNS_RRAnswerGeneric + */ + struct stcMDNS_RRAnswerGeneric : public stcMDNS_RRAnswer + { + uint16_t m_u16RDLength; // Length of variable answer + uint8_t* m_pu8RDData; // Offset of start of variable answer in packet + + stcMDNS_RRAnswerGeneric(const stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL); + ~stcMDNS_RRAnswerGeneric(void); + + bool clear(void); + }; + + + /** + enuProbingStatus + */ + typedef enum _enuProbingStatus + { + ProbingStatus_WaitingForData, + ProbingStatus_ReadyToStart, + ProbingStatus_InProgress, + ProbingStatus_Done + } enuProbingStatus; + + /** + stcProbeInformation + */ + struct stcProbeInformation + { + enuProbingStatus m_ProbingStatus; + uint8_t m_u8SentCount; // Used for probes and announcements + esp8266::polledTimeout::oneShotMs m_Timeout; // Used for probes and announcements + //clsMDNSTimeFlag m_TimeFlag; // Used for probes and announcements + bool m_bConflict; + bool m_bTiebreakNeeded; + MDNSHostProbeFn m_fnHostProbeResultCallback; + MDNSServiceProbeFn m_fnServiceProbeResultCallback; + + stcProbeInformation(void); + + bool clear(bool p_bClearUserdata = false); + }; + + + /** + stcMDNSService + */ + struct stcMDNSService + { + stcMDNSService* m_pNext; + char* m_pcName; + bool m_bAutoName; // Name was set automatically to hostname (if no name was supplied) + char* m_pcService; + char* m_pcProtocol; + uint16_t m_u16Port; + uint8_t m_u8ReplyMask; + stcMDNSServiceTxts m_Txts; + MDNSDynamicServiceTxtCallbackFunc m_fnTxtCallback; + stcProbeInformation m_ProbeInformation; + + stcMDNSService(const char* p_pcName = 0, + const char* p_pcService = 0, + const char* p_pcProtocol = 0); + ~stcMDNSService(void); + + bool setName(const char* p_pcName); + bool releaseName(void); + + bool setService(const char* p_pcService); + bool releaseService(void); + + bool setProtocol(const char* p_pcProtocol); + bool releaseProtocol(void); + }; + + /** + stcMDNSServiceQuery + */ + struct stcMDNSServiceQuery + { + /** + stcAnswer + */ + struct stcAnswer + { + /** + stcTTL + */ + struct stcTTL + { + /** + timeoutLevel_t + */ + typedef uint8_t timeoutLevel_t; + /** + TIMEOUTLEVELs + */ + const timeoutLevel_t TIMEOUTLEVEL_UNSET = 0; + const timeoutLevel_t TIMEOUTLEVEL_BASE = 80; + const timeoutLevel_t TIMEOUTLEVEL_INTERVAL = 5; + const timeoutLevel_t TIMEOUTLEVEL_FINAL = 100; + + uint32_t m_u32TTL; + esp8266::polledTimeout::oneShotMs m_TTLTimeout; + timeoutLevel_t m_timeoutLevel; + + stcTTL(void); + bool set(uint32_t p_u32TTL); + + bool flagged(void); + bool restart(void); + + bool prepareDeletion(void); + bool finalTimeoutLevel(void) const; + + unsigned long timeout(void) const; + }; +#ifdef MDNS_IP4_SUPPORT + /** + stcIP4Address + */ + struct stcIP4Address + { + stcIP4Address* m_pNext; + IPAddress m_IPAddress; + stcTTL m_TTL; + + stcIP4Address(IPAddress p_IPAddress, + uint32_t p_u32TTL = 0); + }; +#endif +#ifdef MDNS_IP6_SUPPORT + /** + stcIP6Address + */ + struct stcIP6Address + { + stcIP6Address* m_pNext; + IP6Address m_IPAddress; + stcTTL m_TTL; + + stcIP6Address(IPAddress p_IPAddress, + uint32_t p_u32TTL = 0); + }; +#endif + + stcAnswer* m_pNext; + // The service domain is the first 'answer' (from PTR answer, using service and protocol) to be set + // Defines the key for additional answer, like host domain, etc. + stcMDNS_RRDomain m_ServiceDomain; // 1. level answer (PTR), eg. MyESP._http._tcp.local + char* m_pcServiceDomain; + stcTTL m_TTLServiceDomain; + stcMDNS_RRDomain m_HostDomain; // 2. level answer (SRV, using service domain), eg. esp8266.local + char* m_pcHostDomain; + uint16_t m_u16Port; // 2. level answer (SRV, using service domain), eg. 5000 + stcTTL m_TTLHostDomainAndPort; + stcMDNSServiceTxts m_Txts; // 2. level answer (TXT, using service domain), eg. c#=1 + char* m_pcTxts; + stcTTL m_TTLTxts; +#ifdef MDNS_IP4_SUPPORT + stcIP4Address* m_pIP4Addresses; // 3. level answer (A, using host domain), eg. 123.456.789.012 +#endif +#ifdef MDNS_IP6_SUPPORT + stcIP6Address* m_pIP6Addresses; // 3. level answer (AAAA, using host domain), eg. 1234::09 +#endif + uint32_t m_u32ContentFlags; + + stcAnswer(void); + ~stcAnswer(void); + + bool clear(void); + + char* allocServiceDomain(size_t p_stLength); + bool releaseServiceDomain(void); + + char* allocHostDomain(size_t p_stLength); + bool releaseHostDomain(void); + + char* allocTxts(size_t p_stLength); + bool releaseTxts(void); + +#ifdef MDNS_IP4_SUPPORT + bool releaseIP4Addresses(void); + bool addIP4Address(stcIP4Address* p_pIP4Address); + bool removeIP4Address(stcIP4Address* p_pIP4Address); + const stcIP4Address* findIP4Address(const IPAddress& p_IPAddress) const; + stcIP4Address* findIP4Address(const IPAddress& p_IPAddress); + uint32_t IP4AddressCount(void) const; + const stcIP4Address* IP4AddressAtIndex(uint32_t p_u32Index) const; + stcIP4Address* IP4AddressAtIndex(uint32_t p_u32Index); +#endif +#ifdef MDNS_IP6_SUPPORT + bool releaseIP6Addresses(void); + bool addIP6Address(stcIP6Address* p_pIP6Address); + bool removeIP6Address(stcIP6Address* p_pIP6Address); + const stcIP6Address* findIP6Address(const IPAddress& p_IPAddress) const; + stcIP6Address* findIP6Address(const IPAddress& p_IPAddress); + uint32_t IP6AddressCount(void) const; + const stcIP6Address* IP6AddressAtIndex(uint32_t p_u32Index) const; + stcIP6Address* IP6AddressAtIndex(uint32_t p_u32Index); +#endif + }; + + stcMDNSServiceQuery* m_pNext; + stcMDNS_RRDomain m_ServiceTypeDomain; // eg. _http._tcp.local + MDNSServiceQueryCallbackFunc m_fnCallback; + bool m_bLegacyQuery; + uint8_t m_u8SentCount; + esp8266::polledTimeout::oneShotMs m_ResendTimeout; + bool m_bAwaitingAnswers; + stcAnswer* m_pAnswers; + + stcMDNSServiceQuery(void); + ~stcMDNSServiceQuery(void); + + bool clear(void); + + uint32_t answerCount(void) const; + const stcAnswer* answerAtIndex(uint32_t p_u32Index) const; + stcAnswer* answerAtIndex(uint32_t p_u32Index); + uint32_t indexOfAnswer(const stcAnswer* p_pAnswer) const; + + bool addAnswer(stcAnswer* p_pAnswer); + bool removeAnswer(stcAnswer* p_pAnswer); + + stcAnswer* findAnswerForServiceDomain(const stcMDNS_RRDomain& p_ServiceDomain); + stcAnswer* findAnswerForHostDomain(const stcMDNS_RRDomain& p_HostDomain); + }; + + /** + stcMDNSSendParameter + */ + struct stcMDNSSendParameter + { + protected: + /** + stcDomainCacheItem + */ + struct stcDomainCacheItem + { + stcDomainCacheItem* m_pNext; + const void* m_pHostnameOrService; // Opaque id for host or service domain (pointer) + bool m_bAdditionalData; // Opaque flag for special info (service domain included) + uint16_t m_u16Offset; // Offset in UDP output buffer + + stcDomainCacheItem(const void* p_pHostnameOrService, + bool p_bAdditionalData, + uint32_t p_u16Offset); + }; + + public: + uint16_t m_u16ID; // Query ID (used only in lagacy queries) + stcMDNS_RRQuestion* m_pQuestions; // A list of queries + uint8_t m_u8HostReplyMask; // Flags for reply components/answers + bool m_bLegacyQuery; // Flag: Legacy query + bool m_bResponse; // Flag: Response to a query + bool m_bAuthorative; // Flag: Authorative (owner) response + bool m_bCacheFlush; // Flag: Clients should flush their caches + bool m_bUnicast; // Flag: Unicast response + bool m_bUnannounce; // Flag: Unannounce service + uint16_t m_u16Offset; // Current offset in UDP write buffer (mainly for domain cache) + stcDomainCacheItem* m_pDomainCacheItems; // Cached host and service domains + + stcMDNSSendParameter(void); + ~stcMDNSSendParameter(void); + + bool clear(void); + + bool shiftOffset(uint16_t p_u16Shift); + + bool addDomainCacheItem(const void* p_pHostnameOrService, + bool p_bAdditionalData, + uint16_t p_u16Offset); + uint16_t findCachedDomainOffset(const void* p_pHostnameOrService, + bool p_bAdditionalData) const; + }; + + // Instance variables + stcMDNSService* m_pServices; + UdpContext* m_pUDPContext; + char* m_pcHostname; + stcMDNSServiceQuery* m_pServiceQueries; + WiFiEventHandler m_DisconnectedHandler; + WiFiEventHandler m_GotIPHandler; + MDNSDynamicServiceTxtCallbackFunc m_fnServiceTxtCallback; + bool m_bPassivModeEnabled; + stcProbeInformation m_HostProbeInformation; + CONST netif* m_netif; // network interface to run on + + /** CONTROL **/ + /* MAINTENANCE */ + bool _process(bool p_bUserContext); + bool _restart(void); + + /* RECEIVING */ + bool _parseMessage(void); + bool _parseQuery(const stcMDNS_MsgHeader& p_Header); + + bool _parseResponse(const stcMDNS_MsgHeader& p_Header); + bool _processAnswers(const stcMDNS_RRAnswer* p_pPTRAnswers); + bool _processPTRAnswer(const stcMDNS_RRAnswerPTR* p_pPTRAnswer, + bool& p_rbFoundNewKeyAnswer); + bool _processSRVAnswer(const stcMDNS_RRAnswerSRV* p_pSRVAnswer, + bool& p_rbFoundNewKeyAnswer); + bool _processTXTAnswer(const stcMDNS_RRAnswerTXT* p_pTXTAnswer); +#ifdef MDNS_IP4_SUPPORT + bool _processAAnswer(const stcMDNS_RRAnswerA* p_pAAnswer); +#endif +#ifdef MDNS_IP6_SUPPORT + bool _processAAAAAnswer(const stcMDNS_RRAnswerAAAA* p_pAAAAAnswer); +#endif + + /* PROBING */ + bool _updateProbeStatus(void); + bool _resetProbeStatus(bool p_bRestart = true); + bool _hasProbesWaitingForAnswers(void) const; + bool _sendHostProbe(void); + bool _sendServiceProbe(stcMDNSService& p_rService); + bool _cancelProbingForHost(void); + bool _cancelProbingForService(stcMDNSService& p_rService); + + /* ANNOUNCE */ + bool _announce(bool p_bAnnounce, + bool p_bIncludeServices); + bool _announceService(stcMDNSService& p_rService, + bool p_bAnnounce = true); + + /* SERVICE QUERY CACHE */ + bool _hasServiceQueriesWaitingForAnswers(void) const; + bool _checkServiceQueryCache(void); + + /** TRANSFER **/ + /* SENDING */ + bool _sendMDNSMessage(stcMDNSSendParameter& p_SendParameter); + bool _sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParameter& p_rSendParameter); + bool _prepareMDNSMessage(stcMDNSSendParameter& p_SendParameter, + IPAddress p_IPAddress); + bool _sendMDNSServiceQuery(const stcMDNSServiceQuery& p_ServiceQuery); + bool _sendMDNSQuery(const stcMDNS_RRDomain& p_QueryDomain, + uint16_t p_u16QueryType, + stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers = 0); + + const IPAddress _getResponseMulticastInterface() const + { + return IPAddress(m_netif->ip_addr); + } + + uint8_t _replyMaskForHost(const stcMDNS_RRHeader& p_RRHeader, + bool* p_pbFullNameMatch = 0) const; + uint8_t _replyMaskForService(const stcMDNS_RRHeader& p_RRHeader, + const stcMDNSService& p_Service, + bool* p_pbFullNameMatch = 0) const; + + /* RESOURCE RECORD */ + bool _readRRQuestion(stcMDNS_RRQuestion& p_rQuestion); + bool _readRRAnswer(stcMDNS_RRAnswer*& p_rpAnswer); +#ifdef MDNS_IP4_SUPPORT + bool _readRRAnswerA(stcMDNS_RRAnswerA& p_rRRAnswerA, + uint16_t p_u16RDLength); +#endif + bool _readRRAnswerPTR(stcMDNS_RRAnswerPTR& p_rRRAnswerPTR, + uint16_t p_u16RDLength); + bool _readRRAnswerTXT(stcMDNS_RRAnswerTXT& p_rRRAnswerTXT, + uint16_t p_u16RDLength); +#ifdef MDNS_IP6_SUPPORT + bool _readRRAnswerAAAA(stcMDNS_RRAnswerAAAA& p_rRRAnswerAAAA, + uint16_t p_u16RDLength); +#endif + bool _readRRAnswerSRV(stcMDNS_RRAnswerSRV& p_rRRAnswerSRV, + uint16_t p_u16RDLength); + bool _readRRAnswerGeneric(stcMDNS_RRAnswerGeneric& p_rRRAnswerGeneric, + uint16_t p_u16RDLength); + + bool _readRRHeader(stcMDNS_RRHeader& p_rHeader); + bool _readRRDomain(stcMDNS_RRDomain& p_rRRDomain); + bool _readRRDomain_Loop(stcMDNS_RRDomain& p_rRRDomain, + uint8_t p_u8Depth); + bool _readRRAttributes(stcMDNS_RRAttributes& p_rAttributes); + + /* DOMAIN NAMES */ + bool _buildDomainForHost(const char* p_pcHostname, + stcMDNS_RRDomain& p_rHostDomain) const; + bool _buildDomainForDNSSD(stcMDNS_RRDomain& p_rDNSSDDomain) const; + bool _buildDomainForService(const stcMDNSService& p_Service, + bool p_bIncludeName, + stcMDNS_RRDomain& p_rServiceDomain) const; + bool _buildDomainForService(const char* p_pcService, + const char* p_pcProtocol, + stcMDNS_RRDomain& p_rServiceDomain) const; +#ifdef MDNS_IP4_SUPPORT + bool _buildDomainForReverseIP4(IPAddress p_IP4Address, + stcMDNS_RRDomain& p_rReverseIP4Domain) const; +#endif +#ifdef MDNS_IP6_SUPPORT + bool _buildDomainForReverseIP6(IPAddress p_IP4Address, + stcMDNS_RRDomain& p_rReverseIP6Domain) const; +#endif + + /* UDP */ + bool _udpReadBuffer(unsigned char* p_pBuffer, + size_t p_stLength); + bool _udpRead8(uint8_t& p_ru8Value); + bool _udpRead16(uint16_t& p_ru16Value); + bool _udpRead32(uint32_t& p_ru32Value); + + bool _udpAppendBuffer(const unsigned char* p_pcBuffer, + size_t p_stLength); + bool _udpAppend8(uint8_t p_u8Value); + bool _udpAppend16(uint16_t p_u16Value); + bool _udpAppend32(uint32_t p_u32Value); + +#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER + bool _udpDump(bool p_bMovePointer = false); + bool _udpDump(unsigned p_uOffset, + unsigned p_uLength); +#endif + + /* READ/WRITE MDNS STRUCTS */ + bool _readMDNSMsgHeader(stcMDNS_MsgHeader& p_rMsgHeader); + + bool _write8(uint8_t p_u8Value, + stcMDNSSendParameter& p_rSendParameter); + bool _write16(uint16_t p_u16Value, + stcMDNSSendParameter& p_rSendParameter); + bool _write32(uint32_t p_u32Value, + stcMDNSSendParameter& p_rSendParameter); + + bool _writeMDNSMsgHeader(const stcMDNS_MsgHeader& p_MsgHeader, + stcMDNSSendParameter& p_rSendParameter); + bool _writeMDNSRRAttributes(const stcMDNS_RRAttributes& p_Attributes, + stcMDNSSendParameter& p_rSendParameter); + bool _writeMDNSRRDomain(const stcMDNS_RRDomain& p_Domain, + stcMDNSSendParameter& p_rSendParameter); + bool _writeMDNSHostDomain(const char* m_pcHostname, + bool p_bPrependRDLength, + stcMDNSSendParameter& p_rSendParameter); + bool _writeMDNSServiceDomain(const stcMDNSService& p_Service, + bool p_bIncludeName, + bool p_bPrependRDLength, + stcMDNSSendParameter& p_rSendParameter); + + bool _writeMDNSQuestion(stcMDNS_RRQuestion& p_Question, + stcMDNSSendParameter& p_rSendParameter); + +#ifdef MDNS_IP4_SUPPORT + bool _writeMDNSAnswer_A(IPAddress p_IPAddress, + stcMDNSSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_PTR_IP4(IPAddress p_IPAddress, + stcMDNSSendParameter& p_rSendParameter); +#endif + bool _writeMDNSAnswer_PTR_TYPE(stcMDNSService& p_rService, + stcMDNSSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_PTR_NAME(stcMDNSService& p_rService, + stcMDNSSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_TXT(stcMDNSService& p_rService, + stcMDNSSendParameter& p_rSendParameter); +#ifdef MDNS_IP6_SUPPORT + bool _writeMDNSAnswer_AAAA(IPAddress p_IPAddress, + stcMDNSSendParameter& p_rSendParameter); + bool _writeMDNSAnswer_PTR_IP6(IPAddress p_IPAddress, + stcMDNSSendParameter& p_rSendParameter); +#endif + bool _writeMDNSAnswer_SRV(stcMDNSService& p_rService, + stcMDNSSendParameter& p_rSendParameter); + + /** HELPERS **/ + /* UDP CONTEXT */ + bool _callProcess(void); + bool _allocUDPContext(void); + bool _releaseUDPContext(void); + + /* SERVICE QUERY */ + stcMDNSServiceQuery* _allocServiceQuery(void); + bool _removeServiceQuery(stcMDNSServiceQuery* p_pServiceQuery); + bool _removeLegacyServiceQuery(void); + stcMDNSServiceQuery* _findServiceQuery(hMDNSServiceQuery p_hServiceQuery); + stcMDNSServiceQuery* _findLegacyServiceQuery(void); + bool _releaseServiceQueries(void); + stcMDNSServiceQuery* _findNextServiceQueryByServiceType(const stcMDNS_RRDomain& p_ServiceDomain, + const stcMDNSServiceQuery* p_pPrevServiceQuery); + + /* HOSTNAME */ + bool _setHostname(const char* p_pcHostname); + bool _releaseHostname(void); + + /* SERVICE */ + stcMDNSService* _allocService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + uint16_t p_u16Port); + bool _releaseService(stcMDNSService* p_pService); + bool _releaseServices(void); + + stcMDNSService* _findService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol); + stcMDNSService* _findService(const hMDNSService p_hService); + + size_t _countServices(void) const; + + /* SERVICE TXT */ + stcMDNSServiceTxt* _allocServiceTxt(stcMDNSService* p_pService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp); + bool _releaseServiceTxt(stcMDNSService* p_pService, + stcMDNSServiceTxt* p_pTxt); + stcMDNSServiceTxt* _updateServiceTxt(stcMDNSService* p_pService, + stcMDNSServiceTxt* p_pTxt, + const char* p_pcValue, + bool p_bTemp); + + stcMDNSServiceTxt* _findServiceTxt(stcMDNSService* p_pService, + const char* p_pcKey); + stcMDNSServiceTxt* _findServiceTxt(stcMDNSService* p_pService, + const hMDNSTxt p_hTxt); + + stcMDNSServiceTxt* _addServiceTxt(stcMDNSService* p_pService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp); + + stcMDNSServiceTxt* _answerKeyValue(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex); + + bool _collectServiceTxts(stcMDNSService& p_rService); + bool _releaseTempServiceTxts(stcMDNSService& p_rService); + const stcMDNSServiceTxt* _serviceTxts(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol); + + /* MISC */ +#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER + bool _printRRDomain(const stcMDNS_RRDomain& p_rRRDomain) const; + bool _printRRAnswer(const MDNSResponder::stcMDNS_RRAnswer& p_RRAnswer) const; +#endif +}; + +}// namespace MDNSImplementation + +}// namespace esp8266 + +#endif // MDNS_H diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index cee90c907c..740b77db6f 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -22,6 +22,7 @@ */ +#include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" #ifdef MDNS_IPV4_SUPPORT diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index ff590473c7..ceee11834a 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -129,9 +129,9 @@ /* Enable/disable debug trace macros */ -#ifdef DEBUG_ESP_MDNS_RESPONDER -//#define DEBUG_ESP_MDNS_INFO -//#define DEBUG_ESP_MDNS_INFO2 +#if defined(DEBUG_ESP_PORT) && defined(DEBUG_ESP_MDNS_RESPONDER) +#define DEBUG_ESP_MDNS_INFO +#define DEBUG_ESP_MDNS_INFO2 #define DEBUG_ESP_MDNS_ERR #define DEBUG_ESP_MDNS_TX #define DEBUG_ESP_MDNS_RX @@ -144,7 +144,7 @@ #define DEBUG_EX_INFO(A) #endif #ifdef DEBUG_ESP_MDNS_INFO2 -#define DEBUG_EX_INFO2(A) A +#define DEBUG_EX_INFO2(A) A #else #define DEBUG_EX_INFO2(A) #endif @@ -340,6 +340,9 @@ class clsLEAMDNSHost }; public: + + static constexpr auto ApiVersion = MDNSApiVersion::LEAv2; + /** clsServiceTxt */ @@ -621,6 +624,7 @@ class clsLEAMDNSHost */ using list = std::list<clsService*>; }; + using hMDNSService = clsService; // backward compatibility with LEAmDNS protected: /** diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index efc9d1879e..a061d77da8 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -22,6 +22,7 @@ */ +#include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp index b449d1cd08..bc7316be88 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp @@ -22,6 +22,7 @@ */ +#include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index b2fe64072a..e027f494ac 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -22,6 +22,7 @@ */ +#include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index f4a187b667..36b5ece554 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -23,7 +23,7 @@ */ #include <coredecls.h> // for can_yield() - +#include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index 83ecf0c8a4..d3d4849a54 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -22,6 +22,7 @@ */ +#include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 896018f81d..151555d15c 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -4,6 +4,7 @@ */ +#include "ESP8266mDNS.h" #include "LEAmDNS2_Legacy.h" diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp new file mode 100644 index 0000000000..0e46651d5f --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp @@ -0,0 +1,2135 @@ +/* + LEAmDNS_Control.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#include <sys/time.h> +#include <IPAddress.h> +#include <AddrList.h> +#include <lwip/ip_addr.h> +#include <WString.h> +#include <cstdint> + +/* + ESP8266mDNS Control.cpp +*/ + +extern "C" { +#include "user_interface.h" +} + +#include "ESP8266mDNS.h" +#include "LEAmDNS_lwIPdefs.h" +#include "LEAmDNS_Priv.h" + +namespace esp8266 +{ +/* + LEAmDNS +*/ +namespace MDNSImplementation +{ + +/** + CONTROL +*/ + + +/** + MAINTENANCE +*/ + +/* + MDNSResponder::_process + + Run the MDNS process. + Is called, every time the UDPContext receives data AND + should be called in every 'loop' by calling 'MDNS::update()'. + +*/ +bool MDNSResponder::_process(bool p_bUserContext) +{ + + bool bResult = true; + + if (!p_bUserContext) + { + + if ((m_pUDPContext) && // UDPContext available AND + (m_pUDPContext->next())) // has content + { + + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _update: Calling _parseMessage\n"));); + bResult = _parseMessage(); + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parsePacket %s\n"), (bResult ? "succeeded" : "FAILED"));); + } + } + else + { + bResult = (m_netif != nullptr) && + (m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running + _updateProbeStatus() && // Probing + _checkServiceQueryCache(); // Service query cache check + } + return bResult; +} + +/* + MDNSResponder::_restart +*/ +bool MDNSResponder::_restart(void) +{ + + return ((m_netif != nullptr) && + (m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running + (_resetProbeStatus(true)) && // Stop and restart probing + (_allocUDPContext())); // Restart UDP +} + + +/** + RECEIVING +*/ + +/* + MDNSResponder::_parseMessage +*/ +bool MDNSResponder::_parseMessage(void) +{ + DEBUG_EX_INFO( + unsigned long ulStartTime = millis(); + unsigned uStartMemory = ESP.getFreeHeap(); + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage (Time: %lu ms, heap: %u bytes, from %s(%u), to %s(%u))\n"), ulStartTime, uStartMemory, + IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str(), m_pUDPContext->getRemotePort(), + IPAddress(m_pUDPContext->getDestAddress()).toString().c_str(), m_pUDPContext->getLocalPort()); + ); + //DEBUG_EX_INFO(_udpDump();); + + bool bResult = false; + + stcMDNS_MsgHeader header; + if (_readMDNSMsgHeader(header)) + { + if (0 == header.m_4bOpcode) // A standard query + { + if (header.m_1bQR) // Received a response -> answers to a query + { + //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: Reading answers: ID:%u, Q:%u, A:%u, NS:%u, AR:%u\n"), header.m_u16ID, header.m_u16QDCount, header.m_u16ANCount, header.m_u16NSCount, header.m_u16ARCount);); + bResult = _parseResponse(header); + } + else // Received a query (Questions) + { + //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: Reading query: ID:%u, Q:%u, A:%u, NS:%u, AR:%u\n"), header.m_u16ID, header.m_u16QDCount, header.m_u16ANCount, header.m_u16NSCount, header.m_u16ARCount);); + bResult = _parseQuery(header); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: Received UNEXPECTED opcode:%u. Ignoring message!\n"), header.m_4bOpcode);); + m_pUDPContext->flush(); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: FAILED to read header\n"));); + m_pUDPContext->flush(); + } + DEBUG_EX_INFO( + unsigned uFreeHeap = ESP.getFreeHeap(); + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: Done (%s after %lu ms, ate %i bytes, remaining %u)\n\n"), (bResult ? "Succeeded" : "FAILED"), (millis() - ulStartTime), (uStartMemory - uFreeHeap), uFreeHeap); + ); + return bResult; +} + +/* + MDNSResponder::_parseQuery + + Queries are of interest in two cases: + 1. allow for tiebreaking while probing in the case of a race condition between two instances probing for + the same name at the same time + 2. provide answers to questions for our host domain or any presented service + + When reading the questions, a set of (planned) responses is created, eg. a reverse PTR question for the host domain + gets an A (IP address) response, a PTR question for the _services._dns-sd domain gets a PTR (type) response for any + registered service, ... + + As any mDNS responder should be able to handle 'legacy' queries (from DNS clients), this case is handled here also. + Legacy queries have got only one (unicast) question and are directed to the local DNS port (not the multicast port). + + 1. +*/ +bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHeader) +{ + + bool bResult = true; + + stcMDNSSendParameter sendParameter; + uint8_t u8HostOrServiceReplies = 0; + for (uint16_t qd = 0; ((bResult) && (qd < p_MsgHeader.m_u16QDCount)); ++qd) + { + + stcMDNS_RRQuestion questionRR; + if ((bResult = _readRRQuestion(questionRR))) + { + // Define host replies, BUT only answer queries after probing is done + u8HostOrServiceReplies = + sendParameter.m_u8HostReplyMask |= (((m_bPassivModeEnabled) || + (ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus)) + ? _replyMaskForHost(questionRR.m_Header, 0) + : 0); + DEBUG_EX_INFO(if (u8HostOrServiceReplies) + { + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Host reply needed 0x%X\n"), u8HostOrServiceReplies); + }); + + // Check tiebreak need for host domain + if (ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) + { + bool bFullNameMatch = false; + if ((_replyMaskForHost(questionRR.m_Header, &bFullNameMatch)) && + (bFullNameMatch)) + { + // We're in 'probing' state and someone is asking for our host domain: this might be + // a race-condition: Two host with the same domain names try simutanously to probe their domains + // See: RFC 6762, 8.2 (Tiebraking) + // However, we're using a max. reduced approach for tiebreaking here: The higher IP-address wins! + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Possible race-condition for host domain detected while probing.\n"));); + + m_HostProbeInformation.m_bTiebreakNeeded = true; + } + } + + // Define service replies + for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) + { + // Define service replies, BUT only answer queries after probing is done + uint8_t u8ReplyMaskForQuestion = (((m_bPassivModeEnabled) || + (ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus)) + ? _replyMaskForService(questionRR.m_Header, *pService, 0) + : 0); + u8HostOrServiceReplies |= (pService->m_u8ReplyMask |= u8ReplyMaskForQuestion); + DEBUG_EX_INFO(if (u8ReplyMaskForQuestion) + { + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service reply needed for (%s.%s.%s): 0x%X (%s)\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol, u8ReplyMaskForQuestion, IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str()); + }); + + // Check tiebreak need for service domain + if (ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) + { + bool bFullNameMatch = false; + if ((_replyMaskForService(questionRR.m_Header, *pService, &bFullNameMatch)) && + (bFullNameMatch)) + { + // We're in 'probing' state and someone is asking for this service domain: this might be + // a race-condition: Two services with the same domain names try simutanously to probe their domains + // See: RFC 6762, 8.2 (Tiebraking) + // However, we're using a max. reduced approach for tiebreaking here: The 'higher' SRV host wins! + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Possible race-condition for service domain %s.%s.%s detected while probing.\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); + + pService->m_ProbeInformation.m_bTiebreakNeeded = true; + } + } + } + + // Handle unicast and legacy specialities + // If only one question asks for unicast reply, the whole reply packet is send unicast + if (((DNS_MQUERY_PORT != m_pUDPContext->getRemotePort()) || // Unicast (maybe legacy) query OR + (questionRR.m_bUnicast)) && // Expressivly unicast query + (!sendParameter.m_bUnicast)) + { + + sendParameter.m_bUnicast = true; + sendParameter.m_bCacheFlush = false; + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Unicast response for %s!\n"), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str());); + + if ((DNS_MQUERY_PORT != m_pUDPContext->getRemotePort()) && // Unicast (maybe legacy) query AND + (1 == p_MsgHeader.m_u16QDCount) && // Only one question AND + ((sendParameter.m_u8HostReplyMask) || // Host replies OR + (u8HostOrServiceReplies))) // Host or service replies available + { + // We're a match for this legacy query, BUT + // make sure, that the query comes from a local host + ip_info IPInfo_Local; + ip_info IPInfo_Remote; + if (((IPInfo_Remote.ip.addr = m_pUDPContext->getRemoteAddress())) && + (((wifi_get_ip_info(SOFTAP_IF, &IPInfo_Local)) && + (ip4_addr_netcmp(&IPInfo_Remote.ip, &IPInfo_Local.ip, &IPInfo_Local.netmask))) || // Remote IP in SOFTAP's subnet OR + ((wifi_get_ip_info(STATION_IF, &IPInfo_Local)) && + (ip4_addr_netcmp(&IPInfo_Remote.ip, &IPInfo_Local.ip, &IPInfo_Local.netmask))))) // Remote IP in STATION's subnet + { + + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Legacy query from local host %s, id %u!\n"), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str(), p_MsgHeader.m_u16ID);); + + sendParameter.m_u16ID = p_MsgHeader.m_u16ID; + sendParameter.m_bLegacyQuery = true; + sendParameter.m_pQuestions = new stcMDNS_RRQuestion; + if ((bResult = (0 != sendParameter.m_pQuestions))) + { + sendParameter.m_pQuestions->m_Header.m_Domain = questionRR.m_Header.m_Domain; + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = questionRR.m_Header.m_Attributes.m_u16Type; + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = questionRR.m_Header.m_Attributes.m_u16Class; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: FAILED to add legacy question!\n"));); + } + } + else + { + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Legacy query from NON-LOCAL host!\n"));); + bResult = false; + } + } + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: FAILED to read question!\n"));); + } + } // for questions + + //DEBUG_EX_INFO(if (u8HostOrServiceReplies) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Reply needed: %u (%s: %s->%s)\n"), u8HostOrServiceReplies, clsTimeSyncer::timestr(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str(), IPAddress(m_pUDPContext->getDestAddress()).toString().c_str()); } ); + + // Handle known answers + uint32_t u32Answers = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); + DEBUG_EX_INFO(if ((u8HostOrServiceReplies) && (u32Answers)) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Known answers(%u):\n"), u32Answers); + }); + + for (uint32_t an = 0; ((bResult) && (an < u32Answers)); ++an) + { + stcMDNS_RRAnswer* pKnownRRAnswer = 0; + if (((bResult = _readRRAnswer(pKnownRRAnswer))) && + (pKnownRRAnswer)) + { + + if ((DNS_RRTYPE_ANY != pKnownRRAnswer->m_Header.m_Attributes.m_u16Type) && // No ANY type answer + (DNS_RRCLASS_ANY != pKnownRRAnswer->m_Header.m_Attributes.m_u16Class)) // No ANY class answer + { + + // Find match between planned answer (sendParameter.m_u8HostReplyMask) and this 'known answer' + uint8_t u8HostMatchMask = (sendParameter.m_u8HostReplyMask & _replyMaskForHost(pKnownRRAnswer->m_Header)); + if ((u8HostMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND + ((MDNS_HOST_TTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new host TTL (120s) + { + + // Compare contents + if (AnswerType_PTR == pKnownRRAnswer->answerType()) + { + stcMDNS_RRDomain hostDomain; + if ((_buildDomainForHost(m_pcHostname, hostDomain)) && + (((stcMDNS_RRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain == hostDomain)) + { + // Host domain match +#ifdef MDNS_IP4_SUPPORT + if (u8HostMatchMask & ContentFlag_PTR_IP4) + { + // IP4 PTR was asked for, but is already known -> skipping + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP4 PTR already known... skipping!\n"));); + sendParameter.m_u8HostReplyMask &= ~ContentFlag_PTR_IP4; + } +#endif +#ifdef MDNS_IP6_SUPPORT + if (u8HostMatchMask & ContentFlag_PTR_IP6) + { + // IP6 PTR was asked for, but is already known -> skipping + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP6 PTR already known... skipping!\n"));); + sendParameter.m_u8HostReplyMask &= ~ContentFlag_PTR_IP6; + } +#endif + } + } + else if (u8HostMatchMask & ContentFlag_A) + { + // IP4 address was asked for +#ifdef MDNS_IP4_SUPPORT + if ((AnswerType_A == pKnownRRAnswer->answerType()) && + (((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == _getResponseMulticastInterface())) + { + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP4 address already known... skipping!\n"));); + sendParameter.m_u8HostReplyMask &= ~ContentFlag_A; + } // else: RData NOT IP4 length !! +#endif + } + else if (u8HostMatchMask & ContentFlag_AAAA) + { + // IP6 address was asked for +#ifdef MDNS_IP6_SUPPORT + if ((AnswerType_AAAA == pAnswerRR->answerType()) && + (((stcMDNS_RRAnswerAAAA*)pAnswerRR)->m_IPAddress == _getResponseMulticastInterface())) + { + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP6 address already known... skipping!\n"));); + sendParameter.m_u8HostReplyMask &= ~ContentFlag_AAAA; + } // else: RData NOT IP6 length !! +#endif + } + } // Host match /*and TTL*/ + + // + // Check host tiebreak possibility + if (m_HostProbeInformation.m_bTiebreakNeeded) + { + stcMDNS_RRDomain hostDomain; + if ((_buildDomainForHost(m_pcHostname, hostDomain)) && + (pKnownRRAnswer->m_Header.m_Domain == hostDomain)) + { + // Host domain match +#ifdef MDNS_IP4_SUPPORT + if (AnswerType_A == pKnownRRAnswer->answerType()) + { + IPAddress localIPAddress(_getResponseMulticastInterface()); + if (((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) + { + // SAME IP address -> We've received an old message from ourselfs (same IP) + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (IP4) WON (was an old message)!\n"));); + m_HostProbeInformation.m_bTiebreakNeeded = false; + } + else + { + if ((uint32_t)(((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress) > (uint32_t)localIPAddress) // The OTHER IP is 'higher' -> LOST + { + // LOST tiebreak + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (IP4) LOST (lower)!\n"));); + _cancelProbingForHost(); + m_HostProbeInformation.m_bTiebreakNeeded = false; + } + else // WON tiebreak + { + //TiebreakState = TiebreakState_Won; // We received an 'old' message from ourselfs -> Just ignore + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (IP4) WON (higher IP)!\n"));); + m_HostProbeInformation.m_bTiebreakNeeded = false; + } + } + } +#endif +#ifdef MDNS_IP6_SUPPORT + if (AnswerType_AAAA == pAnswerRR->answerType()) + { + // TODO + } +#endif + } + } // Host tiebreak possibility + + // Check service answers + for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) + { + + uint8_t u8ServiceMatchMask = (pService->m_u8ReplyMask & _replyMaskForService(pKnownRRAnswer->m_Header, *pService)); + + if ((u8ServiceMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND + ((MDNS_SERVICE_TTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new service TTL (4500s) + { + + if (AnswerType_PTR == pKnownRRAnswer->answerType()) + { + stcMDNS_RRDomain serviceDomain; + if ((u8ServiceMatchMask & ContentFlag_PTR_TYPE) && + (_buildDomainForService(*pService, false, serviceDomain)) && + (serviceDomain == ((stcMDNS_RRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service type PTR already known... skipping!\n"));); + pService->m_u8ReplyMask &= ~ContentFlag_PTR_TYPE; + } + if ((u8ServiceMatchMask & ContentFlag_PTR_NAME) && + (_buildDomainForService(*pService, true, serviceDomain)) && + (serviceDomain == ((stcMDNS_RRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service name PTR already known... skipping!\n"));); + pService->m_u8ReplyMask &= ~ContentFlag_PTR_NAME; + } + } + else if (u8ServiceMatchMask & ContentFlag_SRV) + { + DEBUG_EX_ERR(if (AnswerType_SRV != pKnownRRAnswer->answerType()) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: ERROR! INVALID answer type (SRV)!\n"));); + stcMDNS_RRDomain hostDomain; + if ((_buildDomainForHost(m_pcHostname, hostDomain)) && + (hostDomain == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain)) // Host domain match + { + + if ((MDNS_SRV_PRIORITY == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_u16Priority) && + (MDNS_SRV_WEIGHT == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_u16Weight) && + (pService->m_u16Port == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_u16Port)) + { + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service SRV answer already known... skipping!\n"));); + pService->m_u8ReplyMask &= ~ContentFlag_SRV; + } // else: Small differences -> send update message + } + } + else if (u8ServiceMatchMask & ContentFlag_TXT) + { + DEBUG_EX_ERR(if (AnswerType_TXT != pKnownRRAnswer->answerType()) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: ERROR! INVALID answer type (TXT)!\n"));); + _collectServiceTxts(*pService); + if (pService->m_Txts == ((stcMDNS_RRAnswerTXT*)pKnownRRAnswer)->m_Txts) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service TXT answer already known... skipping!\n"));); + pService->m_u8ReplyMask &= ~ContentFlag_TXT; + } + _releaseTempServiceTxts(*pService); + } + } // Service match and enough TTL + + // + // Check service tiebreak possibility + if (pService->m_ProbeInformation.m_bTiebreakNeeded) + { + stcMDNS_RRDomain serviceDomain; + if ((_buildDomainForService(*pService, true, serviceDomain)) && + (pKnownRRAnswer->m_Header.m_Domain == serviceDomain)) + { + // Service domain match + if (AnswerType_SRV == pKnownRRAnswer->answerType()) + { + stcMDNS_RRDomain hostDomain; + if ((_buildDomainForHost(m_pcHostname, hostDomain)) && + (hostDomain == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain)) // Host domain match + { + + // We've received an old message from ourselfs (same SRV) + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (SRV) won (was an old message)!\n"));); + pService->m_ProbeInformation.m_bTiebreakNeeded = false; + } + else + { + if (((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain > hostDomain) // The OTHER domain is 'higher' -> LOST + { + // LOST tiebreak + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (SRV) LOST (lower)!\n"));); + _cancelProbingForService(*pService); + pService->m_ProbeInformation.m_bTiebreakNeeded = false; + } + else // WON tiebreak + { + //TiebreakState = TiebreakState_Won; // We received an 'old' message from ourselfs -> Just ignore + DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (SRV) won (higher)!\n"));); + pService->m_ProbeInformation.m_bTiebreakNeeded = false; + } + } + } + } + } // service tiebreak possibility + } // for services + } // ANY answers + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: FAILED to read known answer!\n"));); + } + + if (pKnownRRAnswer) + { + delete pKnownRRAnswer; + pKnownRRAnswer = 0; + } + } // for answers + + if (bResult) + { + // Check, if a reply is needed + uint8_t u8ReplyNeeded = sendParameter.m_u8HostReplyMask; + for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) + { + u8ReplyNeeded |= pService->m_u8ReplyMask; + } + + if (u8ReplyNeeded) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Sending answer(0x%X)...\n"), u8ReplyNeeded);); + + sendParameter.m_bResponse = true; + sendParameter.m_bAuthorative = true; + + bResult = _sendMDNSMessage(sendParameter); + } + DEBUG_EX_INFO( + else + { + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: No reply needed\n")); + } + ); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Something FAILED!\n"));); + m_pUDPContext->flush(); + } + + // + // Check and reset tiebreak-states + if (m_HostProbeInformation.m_bTiebreakNeeded) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: UNSOLVED tiebreak-need for host domain!\n"));); + m_HostProbeInformation.m_bTiebreakNeeded = false; + } + for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) + { + if (pService->m_ProbeInformation.m_bTiebreakNeeded) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: UNSOLVED tiebreak-need for service domain (%s.%s.%s)\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); + pService->m_ProbeInformation.m_bTiebreakNeeded = false; + } + } + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_parseResponse + + Responses are of interest in two cases: + 1. find domain name conflicts while probing + 2. get answers to service queries + + In both cases any included questions are ignored + + 1. If any answer has a domain name similar to one of the domain names we're planning to use (and are probing for), + then we've got a 'probing conflict'. The conflict has to be solved on our side of the conflict (eg. by + setting a new hostname and restart probing). The callback 'm_fnProbeResultCallback' is called with + 'p_bProbeResult=false' in this case. + + 2. Service queries like '_http._tcp.local' will (if available) produce PTR, SRV, TXT and A/AAAA answers. + All stored answers are pivoted by the service instance name (from the PTR record). Other answer parts, + like host domain or IP address are than attached to this element. + Any answer part carries a TTL, this is also stored (incl. the reception time); if the TTL is '0' the + answer (part) is withdrawn by the sender and should be removed from any cache. RFC 6762, 10.1 proposes to + set the caches TTL-value to 1 second in such a case and to delete the item only, if no update has + has taken place in this second. + Answer parts may arrive in 'unsorted' order, so they are grouped into three levels: + Level 1: PRT - names the service instance (and is used as pivot), voids all other parts if is withdrawn or outdates + Level 2: SRV - links the instance name to a host domain and port, voids A/AAAA parts if is withdrawn or outdates + TXT - links the instance name to services TXTs + Level 3: A/AAAA - links the host domain to an IP address +*/ +bool MDNSResponder::_parseResponse(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHeader) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse\n"));); + //DEBUG_EX_INFO(_udpDump();); + + bool bResult = false; + + // A response should be the result of a query or a probe + if ((_hasServiceQueriesWaitingForAnswers()) || // Waiting for query answers OR + (_hasProbesWaitingForAnswers())) // Probe responses + { + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: Received a response\n")); + //_udpDump(); + ); + + bResult = true; + // + // Ignore questions here + stcMDNS_RRQuestion dummyRRQ; + for (uint16_t qd = 0; ((bResult) && (qd < p_MsgHeader.m_u16QDCount)); ++qd) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: Received a response containing a question... ignoring!\n"));); + bResult = _readRRQuestion(dummyRRQ); + } // for queries + + // + // Read and collect answers + stcMDNS_RRAnswer* pCollectedRRAnswers = 0; + uint32_t u32NumberOfAnswerRRs = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); + for (uint32_t an = 0; ((bResult) && (an < u32NumberOfAnswerRRs)); ++an) + { + stcMDNS_RRAnswer* pRRAnswer = 0; + if (((bResult = _readRRAnswer(pRRAnswer))) && + (pRRAnswer)) + { + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: ADDING answer!\n"));); + pRRAnswer->m_pNext = pCollectedRRAnswers; + pCollectedRRAnswers = pRRAnswer; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: FAILED to read answer!\n"));); + if (pRRAnswer) + { + delete pRRAnswer; + pRRAnswer = 0; + } + bResult = false; + } + } // for answers + + // + // Process answers + if (bResult) + { + bResult = ((!pCollectedRRAnswers) || + (_processAnswers(pCollectedRRAnswers))); + } + else // Some failure while reading answers + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: FAILED to read answers!\n"));); + m_pUDPContext->flush(); + } + + // Delete collected answers + while (pCollectedRRAnswers) + { + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: DELETING answer!\n"));); + stcMDNS_RRAnswer* pNextAnswer = pCollectedRRAnswers->m_pNext; + delete pCollectedRRAnswers; + pCollectedRRAnswers = pNextAnswer; + } + } + else // Received an unexpected response -> ignore + { + /* DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: Received an unexpected response... ignoring!\nDUMP:\n")); + bool bDumpResult = true; + for (uint16_t qd=0; ((bDumpResult) && (qd<p_MsgHeader.m_u16QDCount)); ++qd) { + stcMDNS_RRQuestion questionRR; + bDumpResult = _readRRQuestion(questionRR); + esp_yield(); + } // for questions + // Handle known answers + uint32_t u32Answers = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); + for (uint32_t an=0; ((bDumpResult) && (an<u32Answers)); ++an) { + stcMDNS_RRAnswer* pRRAnswer = 0; + bDumpResult = _readRRAnswer(pRRAnswer); + if (pRRAnswer) { + delete pRRAnswer; + pRRAnswer = 0; + } + esp_yield(); + } + );*/ + m_pUDPContext->flush(); + bResult = true; + } + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_processAnswers + Host: + A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 + AAAA (01Cx): eg. esp8266.local AAAA OP TTL 1234:5678::90 + PTR (0x0C, IP4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local + PTR (0x0C, IP6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local + Service: + PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local + PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local + SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local + TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 + +*/ +bool MDNSResponder::_processAnswers(const MDNSResponder::stcMDNS_RRAnswer* p_pAnswers) +{ + + bool bResult = false; + + if (p_pAnswers) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAnswers: Processing answers...\n"));); + bResult = true; + + // Answers may arrive in an unexpected order. So we loop our answers as long, as we + // can connect new information to service queries + bool bFoundNewKeyAnswer; + do + { + bFoundNewKeyAnswer = false; + + const stcMDNS_RRAnswer* pRRAnswer = p_pAnswers; + while ((pRRAnswer) && + (bResult)) + { + // 1. level answer (PTR) + if (AnswerType_PTR == pRRAnswer->answerType()) + { + // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local + bResult = _processPTRAnswer((stcMDNS_RRAnswerPTR*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new SRV or TXT answers to be linked to queries + } + // 2. level answers + // SRV -> host domain and port + else if (AnswerType_SRV == pRRAnswer->answerType()) + { + // eg. MyESP_http._tcp.local SRV xxxx xx yy zz 5000 esp8266.local + bResult = _processSRVAnswer((stcMDNS_RRAnswerSRV*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new A/AAAA answers to be linked to queries + } + // TXT -> Txts + else if (AnswerType_TXT == pRRAnswer->answerType()) + { + // eg. MyESP_http._tcp.local TXT xxxx xx c#=1 + bResult = _processTXTAnswer((stcMDNS_RRAnswerTXT*)pRRAnswer); + } + // 3. level answers +#ifdef MDNS_IP4_SUPPORT + // A -> IP4Address + else if (AnswerType_A == pRRAnswer->answerType()) + { + // eg. esp8266.local A xxxx xx 192.168.2.120 + bResult = _processAAnswer((stcMDNS_RRAnswerA*)pRRAnswer); + } +#endif +#ifdef MDNS_IP6_SUPPORT + // AAAA -> IP6Address + else if (AnswerType_AAAA == pRRAnswer->answerType()) + { + // eg. esp8266.local AAAA xxxx xx 09cf::0c + bResult = _processAAAAAnswer((stcMDNS_RRAnswerAAAA*)pRRAnswer); + } +#endif + + // Finally check for probing conflicts + // Host domain + if ((ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) && + ((AnswerType_A == pRRAnswer->answerType()) || + (AnswerType_AAAA == pRRAnswer->answerType()))) + { + + stcMDNS_RRDomain hostDomain; + if ((_buildDomainForHost(m_pcHostname, hostDomain)) && + (pRRAnswer->m_Header.m_Domain == hostDomain)) + { + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAnswers: Probing CONFLICT found with: %s.local\n"), m_pcHostname);); + _cancelProbingForHost(); + } + } + // Service domains + for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) + { + if ((ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) && + ((AnswerType_TXT == pRRAnswer->answerType()) || + (AnswerType_SRV == pRRAnswer->answerType()))) + { + + stcMDNS_RRDomain serviceDomain; + if ((_buildDomainForService(*pService, true, serviceDomain)) && + (pRRAnswer->m_Header.m_Domain == serviceDomain)) + { + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAnswers: Probing CONFLICT found with: %s.%s.%s\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); + _cancelProbingForService(*pService); + } + } + } + + pRRAnswer = pRRAnswer->m_pNext; // Next collected answer + } // while (answers) + } while ((bFoundNewKeyAnswer) && + (bResult)); + } // else: No answers provided + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAnswers: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_processPTRAnswer +*/ +bool MDNSResponder::_processPTRAnswer(const MDNSResponder::stcMDNS_RRAnswerPTR* p_pPTRAnswer, + bool& p_rbFoundNewKeyAnswer) +{ + + bool bResult = false; + + if ((bResult = (0 != p_pPTRAnswer))) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: Processing PTR answers...\n"));); + // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local + // Check pending service queries for eg. '_http._tcp' + + stcMDNSServiceQuery* pServiceQuery = _findNextServiceQueryByServiceType(p_pPTRAnswer->m_Header.m_Domain, 0); + while (pServiceQuery) + { + if (pServiceQuery->m_bAwaitingAnswers) + { + // Find answer for service domain (eg. MyESP._http._tcp.local) + stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForServiceDomain(p_pPTRAnswer->m_PTRDomain); + if (pSQAnswer) // existing answer + { + if (p_pPTRAnswer->m_u32TTL) // Received update message + { + pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); // Update TTL tag + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: Updated TTL(%d) for "), (int)p_pPTRAnswer->m_u32TTL); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + ); + } + else // received goodbye-message + { + pSQAnswer->m_TTLServiceDomain.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: 'Goodbye' received for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + ); + } + } + else if ((p_pPTRAnswer->m_u32TTL) && // Not just a goodbye-message + ((pSQAnswer = new stcMDNSServiceQuery::stcAnswer))) // Not yet included -> add answer + { + pSQAnswer->m_ServiceDomain = p_pPTRAnswer->m_PTRDomain; + pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_ServiceDomain; + pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); + pSQAnswer->releaseServiceDomain(); + + bResult = pServiceQuery->addAnswer(pSQAnswer); + p_rbFoundNewKeyAnswer = true; + if (pServiceQuery->m_fnCallback) + { + MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); + pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_ServiceDomain), true); + } + } + } + pServiceQuery = _findNextServiceQueryByServiceType(p_pPTRAnswer->m_Header.m_Domain, pServiceQuery); + } + } // else: No p_pPTRAnswer + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_processSRVAnswer +*/ +bool MDNSResponder::_processSRVAnswer(const MDNSResponder::stcMDNS_RRAnswerSRV* p_pSRVAnswer, + bool& p_rbFoundNewKeyAnswer) +{ + + bool bResult = false; + + if ((bResult = (0 != p_pSRVAnswer))) + { + // eg. MyESP._http._tcp.local SRV xxxx xx yy zz 5000 esp8266.local + + stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; + while (pServiceQuery) + { + stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForServiceDomain(p_pSRVAnswer->m_Header.m_Domain); + if (pSQAnswer) // Answer for this service domain (eg. MyESP._http._tcp.local) available + { + if (p_pSRVAnswer->m_u32TTL) // First or update message (TTL != 0) + { + pSQAnswer->m_TTLHostDomainAndPort.set(p_pSRVAnswer->m_u32TTL); // Update TTL tag + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: Updated TTL(%d) for "), (int)p_pSRVAnswer->m_u32TTL); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); + ); + // Host domain & Port + if ((pSQAnswer->m_HostDomain != p_pSRVAnswer->m_SRVDomain) || + (pSQAnswer->m_u16Port != p_pSRVAnswer->m_u16Port)) + { + + pSQAnswer->m_HostDomain = p_pSRVAnswer->m_SRVDomain; + pSQAnswer->releaseHostDomain(); + pSQAnswer->m_u16Port = p_pSRVAnswer->m_u16Port; + pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_HostDomainAndPort; + + p_rbFoundNewKeyAnswer = true; + if (pServiceQuery->m_fnCallback) + { + MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); + pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_HostDomainAndPort), true); + } + } + } + else // Goodby message + { + pSQAnswer->m_TTLHostDomainAndPort.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: 'Goodbye' received for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); + ); + } + } + pServiceQuery = pServiceQuery->m_pNext; + } // while(service query) + } // else: No p_pSRVAnswer + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_processTXTAnswer +*/ +bool MDNSResponder::_processTXTAnswer(const MDNSResponder::stcMDNS_RRAnswerTXT* p_pTXTAnswer) +{ + + bool bResult = false; + + if ((bResult = (0 != p_pTXTAnswer))) + { + // eg. MyESP._http._tcp.local TXT xxxx xx c#=1 + + stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; + while (pServiceQuery) + { + stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForServiceDomain(p_pTXTAnswer->m_Header.m_Domain); + if (pSQAnswer) // Answer for this service domain (eg. MyESP._http._tcp.local) available + { + if (p_pTXTAnswer->m_u32TTL) // First or update message + { + pSQAnswer->m_TTLTxts.set(p_pTXTAnswer->m_u32TTL); // Update TTL tag + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: Updated TTL(%d) for "), (int)p_pTXTAnswer->m_u32TTL); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); + ); + if (!pSQAnswer->m_Txts.compare(p_pTXTAnswer->m_Txts)) + { + pSQAnswer->m_Txts = p_pTXTAnswer->m_Txts; + pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_Txts; + pSQAnswer->releaseTxts(); + + if (pServiceQuery->m_fnCallback) + { + MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); + pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_Txts), true); + } + } + } + else // Goodby message + { + pSQAnswer->m_TTLTxts.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: 'Goodbye' received for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); + ); + } + } + pServiceQuery = pServiceQuery->m_pNext; + } // while(service query) + } // else: No p_pTXTAnswer + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: FAILED!\n")); + }); + return bResult; +} + +#ifdef MDNS_IP4_SUPPORT +/* + MDNSResponder::_processAAnswer +*/ +bool MDNSResponder::_processAAnswer(const MDNSResponder::stcMDNS_RRAnswerA* p_pAAnswer) +{ + + bool bResult = false; + + if ((bResult = (0 != p_pAAnswer))) + { + // eg. esp8266.local A xxxx xx 192.168.2.120 + + stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; + while (pServiceQuery) + { + stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForHostDomain(p_pAAnswer->m_Header.m_Domain); + if (pSQAnswer) // Answer for this host domain (eg. esp8266.local) available + { + stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address = pSQAnswer->findIP4Address(p_pAAnswer->m_IPAddress); + if (pIP4Address) + { + // Already known IP4 address + if (p_pAAnswer->m_u32TTL) // Valid TTL -> Update answers TTL + { + pIP4Address->m_TTL.set(p_pAAnswer->m_u32TTL); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL(%d) for "), (int)p_pAAnswer->m_u32TTL); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IP4Address (%s)\n"), pIP4Address->m_IPAddress.toString().c_str()); + ); + } + else // 'Goodbye' message for known IP4 address + { + pIP4Address->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: 'Goodbye' received for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IP4 address (%s)\n"), pIP4Address->m_IPAddress.toString().c_str()); + ); + } + } + else + { + // Until now unknown IP4 address -> Add (if the message isn't just a 'Goodbye' note) + if (p_pAAnswer->m_u32TTL) // NOT just a 'Goodbye' message + { + pIP4Address = new stcMDNSServiceQuery::stcAnswer::stcIP4Address(p_pAAnswer->m_IPAddress, p_pAAnswer->m_u32TTL); + if ((pIP4Address) && + (pSQAnswer->addIP4Address(pIP4Address))) + { + + pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_IP4Address; + if (pServiceQuery->m_fnCallback) + { + MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); + pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_IP4Address), true); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: FAILED to add IP4 address (%s)!\n"), p_pAAnswer->m_IPAddress.toString().c_str());); + } + } + } + } + pServiceQuery = pServiceQuery->m_pNext; + } // while(service query) + } // else: No p_pAAnswer + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: FAILED!\n")); + }); + return bResult; +} +#endif + +#ifdef MDNS_IP6_SUPPORT +/* + MDNSResponder::_processAAAAAnswer +*/ +bool MDNSResponder::_processAAAAAnswer(const MDNSResponder::stcMDNS_RRAnswerAAAA* p_pAAAAAnswer) +{ + + bool bResult = false; + + if ((bResult = (0 != p_pAAAAAnswer))) + { + // eg. esp8266.local AAAA xxxx xx 0bf3::0c + + stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; + while (pServiceQuery) + { + stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForHostDomain(p_pAAAAAnswer->m_Header.m_Domain); + if (pSQAnswer) // Answer for this host domain (eg. esp8266.local) available + { + stcIP6Address* pIP6Address = pSQAnswer->findIP6Address(p_pAAAAAnswer->m_IPAddress); + if (pIP6Address) + { + // Already known IP6 address + if (p_pAAAAAnswer->m_u32TTL) // Valid TTL -> Update answers TTL + { + pIP6Address->m_TTL.set(p_pAAAAAnswer->m_u32TTL); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL(%lu) for "), p_pAAAAAnswer->m_u32TTL); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IP6 address (%s)\n"), pIP6Address->m_IPAddress.toString().c_str()); + ); + } + else // 'Goodbye' message for known IP6 address + { + pIP6Address->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: 'Goodbye' received for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IP6 address (%s)\n"), pIP6Address->m_IPAddress.toString().c_str()); + ); + } + } + else + { + // Until now unknown IP6 address -> Add (if the message isn't just a 'Goodbye' note) + if (p_pAAAAAnswer->m_u32TTL) // NOT just a 'Goodbye' message + { + pIP6Address = new stcIP6Address(p_pAAAAAnswer->m_IPAddress, p_pAAAAAnswer->m_u32TTL); + if ((pIP6Address) && + (pSQAnswer->addIP6Address(pIP6Address))) + { + + pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_IP6Address; + + if (pServiceQuery->m_fnCallback) + { + pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), ServiceQueryAnswerType_IP6Address, true, pServiceQuery->m_pUserdata); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: FAILED to add IP6 address (%s)!\n"), p_pAAAAAnswer->m_IPAddress.toString().c_str());); + } + } + } + } + pServiceQuery = pServiceQuery->m_pNext; + } // while(service query) + } // else: No p_pAAAAAnswer + + return bResult; +} +#endif + + +/* + PROBING +*/ + +/* + MDNSResponder::_updateProbeStatus + + Manages the (outgoing) probing process. + - If probing has not been started yet (ProbingStatus_NotStarted), the initial delay (see RFC 6762) is determined and + the process is started + - After timeout (of initial or subsequential delay) a probe message is send out for three times. If the message has + already been sent out three times, the probing has been successful and is finished. + + Conflict management is handled in '_parseResponse ff.' + Tiebraking is handled in 'parseQuery ff.' +*/ +bool MDNSResponder::_updateProbeStatus(void) +{ + + bool bResult = true; + + // + // Probe host domain + if ((ProbingStatus_ReadyToStart == m_HostProbeInformation.m_ProbingStatus) && // Ready to get started AND + //TODO: Fix the following to allow Ethernet shield or other interfaces + (_getResponseMulticastInterface() != IPAddress())) // Has IP address + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Starting host probing...\n"));); + + // First probe delay SHOULD be random 0-250 ms + m_HostProbeInformation.m_Timeout.reset(rand() % MDNS_PROBE_DELAY); + m_HostProbeInformation.m_ProbingStatus = ProbingStatus_InProgress; + } + else if ((ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing AND + (m_HostProbeInformation.m_Timeout.expired())) // Time for next probe + { + + if (MDNS_PROBE_COUNT > m_HostProbeInformation.m_u8SentCount) // Send next probe + { + if ((bResult = _sendHostProbe())) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Did sent host probe\n\n"));); + m_HostProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); + ++m_HostProbeInformation.m_u8SentCount; + } + } + else // Probing finished + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done host probing.\n"));); + m_HostProbeInformation.m_ProbingStatus = ProbingStatus_Done; + m_HostProbeInformation.m_Timeout.resetToNeverExpires(); + if (m_HostProbeInformation.m_fnHostProbeResultCallback) + { + m_HostProbeInformation.m_fnHostProbeResultCallback(m_pcHostname, true); + } + + // Prepare to announce host + m_HostProbeInformation.m_u8SentCount = 0; + m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Prepared host announcing.\n\n"));); + } + } // else: Probing already finished OR waiting for next time slot + else if ((ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus) && + (m_HostProbeInformation.m_Timeout.expired())) + { + + if ((bResult = _announce(true, false))) // Don't announce services here + { + ++m_HostProbeInformation.m_u8SentCount; + + if (MDNS_ANNOUNCE_COUNT > m_HostProbeInformation.m_u8SentCount) + { + m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing host (%d).\n\n"), m_HostProbeInformation.m_u8SentCount);); + } + else + { + m_HostProbeInformation.m_Timeout.resetToNeverExpires(); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done host announcing.\n\n"));); + } + } + } + + // + // Probe services + for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + { + if (ProbingStatus_ReadyToStart == pService->m_ProbeInformation.m_ProbingStatus) // Ready to get started + { + + pService->m_ProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); // More or equal than first probe for host domain + pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_InProgress; + } + else if ((ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing AND + (pService->m_ProbeInformation.m_Timeout.expired())) // Time for next probe + { + + if (MDNS_PROBE_COUNT > pService->m_ProbeInformation.m_u8SentCount) // Send next probe + { + if ((bResult = _sendServiceProbe(*pService))) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Did sent service probe (%u)\n\n"), (pService->m_ProbeInformation.m_u8SentCount + 1));); + pService->m_ProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); + ++pService->m_ProbeInformation.m_u8SentCount; + } + } + else // Probing finished + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done service probing %s.%s.%s\n\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); + pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_Done; + pService->m_ProbeInformation.m_Timeout.resetToNeverExpires(); + if (pService->m_ProbeInformation.m_fnServiceProbeResultCallback) + { + pService->m_ProbeInformation.m_fnServiceProbeResultCallback(pService->m_pcName, pService, true); + } + // Prepare to announce service + pService->m_ProbeInformation.m_u8SentCount = 0; + pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Prepared service announcing.\n\n"));); + } + } // else: Probing already finished OR waiting for next time slot + else if ((ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus) && + (pService->m_ProbeInformation.m_Timeout.expired())) + { + + if ((bResult = _announceService(*pService))) // Announce service + { + ++pService->m_ProbeInformation.m_u8SentCount; + + if (MDNS_ANNOUNCE_COUNT > pService->m_ProbeInformation.m_u8SentCount) + { + pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing service %s.%s.%s (%d)\n\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_ProbeInformation.m_u8SentCount);); + } + else + { + pService->m_ProbeInformation.m_Timeout.resetToNeverExpires(); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done service announcing for %s.%s.%s\n\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); + } + } + } + } + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: FAILED!\n\n")); + }); + return bResult; +} + +/* + MDNSResponder::_resetProbeStatus + + Resets the probe status. + If 'p_bRestart' is set, the status is set to ProbingStatus_NotStarted. Consequently, + when running 'updateProbeStatus' (which is done in every '_update' loop), the probing + process is restarted. +*/ +bool MDNSResponder::_resetProbeStatus(bool p_bRestart /*= true*/) +{ + + m_HostProbeInformation.clear(false); + m_HostProbeInformation.m_ProbingStatus = (p_bRestart ? ProbingStatus_ReadyToStart : ProbingStatus_Done); + + for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) + { + pService->m_ProbeInformation.clear(false); + pService->m_ProbeInformation.m_ProbingStatus = (p_bRestart ? ProbingStatus_ReadyToStart : ProbingStatus_Done); + } + return true; +} + +/* + MDNSResponder::_hasProbesWaitingForAnswers +*/ +bool MDNSResponder::_hasProbesWaitingForAnswers(void) const +{ + + bool bResult = ((ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing + (0 < m_HostProbeInformation.m_u8SentCount)); // And really probing + + for (stcMDNSService* pService = m_pServices; ((!bResult) && (pService)); pService = pService->m_pNext) + { + bResult = ((ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing + (0 < pService->m_ProbeInformation.m_u8SentCount)); // And really probing + } + return bResult; +} + +/* + MDNSResponder::_sendHostProbe + + Asks (probes) in the local network for the planned host domain + - (eg. esp8266.local) + + To allow 'tiebreaking' (see '_parseQuery'), the answers for these questions are delivered in + the 'knwon answers' section of the query. + Host domain: + - A/AAAA (eg. esp8266.esp -> 192.168.2.120) +*/ +bool MDNSResponder::_sendHostProbe(void) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendHostProbe (%s, %lu)\n"), m_pcHostname, millis());); + + bool bResult = true; + + // Requests for host domain + stcMDNSSendParameter sendParameter; + sendParameter.m_bCacheFlush = false; // RFC 6762 10.2 + + sendParameter.m_pQuestions = new stcMDNS_RRQuestion; + if (((bResult = (0 != sendParameter.m_pQuestions))) && + ((bResult = _buildDomainForHost(m_pcHostname, sendParameter.m_pQuestions->m_Header.m_Domain)))) + { + + //sendParameter.m_pQuestions->m_bUnicast = true; + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet + + // Add known answers +#ifdef MDNS_IP4_SUPPORT + sendParameter.m_u8HostReplyMask |= ContentFlag_A; // Add A answer +#endif +#ifdef MDNS_IP6_SUPPORT + sendParameter.m_u8HostReplyMask |= ContentFlag_AAAA; // Add AAAA answer +#endif + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendHostProbe: FAILED to create host question!\n"));); + if (sendParameter.m_pQuestions) + { + delete sendParameter.m_pQuestions; + sendParameter.m_pQuestions = 0; + } + } + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendHostProbe: FAILED!\n")); + }); + return ((bResult) && + (_sendMDNSMessage(sendParameter))); +} + +/* + MDNSResponder::_sendServiceProbe + + Asks (probes) in the local network for the planned service instance domain + - (eg. MyESP._http._tcp.local). + + To allow 'tiebreaking' (see '_parseQuery'), the answers for these questions are delivered in + the 'knwon answers' section of the query. + Service domain: + - SRV (eg. MyESP._http._tcp.local -> 5000 esp8266.local) + - PTR NAME (eg. _http._tcp.local -> MyESP._http._tcp.local) (TODO: Check if needed, maybe TXT is better) +*/ +bool MDNSResponder::_sendServiceProbe(stcMDNSService& p_rService) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendServiceProbe (%s.%s.%s, %lu)\n"), (p_rService.m_pcName ? : m_pcHostname), p_rService.m_pcService, p_rService.m_pcProtocol, millis());); + + bool bResult = true; + + // Requests for service instance domain + stcMDNSSendParameter sendParameter; + sendParameter.m_bCacheFlush = false; // RFC 6762 10.2 + + sendParameter.m_pQuestions = new stcMDNS_RRQuestion; + if (((bResult = (0 != sendParameter.m_pQuestions))) && + ((bResult = _buildDomainForService(p_rService, true, sendParameter.m_pQuestions->m_Header.m_Domain)))) + { + + sendParameter.m_pQuestions->m_bUnicast = true; + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet + + // Add known answers + p_rService.m_u8ReplyMask = (ContentFlag_SRV | ContentFlag_PTR_NAME); // Add SRV and PTR NAME answers + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendServiceProbe: FAILED to create service question!\n"));); + if (sendParameter.m_pQuestions) + { + delete sendParameter.m_pQuestions; + sendParameter.m_pQuestions = 0; + } + } + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendServiceProbe: FAILED!\n")); + }); + return ((bResult) && + (_sendMDNSMessage(sendParameter))); +} + +/* + MDNSResponder::_cancelProbingForHost +*/ +bool MDNSResponder::_cancelProbingForHost(void) +{ + + bool bResult = false; + + m_HostProbeInformation.clear(false); + // Send host notification + if (m_HostProbeInformation.m_fnHostProbeResultCallback) + { + m_HostProbeInformation.m_fnHostProbeResultCallback(m_pcHostname, false); + + bResult = true; + } + + for (stcMDNSService* pService = m_pServices; ((!bResult) && (pService)); pService = pService->m_pNext) + { + bResult = _cancelProbingForService(*pService); + } + return bResult; +} + +/* + MDNSResponder::_cancelProbingForService +*/ +bool MDNSResponder::_cancelProbingForService(stcMDNSService& p_rService) +{ + + bool bResult = false; + + p_rService.m_ProbeInformation.clear(false); + // Send notification + if (p_rService.m_ProbeInformation.m_fnServiceProbeResultCallback) + { + p_rService.m_ProbeInformation.m_fnServiceProbeResultCallback(p_rService.m_pcName, &p_rService, false); + bResult = true; + } + return bResult; +} + + + +/** + ANNOUNCING +*/ + +/* + MDNSResponder::_announce + + Announces the host domain: + - A/AAAA (eg. esp8266.local -> 192.168.2.120) + - PTR (eg. 192.168.2.120.in-addr.arpa -> esp8266.local) + + and all presented services: + - PTR_TYPE (_services._dns-sd._udp.local -> _http._tcp.local) + - PTR_NAME (eg. _http._tcp.local -> MyESP8266._http._tcp.local) + - SRV (eg. MyESP8266._http._tcp.local -> 5000 esp8266.local) + - TXT (eg. MyESP8266._http._tcp.local -> c#=1) + + Goodbye (Un-Announcing) for the host domain and all services is also handled here. + Goodbye messages are created by setting the TTL for the answer to 0, this happens + inside the '_writeXXXAnswer' procs via 'sendParameter.m_bUnannounce = true' +*/ +bool MDNSResponder::_announce(bool p_bAnnounce, + bool p_bIncludeServices) +{ + + bool bResult = false; + + stcMDNSSendParameter sendParameter; + if (ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus) + { + + bResult = true; + + sendParameter.m_bResponse = true; // Announces are 'Unsolicited authorative responses' + sendParameter.m_bAuthorative = true; + sendParameter.m_bUnannounce = !p_bAnnounce; // When unannouncing, the TTL is set to '0' while creating the answers + + // Announce host + sendParameter.m_u8HostReplyMask = 0; +#ifdef MDNS_IP4_SUPPORT + sendParameter.m_u8HostReplyMask |= ContentFlag_A; // A answer + sendParameter.m_u8HostReplyMask |= ContentFlag_PTR_IP4; // PTR_IP4 answer +#endif +#ifdef MDNS_IP6_SUPPORT + sendParameter.m_u8HostReplyMask |= ContentFlag_AAAA; // AAAA answer + sendParameter.m_u8HostReplyMask |= ContentFlag_PTR_IP6; // PTR_IP6 answer +#endif + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: Announcing host %s (content 0x%X)\n"), m_pcHostname, sendParameter.m_u8HostReplyMask);); + + if (p_bIncludeServices) + { + // Announce services (service type, name, SRV (location) and TXTs) + for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + { + if (ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus) + { + pService->m_u8ReplyMask = (ContentFlag_PTR_TYPE | ContentFlag_PTR_NAME | ContentFlag_SRV | ContentFlag_TXT); + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: Announcing service %s.%s.%s (content %u)\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_u8ReplyMask);); + } + } + } + } + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: FAILED!\n")); + }); + return ((bResult) && + (_sendMDNSMessage(sendParameter))); +} + +/* + MDNSResponder::_announceService +*/ +bool MDNSResponder::_announceService(stcMDNSService& p_rService, + bool p_bAnnounce /*= true*/) +{ + + bool bResult = false; + + stcMDNSSendParameter sendParameter; + if (ProbingStatus_Done == p_rService.m_ProbeInformation.m_ProbingStatus) + { + + sendParameter.m_bResponse = true; // Announces are 'Unsolicited authorative responses' + sendParameter.m_bAuthorative = true; + sendParameter.m_bUnannounce = !p_bAnnounce; // When unannouncing, the TTL is set to '0' while creating the answers + + // DON'T announce host + sendParameter.m_u8HostReplyMask = 0; + + // Announce services (service type, name, SRV (location) and TXTs) + p_rService.m_u8ReplyMask = (ContentFlag_PTR_TYPE | ContentFlag_PTR_NAME | ContentFlag_SRV | ContentFlag_TXT); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announceService: Announcing service %s.%s.%s (content 0x%X)\n"), (p_rService.m_pcName ? : m_pcHostname), p_rService.m_pcService, p_rService.m_pcProtocol, p_rService.m_u8ReplyMask);); + + bResult = true; + } + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announceService: FAILED!\n")); + }); + return ((bResult) && + (_sendMDNSMessage(sendParameter))); +} + + +/** + SERVICE QUERY CACHE +*/ + +/* + MDNSResponder::_hasServiceQueriesWaitingForAnswers +*/ +bool MDNSResponder::_hasServiceQueriesWaitingForAnswers(void) const +{ + + bool bOpenQueries = false; + + for (stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; pServiceQuery; pServiceQuery = pServiceQuery->m_pNext) + { + if (pServiceQuery->m_bAwaitingAnswers) + { + bOpenQueries = true; + break; + } + } + return bOpenQueries; +} + +/* + MDNSResponder::_checkServiceQueryCache + + For any 'living' service query (m_bAwaitingAnswers == true) all available answers (their components) + are checked for topicality based on the stored reception time and the answers TTL. + When the components TTL is outlasted by more than 80%, a new question is generated, to get updated information. + When no update arrived (in time), the component is removed from the answer (cache). + +*/ +bool MDNSResponder::_checkServiceQueryCache(void) +{ + + bool bResult = true; + + DEBUG_EX_INFO( + bool printedInfo = false; + ); + for (stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; ((bResult) && (pServiceQuery)); pServiceQuery = pServiceQuery->m_pNext) + { + + // + // Resend dynamic service queries, if not already done often enough + if ((!pServiceQuery->m_bLegacyQuery) && + (MDNS_DYNAMIC_QUERY_RESEND_COUNT > pServiceQuery->m_u8SentCount) && + (pServiceQuery->m_ResendTimeout.expired())) + { + + if ((bResult = _sendMDNSServiceQuery(*pServiceQuery))) + { + ++pServiceQuery->m_u8SentCount; + pServiceQuery->m_ResendTimeout.reset((MDNS_DYNAMIC_QUERY_RESEND_COUNT > pServiceQuery->m_u8SentCount) + ? (MDNS_DYNAMIC_QUERY_RESEND_DELAY * (pServiceQuery->m_u8SentCount - 1)) + : esp8266::polledTimeout::oneShotMs::neverExpires); + } + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: %s to resend service query!"), (bResult ? "Succeeded" : "FAILED")); + printedInfo = true; + ); + } + + // + // Schedule updates for cached answers + if (pServiceQuery->m_bAwaitingAnswers) + { + stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->m_pAnswers; + while ((bResult) && + (pSQAnswer)) + { + stcMDNSServiceQuery::stcAnswer* pNextSQAnswer = pSQAnswer->m_pNext; + + // 1. level answer + if ((bResult) && + (pSQAnswer->m_TTLServiceDomain.flagged())) + { + + if (!pSQAnswer->m_TTLServiceDomain.finalTimeoutLevel()) + { + + bResult = ((_sendMDNSServiceQuery(*pServiceQuery)) && + (pSQAnswer->m_TTLServiceDomain.restart())); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: PTR update scheduled for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" %s\n"), (bResult ? "OK" : "FAILURE")); + printedInfo = true; + ); + } + else + { + // Timed out! -> Delete + if (pServiceQuery->m_fnCallback) + { + MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); + pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_ServiceDomain), false); + } + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove PTR answer for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + printedInfo = true; + ); + + bResult = pServiceQuery->removeAnswer(pSQAnswer); + pSQAnswer = 0; + continue; // Don't use this answer anymore + } + } // ServiceDomain flagged + + // 2. level answers + // HostDomain & Port (from SRV) + if ((bResult) && + (pSQAnswer->m_TTLHostDomainAndPort.flagged())) + { + + if (!pSQAnswer->m_TTLHostDomainAndPort.finalTimeoutLevel()) + { + + bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_SRV)) && + (pSQAnswer->m_TTLHostDomainAndPort.restart())); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: SRV update scheduled for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" host domain and port %s\n"), (bResult ? "OK" : "FAILURE")); + printedInfo = true; + ); + } + else + { + // Timed out! -> Delete + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove SRV answer for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); + printedInfo = true; + ); + // Delete + pSQAnswer->m_HostDomain.clear(); + pSQAnswer->releaseHostDomain(); + pSQAnswer->m_u16Port = 0; + pSQAnswer->m_TTLHostDomainAndPort.set(0); + uint32_t u32ContentFlags = ServiceQueryAnswerType_HostDomainAndPort; + // As the host domain is the base for the IP4- and IP6Address, remove these too +#ifdef MDNS_IP4_SUPPORT + pSQAnswer->releaseIP4Addresses(); + u32ContentFlags |= ServiceQueryAnswerType_IP4Address; +#endif +#ifdef MDNS_IP6_SUPPORT + pSQAnswer->releaseIP6Addresses(); + u32ContentFlags |= ServiceQueryAnswerType_IP6Address; +#endif + + // Remove content flags for deleted answer parts + pSQAnswer->m_u32ContentFlags &= ~u32ContentFlags; + if (pServiceQuery->m_fnCallback) + { + MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); + pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(u32ContentFlags), false); + } + } + } // HostDomainAndPort flagged + + // Txts (from TXT) + if ((bResult) && + (pSQAnswer->m_TTLTxts.flagged())) + { + + if (!pSQAnswer->m_TTLTxts.finalTimeoutLevel()) + { + + bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_TXT)) && + (pSQAnswer->m_TTLTxts.restart())); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: TXT update scheduled for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" TXTs %s\n"), (bResult ? "OK" : "FAILURE")); + printedInfo = true; + ); + } + else + { + // Timed out! -> Delete + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove TXT answer for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); + printedInfo = true; + ); + // Delete + pSQAnswer->m_Txts.clear(); + pSQAnswer->m_TTLTxts.set(0); + + // Remove content flags for deleted answer parts + pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_Txts; + + if (pServiceQuery->m_fnCallback) + { + MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); + pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_Txts), false); + } + } + } // TXTs flagged + + // 3. level answers +#ifdef MDNS_IP4_SUPPORT + // IP4Address (from A) + stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address = pSQAnswer->m_pIP4Addresses; + bool bAUpdateQuerySent = false; + while ((pIP4Address) && + (bResult)) + { + + stcMDNSServiceQuery::stcAnswer::stcIP4Address* pNextIP4Address = pIP4Address->m_pNext; // Get 'next' early, as 'current' may be deleted at the end... + + if (pIP4Address->m_TTL.flagged()) + { + + if (!pIP4Address->m_TTL.finalTimeoutLevel()) // Needs update + { + + if ((bAUpdateQuerySent) || + ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_A)))) + { + + pIP4Address->m_TTL.restart(); + bAUpdateQuerySent = true; + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: IP4 update scheduled for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IP4 address (%s)\n"), (pIP4Address->m_IPAddress.toString().c_str())); + printedInfo = true; + ); + } + } + else + { + // Timed out! -> Delete + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove IP4 answer for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IP4 address\n")); + printedInfo = true; + ); + pSQAnswer->removeIP4Address(pIP4Address); + if (!pSQAnswer->m_pIP4Addresses) // NO IP4 address left -> remove content flag + { + pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_IP4Address; + } + // Notify client + if (pServiceQuery->m_fnCallback) + { + MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); + pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_IP4Address), false); + } + } + } // IP4 flagged + + pIP4Address = pNextIP4Address; // Next + } // while +#endif +#ifdef MDNS_IP6_SUPPORT + // IP6Address (from AAAA) + stcMDNSServiceQuery::stcAnswer::stcIP6Address* pIP6Address = pSQAnswer->m_pIP6Addresses; + bool bAAAAUpdateQuerySent = false; + while ((pIP6Address) && + (bResult)) + { + + stcMDNSServiceQuery::stcAnswer::stcIP6Address* pNextIP6Address = pIP6Address->m_pNext; // Get 'next' early, as 'current' may be deleted at the end... + + if (pIP6Address->m_TTL.flagged()) + { + + if (!pIP6Address->m_TTL.finalTimeoutLevel()) // Needs update + { + + if ((bAAAAUpdateQuerySent) || + ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) + { + + pIP6Address->m_TTL.restart(); + bAAAAUpdateQuerySent = true; + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: IP6 update scheduled for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IP6 address (%s)\n"), (pIP6Address->m_IPAddress.toString().c_str())); + printedInfo = true; + ); + } + } + else + { + // Timed out! -> Delete + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove answer for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IP6Address\n")); + printedInfo = true; + ); + pSQAnswer->removeIP6Address(pIP6Address); + if (!pSQAnswer->m_pIP6Addresses) // NO IP6 address left -> remove content flag + { + pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_IP6Address; + } + // Notify client + if (pServiceQuery->m_fnCallback) + { + pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), ServiceQueryAnswerType_IP6Address, false, pServiceQuery->m_pUserdata); + } + } + } // IP6 flagged + + pIP6Address = pNextIP6Address; // Next + } // while +#endif + pSQAnswer = pNextSQAnswer; + } + } + } + DEBUG_EX_INFO( + if (printedInfo) +{ + DEBUG_OUTPUT.printf_P(PSTR("\n")); + } + ); + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: FAILED!\n")); + }); + return bResult; +} + + +/* + MDNSResponder::_replyMaskForHost + + Determines the relavant host answers for the given question. + - A question for the hostname (eg. esp8266.local) will result in an A/AAAA (eg. 192.168.2.129) reply. + - A question for the reverse IP address (eg. 192-168.2.120.inarpa.arpa) will result in an PTR_IP4 (eg. esp8266.local) reply. + + In addition, a full name match (question domain == host domain) is marked. +*/ +uint8_t MDNSResponder::_replyMaskForHost(const MDNSResponder::stcMDNS_RRHeader& p_RRHeader, + bool* p_pbFullNameMatch /*= 0*/) const +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForHost\n"));); + + uint8_t u8ReplyMask = 0; + (p_pbFullNameMatch ? *p_pbFullNameMatch = false : 0); + + if ((DNS_RRCLASS_IN == p_RRHeader.m_Attributes.m_u16Class) || + (DNS_RRCLASS_ANY == p_RRHeader.m_Attributes.m_u16Class)) + { + + if ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + { + // PTR request +#ifdef MDNS_IP4_SUPPORT + stcMDNS_RRDomain reverseIP4Domain; + if ((_buildDomainForReverseIP4(_getResponseMulticastInterface(), reverseIP4Domain)) && + (p_RRHeader.m_Domain == reverseIP4Domain)) + { + // Reverse domain match + u8ReplyMask |= ContentFlag_PTR_IP4; + } +#endif +#ifdef MDNS_IP6_SUPPORT + // TODO +#endif + } // Address qeuest + + stcMDNS_RRDomain hostDomain; + if ((_buildDomainForHost(m_pcHostname, hostDomain)) && + (p_RRHeader.m_Domain == hostDomain)) // Host domain match + { + + (p_pbFullNameMatch ? (*p_pbFullNameMatch = true) : (0)); + +#ifdef MDNS_IP4_SUPPORT + if ((DNS_RRTYPE_A == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + { + // IP4 address request + u8ReplyMask |= ContentFlag_A; + } +#endif +#ifdef MDNS_IP6_SUPPORT + if ((DNS_RRTYPE_AAAA == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + { + // IP6 address request + u8ReplyMask |= ContentFlag_AAAA; + } +#endif + } + } + else + { + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForHost: INVALID RR-class (0x%04X)!\n"), p_RRHeader.m_Attributes.m_u16Class);); + } + DEBUG_EX_INFO(if (u8ReplyMask) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForHost: 0x%X\n"), u8ReplyMask); + }); + return u8ReplyMask; +} + +/* + MDNSResponder::_replyMaskForService + + Determines the relevant service answers for the given question + - A PTR dns-sd service enum question (_services.dns-sd._udp.local) will result into an PTR_TYPE (eg. _http._tcp.local) answer + - A PTR service type question (eg. _http._tcp.local) will result into an PTR_NAME (eg. MyESP._http._tcp.local) answer + - A PTR service name question (eg. MyESP._http._tcp.local) will result into an PTR_NAME (eg. MyESP._http._tcp.local) answer + - A SRV service name question (eg. MyESP._http._tcp.local) will result into an SRV (eg. 5000 MyESP.local) answer + - A TXT service name question (eg. MyESP._http._tcp.local) will result into an TXT (eg. c#=1) answer + + In addition, a full name match (question domain == service instance domain) is marked. +*/ +uint8_t MDNSResponder::_replyMaskForService(const MDNSResponder::stcMDNS_RRHeader& p_RRHeader, + const MDNSResponder::stcMDNSService& p_Service, + bool* p_pbFullNameMatch /*= 0*/) const +{ + + uint8_t u8ReplyMask = 0; + (p_pbFullNameMatch ? *p_pbFullNameMatch = false : 0); + + if ((DNS_RRCLASS_IN == p_RRHeader.m_Attributes.m_u16Class) || + (DNS_RRCLASS_ANY == p_RRHeader.m_Attributes.m_u16Class)) + { + + stcMDNS_RRDomain DNSSDDomain; + if ((_buildDomainForDNSSD(DNSSDDomain)) && // _services._dns-sd._udp.local + (p_RRHeader.m_Domain == DNSSDDomain) && + ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type))) + { + // Common service info requested + u8ReplyMask |= ContentFlag_PTR_TYPE; + } + + stcMDNS_RRDomain serviceDomain; + if ((_buildDomainForService(p_Service, false, serviceDomain)) && // eg. _http._tcp.local + (p_RRHeader.m_Domain == serviceDomain) && + ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type))) + { + // Special service info requested + u8ReplyMask |= ContentFlag_PTR_NAME; + } + + if ((_buildDomainForService(p_Service, true, serviceDomain)) && // eg. MyESP._http._tcp.local + (p_RRHeader.m_Domain == serviceDomain)) + { + + (p_pbFullNameMatch ? (*p_pbFullNameMatch = true) : (0)); + + if ((DNS_RRTYPE_SRV == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + { + // Instance info SRV requested + u8ReplyMask |= ContentFlag_SRV; + } + if ((DNS_RRTYPE_TXT == p_RRHeader.m_Attributes.m_u16Type) || + (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) + { + // Instance info TXT requested + u8ReplyMask |= ContentFlag_TXT; + } + } + } + else + { + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForService: INVALID RR-class (0x%04X)!\n"), p_RRHeader.m_Attributes.m_u16Class);); + } + DEBUG_EX_INFO(if (u8ReplyMask) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForService(%s.%s.%s): 0x%X\n"), p_Service.m_pcName, p_Service.m_pcService, p_Service.m_pcProtocol, u8ReplyMask); + }); + return u8ReplyMask; +} + +} // namespace MDNSImplementation + +} // namespace esp8266 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp new file mode 100644 index 0000000000..d5a0ccd762 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp @@ -0,0 +1,851 @@ +/* + LEAmDNS_Helpers.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#include <lwip/igmp.h> + +#include "ESP8266mDNS.h" +#include "LEAmDNS_lwIPdefs.h" +#include "LEAmDNS_Priv.h" + + +namespace +{ + +/* + strrstr (static) + + Backwards search for p_pcPattern in p_pcString + Based on: https://stackoverflow.com/a/1634398/2778898 + +*/ +const char* strrstr(const char*__restrict p_pcString, const char*__restrict p_pcPattern) +{ + + const char* pcResult = 0; + + size_t stStringLength = (p_pcString ? strlen(p_pcString) : 0); + size_t stPatternLength = (p_pcPattern ? strlen(p_pcPattern) : 0); + + if ((stStringLength) && + (stPatternLength) && + (stPatternLength <= stStringLength)) + { + // Pattern is shorter or has the same length tham the string + + for (const char* s = (p_pcString + stStringLength - stPatternLength); s >= p_pcString; --s) + { + if (0 == strncmp(s, p_pcPattern, stPatternLength)) + { + pcResult = s; + break; + } + } + } + return pcResult; +} + + +} // anonymous + + + + + +namespace esp8266 +{ + +/* + LEAmDNS +*/ +namespace MDNSImplementation +{ + +/** + HELPERS +*/ + +/* + MDNSResponder::indexDomain (static) + + Updates the given domain 'p_rpcHostname' by appending a delimiter and an index number. + + If the given domain already hasa numeric index (after the given delimiter), this index + incremented. If not, the delimiter and index '2' is added. + + If 'p_rpcHostname' is empty (==0), the given default name 'p_pcDefaultHostname' is used, + if no default is given, 'esp8266' is used. + +*/ +/*static*/ bool MDNSResponder::indexDomain(char*& p_rpcDomain, + const char* p_pcDivider /*= "-"*/, + const char* p_pcDefaultDomain /*= 0*/) +{ + + bool bResult = false; + + // Ensure a divider exists; use '-' as default + const char* pcDivider = (p_pcDivider ? : "-"); + + if (p_rpcDomain) + { + const char* pFoundDivider = strrstr(p_rpcDomain, pcDivider); + if (pFoundDivider) // maybe already extended + { + char* pEnd = 0; + unsigned long ulIndex = strtoul((pFoundDivider + strlen(pcDivider)), &pEnd, 10); + if ((ulIndex) && + ((pEnd - p_rpcDomain) == (ptrdiff_t)strlen(p_rpcDomain)) && + (!*pEnd)) // Valid (old) index found + { + + char acIndexBuffer[16]; + sprintf(acIndexBuffer, "%lu", (++ulIndex)); + size_t stLength = ((pFoundDivider - p_rpcDomain + strlen(pcDivider)) + strlen(acIndexBuffer) + 1); + char* pNewHostname = new char[stLength]; + if (pNewHostname) + { + memcpy(pNewHostname, p_rpcDomain, (pFoundDivider - p_rpcDomain + strlen(pcDivider))); + pNewHostname[pFoundDivider - p_rpcDomain + strlen(pcDivider)] = 0; + strcat(pNewHostname, acIndexBuffer); + + delete[] p_rpcDomain; + p_rpcDomain = pNewHostname; + + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.println(F("[MDNSResponder] indexDomain: FAILED to alloc new hostname!"));); + } + } + else + { + pFoundDivider = 0; // Flag the need to (base) extend the hostname + } + } + + if (!pFoundDivider) // not yet extended (or failed to increment extension) -> start indexing + { + size_t stLength = strlen(p_rpcDomain) + (strlen(pcDivider) + 1 + 1); // Name + Divider + '2' + '\0' + char* pNewHostname = new char[stLength]; + if (pNewHostname) + { + sprintf(pNewHostname, "%s%s2", p_rpcDomain, pcDivider); + + delete[] p_rpcDomain; + p_rpcDomain = pNewHostname; + + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.println(F("[MDNSResponder] indexDomain: FAILED to alloc new hostname!"));); + } + } + } + else + { + // No given host domain, use base or default + const char* cpcDefaultName = (p_pcDefaultDomain ? : "esp8266"); + + size_t stLength = strlen(cpcDefaultName) + 1; // '\0' + p_rpcDomain = new char[stLength]; + if (p_rpcDomain) + { + strncpy(p_rpcDomain, cpcDefaultName, stLength); + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.println(F("[MDNSResponder] indexDomain: FAILED to alloc new hostname!"));); + } + } + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] indexDomain: %s\n"), p_rpcDomain);); + return bResult; +} + + +/* + UDP CONTEXT +*/ + +bool MDNSResponder::_callProcess(void) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf("[MDNSResponder] _callProcess (%lu, triggered by: %s)\n", millis(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str());); + + return _process(false); +} + +/* + MDNSResponder::_allocUDPContext + + (Re-)Creates the one-and-only UDP context for the MDNS responder. + The context is added to the 'multicast'-group and listens to the MDNS port (5353). + The travel-distance for multicast messages is set to 1 (local, via MDNS_MULTICAST_TTL). + Messages are received via the MDNSResponder '_update' function. CAUTION: This function + is called from the WiFi stack side of the ESP stack system. + +*/ +bool MDNSResponder::_allocUDPContext(void) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.println("[MDNSResponder] _allocUDPContext");); + + bool bResult = false; + + _releaseUDPContext(); + +#ifdef MDNS_IP4_SUPPORT + ip_addr_t multicast_addr = DNS_MQUERY_IPV4_GROUP_INIT; +#endif +#ifdef MDNS_IP6_SUPPORT + //TODO: set multicast address (lwip_joingroup() is IPv4 only at the time of writing) + multicast_addr.addr = DNS_MQUERY_IPV6_GROUP_INIT; +#endif + if (ERR_OK == igmp_joingroup(ip_2_ip4(&m_netif->ip_addr), ip_2_ip4(&multicast_addr))) + { + m_pUDPContext = new UdpContext; + m_pUDPContext->ref(); + + if (m_pUDPContext->listen(IP4_ADDR_ANY, DNS_MQUERY_PORT)) + { + m_pUDPContext->setMulticastTTL(MDNS_MULTICAST_TTL); + m_pUDPContext->onRx(std::bind(&MDNSResponder::_callProcess, this)); + + bResult = m_pUDPContext->connect(&multicast_addr, DNS_MQUERY_PORT); + } + } + return bResult; +} + +/* + MDNSResponder::_releaseUDPContext +*/ +bool MDNSResponder::_releaseUDPContext(void) +{ + + if (m_pUDPContext) + { + m_pUDPContext->unref(); + m_pUDPContext = 0; + } + return true; +} + + +/* + SERVICE QUERY +*/ + +/* + MDNSResponder::_allocServiceQuery +*/ +MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_allocServiceQuery(void) +{ + + stcMDNSServiceQuery* pServiceQuery = new stcMDNSServiceQuery; + if (pServiceQuery) + { + // Link to query list + pServiceQuery->m_pNext = m_pServiceQueries; + m_pServiceQueries = pServiceQuery; + } + return m_pServiceQueries; +} + +/* + MDNSResponder::_removeServiceQuery +*/ +bool MDNSResponder::_removeServiceQuery(MDNSResponder::stcMDNSServiceQuery* p_pServiceQuery) +{ + + bool bResult = false; + + if (p_pServiceQuery) + { + stcMDNSServiceQuery* pPred = m_pServiceQueries; + while ((pPred) && + (pPred->m_pNext != p_pServiceQuery)) + { + pPred = pPred->m_pNext; + } + if (pPred) + { + pPred->m_pNext = p_pServiceQuery->m_pNext; + delete p_pServiceQuery; + bResult = true; + } + else // No predecesor + { + if (m_pServiceQueries == p_pServiceQuery) + { + m_pServiceQueries = p_pServiceQuery->m_pNext; + delete p_pServiceQuery; + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.println("[MDNSResponder] _releaseServiceQuery: INVALID service query!");); + } + } + } + return bResult; +} + +/* + MDNSResponder::_removeLegacyServiceQuery +*/ +bool MDNSResponder::_removeLegacyServiceQuery(void) +{ + + stcMDNSServiceQuery* pLegacyServiceQuery = _findLegacyServiceQuery(); + return (pLegacyServiceQuery ? _removeServiceQuery(pLegacyServiceQuery) : true); +} + +/* + MDNSResponder::_findServiceQuery + + 'Convert' hMDNSServiceQuery to stcMDNSServiceQuery* (ensure existance) + +*/ +MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_findServiceQuery(MDNSResponder::hMDNSServiceQuery p_hServiceQuery) +{ + + stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; + while (pServiceQuery) + { + if ((hMDNSServiceQuery)pServiceQuery == p_hServiceQuery) + { + break; + } + pServiceQuery = pServiceQuery->m_pNext; + } + return pServiceQuery; +} + +/* + MDNSResponder::_findLegacyServiceQuery +*/ +MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_findLegacyServiceQuery(void) +{ + + stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; + while (pServiceQuery) + { + if (pServiceQuery->m_bLegacyQuery) + { + break; + } + pServiceQuery = pServiceQuery->m_pNext; + } + return pServiceQuery; +} + +/* + MDNSResponder::_releaseServiceQueries +*/ +bool MDNSResponder::_releaseServiceQueries(void) +{ + while (m_pServiceQueries) + { + stcMDNSServiceQuery* pNext = m_pServiceQueries->m_pNext; + delete m_pServiceQueries; + m_pServiceQueries = pNext; + } + return true; +} + +/* + MDNSResponder::_findNextServiceQueryByServiceType +*/ +MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_findNextServiceQueryByServiceType(const stcMDNS_RRDomain& p_ServiceTypeDomain, + const stcMDNSServiceQuery* p_pPrevServiceQuery) +{ + stcMDNSServiceQuery* pMatchingServiceQuery = 0; + + stcMDNSServiceQuery* pServiceQuery = (p_pPrevServiceQuery ? p_pPrevServiceQuery->m_pNext : m_pServiceQueries); + while (pServiceQuery) + { + if (p_ServiceTypeDomain == pServiceQuery->m_ServiceTypeDomain) + { + pMatchingServiceQuery = pServiceQuery; + break; + } + pServiceQuery = pServiceQuery->m_pNext; + } + return pMatchingServiceQuery; +} + + +/* + HOSTNAME +*/ + +/* + MDNSResponder::_setHostname +*/ +bool MDNSResponder::_setHostname(const char* p_pcHostname) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _allocHostname (%s)\n"), p_pcHostname);); + + bool bResult = false; + + _releaseHostname(); + + size_t stLength = 0; + if ((p_pcHostname) && + (MDNS_DOMAIN_LABEL_MAXLENGTH >= (stLength = strlen(p_pcHostname)))) // char max size for a single label + { + // Copy in hostname characters as lowercase + if ((bResult = (0 != (m_pcHostname = new char[stLength + 1])))) + { +#ifdef MDNS_FORCE_LOWERCASE_HOSTNAME + size_t i = 0; + for (; i < stLength; ++i) + { + m_pcHostname[i] = (isupper(p_pcHostname[i]) ? tolower(p_pcHostname[i]) : p_pcHostname[i]); + } + m_pcHostname[i] = 0; +#else + strncpy(m_pcHostname, p_pcHostname, (stLength + 1)); +#endif + } + } + return bResult; +} + +/* + MDNSResponder::_releaseHostname +*/ +bool MDNSResponder::_releaseHostname(void) +{ + + if (m_pcHostname) + { + delete[] m_pcHostname; + m_pcHostname = 0; + } + return true; +} + + +/* + SERVICE +*/ + +/* + MDNSResponder::_allocService +*/ +MDNSResponder::stcMDNSService* MDNSResponder::_allocService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol, + uint16_t p_u16Port) +{ + + stcMDNSService* pService = 0; + if (((!p_pcName) || + (MDNS_DOMAIN_LABEL_MAXLENGTH >= strlen(p_pcName))) && + (p_pcService) && + (MDNS_SERVICE_NAME_LENGTH >= strlen(p_pcService)) && + (p_pcProtocol) && + (MDNS_SERVICE_PROTOCOL_LENGTH >= strlen(p_pcProtocol)) && + (p_u16Port) && + (0 != (pService = new stcMDNSService)) && + (pService->setName(p_pcName ? : m_pcHostname)) && + (pService->setService(p_pcService)) && + (pService->setProtocol(p_pcProtocol))) + { + + pService->m_bAutoName = (0 == p_pcName); + pService->m_u16Port = p_u16Port; + + // Add to list (or start list) + pService->m_pNext = m_pServices; + m_pServices = pService; + } + return pService; +} + +/* + MDNSResponder::_releaseService +*/ +bool MDNSResponder::_releaseService(MDNSResponder::stcMDNSService* p_pService) +{ + + bool bResult = false; + + if (p_pService) + { + stcMDNSService* pPred = m_pServices; + while ((pPred) && + (pPred->m_pNext != p_pService)) + { + pPred = pPred->m_pNext; + } + if (pPred) + { + pPred->m_pNext = p_pService->m_pNext; + delete p_pService; + bResult = true; + } + else // No predecesor + { + if (m_pServices == p_pService) + { + m_pServices = p_pService->m_pNext; + delete p_pService; + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.println("[MDNSResponder] _releaseService: INVALID service!");); + } + } + } + return bResult; +} + +/* + MDNSResponder::_releaseServices +*/ +bool MDNSResponder::_releaseServices(void) +{ + + stcMDNSService* pService = m_pServices; + while (pService) + { + _releaseService(pService); + pService = m_pServices; + } + return true; +} + +/* + MDNSResponder::_findService +*/ +MDNSResponder::stcMDNSService* MDNSResponder::_findService(const char* p_pcName, + const char* p_pcService, + const char* p_pcProtocol) +{ + + stcMDNSService* pService = m_pServices; + while (pService) + { + if ((0 == strcmp(pService->m_pcName, p_pcName)) && + (0 == strcmp(pService->m_pcService, p_pcService)) && + (0 == strcmp(pService->m_pcProtocol, p_pcProtocol))) + { + + break; + } + pService = pService->m_pNext; + } + return pService; +} + +/* + MDNSResponder::_findService +*/ +MDNSResponder::stcMDNSService* MDNSResponder::_findService(const MDNSResponder::hMDNSService p_hService) +{ + + stcMDNSService* pService = m_pServices; + while (pService) + { + if (p_hService == (hMDNSService)pService) + { + break; + } + pService = pService->m_pNext; + } + return pService; +} + + +/* + SERVICE TXT +*/ + +/* + MDNSResponder::_allocServiceTxt +*/ +MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_allocServiceTxt(MDNSResponder::stcMDNSService* p_pService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp) +{ + + stcMDNSServiceTxt* pTxt = 0; + + if ((p_pService) && + (p_pcKey) && + (MDNS_SERVICE_TXT_MAXLENGTH > (p_pService->m_Txts.length() + + 1 + // Length byte + (p_pcKey ? strlen(p_pcKey) : 0) + + 1 + // '=' + (p_pcValue ? strlen(p_pcValue) : 0)))) + { + + pTxt = new stcMDNSServiceTxt; + if (pTxt) + { + size_t stLength = (p_pcKey ? strlen(p_pcKey) : 0); + pTxt->m_pcKey = new char[stLength + 1]; + if (pTxt->m_pcKey) + { + strncpy(pTxt->m_pcKey, p_pcKey, stLength); pTxt->m_pcKey[stLength] = 0; + } + + if (p_pcValue) + { + stLength = (p_pcValue ? strlen(p_pcValue) : 0); + pTxt->m_pcValue = new char[stLength + 1]; + if (pTxt->m_pcValue) + { + strncpy(pTxt->m_pcValue, p_pcValue, stLength); pTxt->m_pcValue[stLength] = 0; + } + } + pTxt->m_bTemp = p_bTemp; + + // Add to list (or start list) + p_pService->m_Txts.add(pTxt); + } + } + return pTxt; +} + +/* + MDNSResponder::_releaseServiceTxt +*/ +bool MDNSResponder::_releaseServiceTxt(MDNSResponder::stcMDNSService* p_pService, + MDNSResponder::stcMDNSServiceTxt* p_pTxt) +{ + + return ((p_pService) && + (p_pTxt) && + (p_pService->m_Txts.remove(p_pTxt))); +} + +/* + MDNSResponder::_updateServiceTxt +*/ +MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_updateServiceTxt(MDNSResponder::stcMDNSService* p_pService, + MDNSResponder::stcMDNSServiceTxt* p_pTxt, + const char* p_pcValue, + bool p_bTemp) +{ + + if ((p_pService) && + (p_pTxt) && + (MDNS_SERVICE_TXT_MAXLENGTH > (p_pService->m_Txts.length() - + (p_pTxt->m_pcValue ? strlen(p_pTxt->m_pcValue) : 0) + + (p_pcValue ? strlen(p_pcValue) : 0)))) + { + p_pTxt->update(p_pcValue); + p_pTxt->m_bTemp = p_bTemp; + } + return p_pTxt; +} + +/* + MDNSResponder::_findServiceTxt +*/ +MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_findServiceTxt(MDNSResponder::stcMDNSService* p_pService, + const char* p_pcKey) +{ + + return (p_pService ? p_pService->m_Txts.find(p_pcKey) : 0); +} + +/* + MDNSResponder::_findServiceTxt +*/ +MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_findServiceTxt(MDNSResponder::stcMDNSService* p_pService, + const hMDNSTxt p_hTxt) +{ + + return (((p_pService) && (p_hTxt)) ? p_pService->m_Txts.find((stcMDNSServiceTxt*)p_hTxt) : 0); +} + +/* + MDNSResponder::_addServiceTxt +*/ +MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_addServiceTxt(MDNSResponder::stcMDNSService* p_pService, + const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp) +{ + stcMDNSServiceTxt* pResult = 0; + + if ((p_pService) && + (p_pcKey) && + (strlen(p_pcKey))) + { + + stcMDNSServiceTxt* pTxt = p_pService->m_Txts.find(p_pcKey); + if (pTxt) + { + pResult = _updateServiceTxt(p_pService, pTxt, p_pcValue, p_bTemp); + } + else + { + pResult = _allocServiceTxt(p_pService, p_pcKey, p_pcValue, p_bTemp); + } + } + return pResult; +} + +MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_answerKeyValue(const hMDNSServiceQuery p_hServiceQuery, + const uint32_t p_u32AnswerIndex) +{ + stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); + stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); + // Fill m_pcTxts (if not already done) + return (pSQAnswer) ? pSQAnswer->m_Txts.m_pTxts : 0; +} + +/* + MDNSResponder::_collectServiceTxts +*/ +bool MDNSResponder::_collectServiceTxts(MDNSResponder::stcMDNSService& p_rService) +{ + + // Call Dynamic service callbacks + if (m_fnServiceTxtCallback) + { + m_fnServiceTxtCallback((hMDNSService)&p_rService); + } + if (p_rService.m_fnTxtCallback) + { + p_rService.m_fnTxtCallback((hMDNSService)&p_rService); + } + return true; +} + +/* + MDNSResponder::_releaseTempServiceTxts +*/ +bool MDNSResponder::_releaseTempServiceTxts(MDNSResponder::stcMDNSService& p_rService) +{ + + return (p_rService.m_Txts.removeTempTxts()); +} + + +/* + MISC +*/ + +#ifdef DEBUG_ESP_MDNS_RESPONDER +/* + MDNSResponder::_printRRDomain +*/ +bool MDNSResponder::_printRRDomain(const MDNSResponder::stcMDNS_RRDomain& p_RRDomain) const +{ + + //DEBUG_OUTPUT.printf_P(PSTR("Domain: ")); + + const char* pCursor = p_RRDomain.m_acName; + uint8_t u8Length = *pCursor++; + if (u8Length) + { + while (u8Length) + { + for (uint8_t u = 0; u < u8Length; ++u) + { + DEBUG_OUTPUT.printf_P(PSTR("%c"), *(pCursor++)); + } + u8Length = *pCursor++; + if (u8Length) + { + DEBUG_OUTPUT.printf_P(PSTR(".")); + } + } + } + else // empty domain + { + DEBUG_OUTPUT.printf_P(PSTR("-empty-")); + } + //DEBUG_OUTPUT.printf_P(PSTR("\n")); + + return true; +} + +/* + MDNSResponder::_printRRAnswer +*/ +bool MDNSResponder::_printRRAnswer(const MDNSResponder::stcMDNS_RRAnswer& p_RRAnswer) const +{ + + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] RRAnswer: ")); + _printRRDomain(p_RRAnswer.m_Header.m_Domain); + DEBUG_OUTPUT.printf_P(PSTR(" Type:0x%04X Class:0x%04X TTL:%u, "), p_RRAnswer.m_Header.m_Attributes.m_u16Type, p_RRAnswer.m_Header.m_Attributes.m_u16Class, p_RRAnswer.m_u32TTL); + switch (p_RRAnswer.m_Header.m_Attributes.m_u16Type & (~0x8000)) // Topmost bit might carry 'cache flush' flag + { +#ifdef MDNS_IP4_SUPPORT + case DNS_RRTYPE_A: + DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((const stcMDNS_RRAnswerA*)&p_RRAnswer)->m_IPAddress.toString().c_str()); + break; +#endif + case DNS_RRTYPE_PTR: + DEBUG_OUTPUT.printf_P(PSTR("PTR ")); + _printRRDomain(((const stcMDNS_RRAnswerPTR*)&p_RRAnswer)->m_PTRDomain); + break; + case DNS_RRTYPE_TXT: + { + size_t stTxtLength = ((const stcMDNS_RRAnswerTXT*)&p_RRAnswer)->m_Txts.c_strLength(); + char* pTxts = new char[stTxtLength]; + if (pTxts) + { + ((/*const c_str()!!*/stcMDNS_RRAnswerTXT*)&p_RRAnswer)->m_Txts.c_str(pTxts); + DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts); + delete[] pTxts; + } + break; + } +#ifdef MDNS_IP6_SUPPORT + case DNS_RRTYPE_AAAA: + DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((stcMDNS_RRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); + break; +#endif + case DNS_RRTYPE_SRV: + DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((const stcMDNS_RRAnswerSRV*)&p_RRAnswer)->m_u16Port); + _printRRDomain(((const stcMDNS_RRAnswerSRV*)&p_RRAnswer)->m_SRVDomain); + break; + default: + DEBUG_OUTPUT.printf_P(PSTR("generic ")); + break; + } + DEBUG_OUTPUT.printf_P(PSTR("\n")); + + return true; +} +#endif + +} // namespace MDNSImplementation + +} // namespace esp8266 + + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Priv.h b/libraries/ESP8266mDNS/src/LEAmDNS_Priv.h new file mode 100644 index 0000000000..4750669d38 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Priv.h @@ -0,0 +1,182 @@ +/* + LEAmDNS_Priv.h + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#ifndef MDNS_PRIV_H +#define MDNS_PRIV_H + +namespace esp8266 +{ + +/* + LEAmDNS +*/ + +namespace MDNSImplementation +{ + +// Enable class debug functions +#define ESP_8266_MDNS_INCLUDE +//#define DEBUG_ESP_MDNS_RESPONDER + +#if !defined(DEBUG_ESP_MDNS_RESPONDER) && defined(DEBUG_ESP_MDNS) +#define DEBUG_ESP_MDNS_RESPONDER +#endif + +#ifndef LWIP_OPEN_SRC +#define LWIP_OPEN_SRC +#endif + +// +// If ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE is defined, the mDNS responder ignores a successful probing +// This allows to drive the responder in a environment, where 'update()' isn't called in the loop +//#define ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE + +// Enable/disable debug trace macros +#if defined(DEBUG_ESP_PORT) && defined(DEBUG_ESP_MDNS_RESPONDER) +#define DEBUG_ESP_MDNS_INFO +#define DEBUG_ESP_MDNS_ERR +#define DEBUG_ESP_MDNS_TX +#define DEBUG_ESP_MDNS_RX +#endif + +#ifdef DEBUG_ESP_MDNS_RESPONDER +#ifdef DEBUG_ESP_MDNS_INFO +#define DEBUG_EX_INFO(A) A +#else +#define DEBUG_EX_INFO(A) +#endif +#ifdef DEBUG_ESP_MDNS_ERR +#define DEBUG_EX_ERR(A) A +#else +#define DEBUG_EX_ERR(A) +#endif +#ifdef DEBUG_ESP_MDNS_TX +#define DEBUG_EX_TX(A) A +#else +#define DEBUG_EX_TX(A) +#endif +#ifdef DEBUG_ESP_MDNS_RX +#define DEBUG_EX_RX(A) A +#else +#define DEBUG_EX_RX(A) +#endif + +#ifdef DEBUG_ESP_PORT +#define DEBUG_OUTPUT DEBUG_ESP_PORT +#else +#define DEBUG_OUTPUT Serial +#endif +#else +#define DEBUG_EX_INFO(A) do { (void)0; } while (0) +#define DEBUG_EX_ERR(A) do { (void)0; } while (0) +#define DEBUG_EX_TX(A) do { (void)0; } while (0) +#define DEBUG_EX_RX(A) do { (void)0; } while (0) +#endif + + +/* Replaced by 'lwip/prot/dns.h' definitions + #ifdef MDNS_IP4_SUPPORT + #define MDNS_MULTICAST_ADDR_IP4 (IPAddress(224, 0, 0, 251)) // ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT + #endif + #ifdef MDNS_IP6_SUPPORT + #define MDNS_MULTICAST_ADDR_IP6 (IPAddress("FF02::FB")) // ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT + #endif*/ +//#define MDNS_MULTICAST_PORT 5353 + +/* + This is NOT the TTL (Time-To-Live) for MDNS records, but the + subnet level distance MDNS records should travel. + 1 sets the subnet distance to 'local', which is default for MDNS. + (Btw.: 255 would set it to 'as far as possible' -> internet) + + However, RFC 3171 seems to force 255 instead +*/ +#define MDNS_MULTICAST_TTL 255/*1*/ + +/* + This is the MDNS record TTL + Host level records are set to 2min (120s) + service level records are set to 75min (4500s) +*/ +#define MDNS_HOST_TTL 120 +#define MDNS_SERVICE_TTL 4500 + +/* + Compressed labels are flaged by the two topmost bits of the length byte being set +*/ +#define MDNS_DOMAIN_COMPRESS_MARK 0xC0 +/* + Avoid endless recursion because of malformed compressed labels +*/ +#define MDNS_DOMAIN_MAX_REDIRCTION 6 + +/* + Default service priority and weight in SRV answers +*/ +#define MDNS_SRV_PRIORITY 0 +#define MDNS_SRV_WEIGHT 0 + +/* + Delay between and number of probes for host and service domains + Delay between and number of announces for host and service domains + Delay between and number of service queries; the delay is multiplied by the resent number in '_checkServiceQueryCache' +*/ +#define MDNS_PROBE_DELAY 250 +#define MDNS_PROBE_COUNT 3 +#define MDNS_ANNOUNCE_DELAY 1000 +#define MDNS_ANNOUNCE_COUNT 8 +#define MDNS_DYNAMIC_QUERY_RESEND_COUNT 5 +#define MDNS_DYNAMIC_QUERY_RESEND_DELAY 5000 + + +/* + Force host domain to use only lowercase letters +*/ +//#define MDNS_FORCE_LOWERCASE_HOSTNAME + +/* + Enable/disable the usage of the F() macro in debug trace printf calls. + There needs to be an PGM comptible printf function to use this. + + USE_PGM_PRINTF and F +*/ +#define USE_PGM_PRINTF + +#ifdef USE_PGM_PRINTF +#else +#ifdef F +#undef F +#endif +#define F(A) A +#endif + +} // namespace MDNSImplementation + +} // namespace esp8266 + +// Include the main header, so the submodlues only need to include this header +#include "LEAmDNS.h" + + +#endif // MDNS_PRIV_H diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp new file mode 100644 index 0000000000..18c4a95eb3 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp @@ -0,0 +1,2477 @@ +/* + LEAmDNS_Structs.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#include "ESP8266mDNS.h" +#include "LEAmDNS_Priv.h" +#include "LEAmDNS_lwIPdefs.h" + +namespace esp8266 +{ + +/* + LEAmDNS +*/ +namespace MDNSImplementation +{ + +/** + STRUCTS +*/ + +/** + MDNSResponder::stcMDNSServiceTxt + + One MDNS TXT item. + m_pcValue may be '\0'. + Objects can be chained together (list, m_pNext). + A 'm_bTemp' flag differentiates between static and dynamic items. + Output as byte array 'c#=1' is supported. +*/ + +/* + MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt constructor +*/ +MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt(const char* p_pcKey /*= 0*/, + const char* p_pcValue /*= 0*/, + bool p_bTemp /*= false*/) + : m_pNext(0), + m_pcKey(0), + m_pcValue(0), + m_bTemp(p_bTemp) +{ + + setKey(p_pcKey); + setValue(p_pcValue); +} + +/* + MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt copy-constructor +*/ +MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt(const MDNSResponder::stcMDNSServiceTxt& p_Other) + : m_pNext(0), + m_pcKey(0), + m_pcValue(0), + m_bTemp(false) +{ + + operator=(p_Other); +} + +/* + MDNSResponder::stcMDNSServiceTxt::~stcMDNSServiceTxt destructor +*/ +MDNSResponder::stcMDNSServiceTxt::~stcMDNSServiceTxt(void) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNSServiceTxt::operator= +*/ +MDNSResponder::stcMDNSServiceTxt& MDNSResponder::stcMDNSServiceTxt::operator=(const MDNSResponder::stcMDNSServiceTxt& p_Other) +{ + + if (&p_Other != this) + { + clear(); + set(p_Other.m_pcKey, p_Other.m_pcValue, p_Other.m_bTemp); + } + return *this; +} + +/* + MDNSResponder::stcMDNSServiceTxt::clear +*/ +bool MDNSResponder::stcMDNSServiceTxt::clear(void) +{ + + releaseKey(); + releaseValue(); + return true; +} + +/* + MDNSResponder::stcMDNSServiceTxt::allocKey +*/ +char* MDNSResponder::stcMDNSServiceTxt::allocKey(size_t p_stLength) +{ + + releaseKey(); + if (p_stLength) + { + m_pcKey = new char[p_stLength + 1]; + } + return m_pcKey; +} + +/* + MDNSResponder::stcMDNSServiceTxt::setKey +*/ +bool MDNSResponder::stcMDNSServiceTxt::setKey(const char* p_pcKey, + size_t p_stLength) +{ + + bool bResult = false; + + releaseKey(); + if (p_stLength) + { + if (allocKey(p_stLength)) + { + strncpy(m_pcKey, p_pcKey, p_stLength); + m_pcKey[p_stLength] = 0; + bResult = true; + } + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceTxt::setKey +*/ +bool MDNSResponder::stcMDNSServiceTxt::setKey(const char* p_pcKey) +{ + + return setKey(p_pcKey, (p_pcKey ? strlen(p_pcKey) : 0)); +} + +/* + MDNSResponder::stcMDNSServiceTxt::releaseKey +*/ +bool MDNSResponder::stcMDNSServiceTxt::releaseKey(void) +{ + + if (m_pcKey) + { + delete[] m_pcKey; + m_pcKey = 0; + } + return true; +} + +/* + MDNSResponder::stcMDNSServiceTxt::allocValue +*/ +char* MDNSResponder::stcMDNSServiceTxt::allocValue(size_t p_stLength) +{ + + releaseValue(); + if (p_stLength) + { + m_pcValue = new char[p_stLength + 1]; + } + return m_pcValue; +} + +/* + MDNSResponder::stcMDNSServiceTxt::setValue +*/ +bool MDNSResponder::stcMDNSServiceTxt::setValue(const char* p_pcValue, + size_t p_stLength) +{ + + bool bResult = false; + + releaseValue(); + if (p_stLength) + { + if (allocValue(p_stLength)) + { + strncpy(m_pcValue, p_pcValue, p_stLength); + m_pcValue[p_stLength] = 0; + bResult = true; + } + } + else // No value -> also OK + { + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceTxt::setValue +*/ +bool MDNSResponder::stcMDNSServiceTxt::setValue(const char* p_pcValue) +{ + + return setValue(p_pcValue, (p_pcValue ? strlen(p_pcValue) : 0)); +} + +/* + MDNSResponder::stcMDNSServiceTxt::releaseValue +*/ +bool MDNSResponder::stcMDNSServiceTxt::releaseValue(void) +{ + + if (m_pcValue) + { + delete[] m_pcValue; + m_pcValue = 0; + } + return true; +} + +/* + MDNSResponder::stcMDNSServiceTxt::set +*/ +bool MDNSResponder::stcMDNSServiceTxt::set(const char* p_pcKey, + const char* p_pcValue, + bool p_bTemp /*= false*/) +{ + + m_bTemp = p_bTemp; + return ((setKey(p_pcKey)) && + (setValue(p_pcValue))); +} + +/* + MDNSResponder::stcMDNSServiceTxt::update +*/ +bool MDNSResponder::stcMDNSServiceTxt::update(const char* p_pcValue) +{ + + return setValue(p_pcValue); +} + +/* + MDNSResponder::stcMDNSServiceTxt::length + + length of eg. 'c#=1' without any closing '\0' +*/ +size_t MDNSResponder::stcMDNSServiceTxt::length(void) const +{ + + size_t stLength = 0; + if (m_pcKey) + { + stLength += strlen(m_pcKey); // Key + stLength += 1; // '=' + stLength += (m_pcValue ? strlen(m_pcValue) : 0); // Value + } + return stLength; +} + + +/** + MDNSResponder::stcMDNSServiceTxts + + A list of zero or more MDNS TXT items. + Dynamic TXT items can be removed by 'removeTempTxts'. + A TXT item can be looke up by its 'key' member. + Export as ';'-separated byte array is supported. + Export as 'length byte coded' byte array is supported. + Comparision ((all A TXT items in B and equal) AND (all B TXT items in A and equal)) is supported. + +*/ + +/* + MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts contructor +*/ +MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts(void) + : m_pTxts(0) +{ + +} + +/* + MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts copy-constructor +*/ +MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts(const stcMDNSServiceTxts& p_Other) + : m_pTxts(0) +{ + + operator=(p_Other); +} + +/* + MDNSResponder::stcMDNSServiceTxts::~stcMDNSServiceTxts destructor +*/ +MDNSResponder::stcMDNSServiceTxts::~stcMDNSServiceTxts(void) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNSServiceTxts::operator= +*/ +MDNSResponder::stcMDNSServiceTxts& MDNSResponder::stcMDNSServiceTxts::operator=(const stcMDNSServiceTxts& p_Other) +{ + + if (this != &p_Other) + { + clear(); + + for (stcMDNSServiceTxt* pOtherTxt = p_Other.m_pTxts; pOtherTxt; pOtherTxt = pOtherTxt->m_pNext) + { + add(new stcMDNSServiceTxt(*pOtherTxt)); + } + } + return *this; +} + +/* + MDNSResponder::stcMDNSServiceTxts::clear +*/ +bool MDNSResponder::stcMDNSServiceTxts::clear(void) +{ + + while (m_pTxts) + { + stcMDNSServiceTxt* pNext = m_pTxts->m_pNext; + delete m_pTxts; + m_pTxts = pNext; + } + return true; +} + +/* + MDNSResponder::stcMDNSServiceTxts::add +*/ +bool MDNSResponder::stcMDNSServiceTxts::add(MDNSResponder::stcMDNSServiceTxt* p_pTxt) +{ + + bool bResult = false; + + if (p_pTxt) + { + p_pTxt->m_pNext = m_pTxts; + m_pTxts = p_pTxt; + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceTxts::remove +*/ +bool MDNSResponder::stcMDNSServiceTxts::remove(stcMDNSServiceTxt* p_pTxt) +{ + + bool bResult = false; + + if (p_pTxt) + { + stcMDNSServiceTxt* pPred = m_pTxts; + while ((pPred) && + (pPred->m_pNext != p_pTxt)) + { + pPred = pPred->m_pNext; + } + if (pPred) + { + pPred->m_pNext = p_pTxt->m_pNext; + delete p_pTxt; + bResult = true; + } + else if (m_pTxts == p_pTxt) // No predecesor, but first item + { + m_pTxts = p_pTxt->m_pNext; + delete p_pTxt; + bResult = true; + } + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceTxts::removeTempTxts +*/ +bool MDNSResponder::stcMDNSServiceTxts::removeTempTxts(void) +{ + + bool bResult = true; + + stcMDNSServiceTxt* pTxt = m_pTxts; + while ((bResult) && + (pTxt)) + { + stcMDNSServiceTxt* pNext = pTxt->m_pNext; + if (pTxt->m_bTemp) + { + bResult = remove(pTxt); + } + pTxt = pNext; + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceTxts::find +*/ +MDNSResponder::stcMDNSServiceTxt* MDNSResponder::stcMDNSServiceTxts::find(const char* p_pcKey) +{ + + stcMDNSServiceTxt* pResult = 0; + + for (stcMDNSServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) + { + if ((p_pcKey) && + (0 == strcmp(pTxt->m_pcKey, p_pcKey))) + { + pResult = pTxt; + break; + } + } + return pResult; +} + +/* + MDNSResponder::stcMDNSServiceTxts::find +*/ +const MDNSResponder::stcMDNSServiceTxt* MDNSResponder::stcMDNSServiceTxts::find(const char* p_pcKey) const +{ + + const stcMDNSServiceTxt* pResult = 0; + + for (const stcMDNSServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) + { + if ((p_pcKey) && + (0 == strcmp(pTxt->m_pcKey, p_pcKey))) + { + + pResult = pTxt; + break; + } + } + return pResult; +} + +/* + MDNSResponder::stcMDNSServiceTxts::find +*/ +MDNSResponder::stcMDNSServiceTxt* MDNSResponder::stcMDNSServiceTxts::find(const stcMDNSServiceTxt* p_pTxt) +{ + + stcMDNSServiceTxt* pResult = 0; + + for (stcMDNSServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) + { + if (p_pTxt == pTxt) + { + pResult = pTxt; + break; + } + } + return pResult; +} + +/* + MDNSResponder::stcMDNSServiceTxts::length +*/ +uint16_t MDNSResponder::stcMDNSServiceTxts::length(void) const +{ + + uint16_t u16Length = 0; + + stcMDNSServiceTxt* pTxt = m_pTxts; + while (pTxt) + { + u16Length += 1; // Length byte + u16Length += pTxt->length(); // Text + pTxt = pTxt->m_pNext; + } + return u16Length; +} + +/* + MDNSResponder::stcMDNSServiceTxts::c_strLength + + (incl. closing '\0'). Length bytes place is used for delimiting ';' and closing '\0' +*/ +size_t MDNSResponder::stcMDNSServiceTxts::c_strLength(void) const +{ + + return length(); +} + +/* + MDNSResponder::stcMDNSServiceTxts::c_str +*/ +bool MDNSResponder::stcMDNSServiceTxts::c_str(char* p_pcBuffer) +{ + + bool bResult = false; + + if (p_pcBuffer) + { + bResult = true; + + *p_pcBuffer = 0; + for (stcMDNSServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) + { + size_t stLength; + if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) + { + if (pTxt != m_pTxts) + { + *p_pcBuffer++ = ';'; + } + strncpy(p_pcBuffer, pTxt->m_pcKey, stLength); p_pcBuffer[stLength] = 0; + p_pcBuffer += stLength; + *p_pcBuffer++ = '='; + if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) + { + strncpy(p_pcBuffer, pTxt->m_pcValue, stLength); p_pcBuffer[stLength] = 0; + p_pcBuffer += stLength; + } + } + } + *p_pcBuffer++ = 0; + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceTxts::bufferLength + + (incl. closing '\0'). +*/ +size_t MDNSResponder::stcMDNSServiceTxts::bufferLength(void) const +{ + + return (length() + 1); +} + +/* + MDNSResponder::stcMDNSServiceTxts::toBuffer +*/ +bool MDNSResponder::stcMDNSServiceTxts::buffer(char* p_pcBuffer) +{ + + bool bResult = false; + + if (p_pcBuffer) + { + bResult = true; + + *p_pcBuffer = 0; + for (stcMDNSServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) + { + *(unsigned char*)p_pcBuffer++ = pTxt->length(); + size_t stLength; + if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) + { + memcpy(p_pcBuffer, pTxt->m_pcKey, stLength); + p_pcBuffer += stLength; + *p_pcBuffer++ = '='; + if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) + { + memcpy(p_pcBuffer, pTxt->m_pcValue, stLength); + p_pcBuffer += stLength; + } + } + } + *p_pcBuffer++ = 0; + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceTxts::compare +*/ +bool MDNSResponder::stcMDNSServiceTxts::compare(const MDNSResponder::stcMDNSServiceTxts& p_Other) const +{ + + bool bResult = false; + + if ((bResult = (length() == p_Other.length()))) + { + // Compare A->B + for (const stcMDNSServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) + { + const stcMDNSServiceTxt* pOtherTxt = p_Other.find(pTxt->m_pcKey); + bResult = ((pOtherTxt) && + (pTxt->m_pcValue) && + (pOtherTxt->m_pcValue) && + (strlen(pTxt->m_pcValue) == strlen(pOtherTxt->m_pcValue)) && + (0 == strcmp(pTxt->m_pcValue, pOtherTxt->m_pcValue))); + } + // Compare B->A + for (const stcMDNSServiceTxt* pOtherTxt = p_Other.m_pTxts; ((bResult) && (pOtherTxt)); pOtherTxt = pOtherTxt->m_pNext) + { + const stcMDNSServiceTxt* pTxt = find(pOtherTxt->m_pcKey); + bResult = ((pTxt) && + (pOtherTxt->m_pcValue) && + (pTxt->m_pcValue) && + (strlen(pOtherTxt->m_pcValue) == strlen(pTxt->m_pcValue)) && + (0 == strcmp(pOtherTxt->m_pcValue, pTxt->m_pcValue))); + } + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceTxts::operator== +*/ +bool MDNSResponder::stcMDNSServiceTxts::operator==(const stcMDNSServiceTxts& p_Other) const +{ + + return compare(p_Other); +} + +/* + MDNSResponder::stcMDNSServiceTxts::operator!= +*/ +bool MDNSResponder::stcMDNSServiceTxts::operator!=(const stcMDNSServiceTxts& p_Other) const +{ + + return !compare(p_Other); +} + + +/** + MDNSResponder::stcMDNS_MsgHeader + + A MDNS message haeder. + +*/ + +/* + MDNSResponder::stcMDNS_MsgHeader::stcMDNS_MsgHeader +*/ +MDNSResponder::stcMDNS_MsgHeader::stcMDNS_MsgHeader(uint16_t p_u16ID /*= 0*/, + bool p_bQR /*= false*/, + unsigned char p_ucOpcode /*= 0*/, + bool p_bAA /*= false*/, + bool p_bTC /*= false*/, + bool p_bRD /*= false*/, + bool p_bRA /*= false*/, + unsigned char p_ucRCode /*= 0*/, + uint16_t p_u16QDCount /*= 0*/, + uint16_t p_u16ANCount /*= 0*/, + uint16_t p_u16NSCount /*= 0*/, + uint16_t p_u16ARCount /*= 0*/) + : m_u16ID(p_u16ID), + m_1bQR(p_bQR), m_4bOpcode(p_ucOpcode), m_1bAA(p_bAA), m_1bTC(p_bTC), m_1bRD(p_bRD), + m_1bRA(p_bRA), m_3bZ(0), m_4bRCode(p_ucRCode), + m_u16QDCount(p_u16QDCount), + m_u16ANCount(p_u16ANCount), + m_u16NSCount(p_u16NSCount), + m_u16ARCount(p_u16ARCount) +{ + +} + + +/** + MDNSResponder::stcMDNS_RRDomain + + A MDNS domain object. + The labels of the domain are stored (DNS-like encoded) in 'm_acName': + [length byte]varlength label[length byte]varlength label[0] + 'm_u16NameLength' stores the used length of 'm_acName'. + Dynamic label addition is supported. + Comparison is supported. + Export as byte array 'esp8266.local' is supported. + +*/ + +/* + MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain constructor +*/ +MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain(void) + : m_u16NameLength(0) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain copy-constructor +*/ +MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain(const stcMDNS_RRDomain& p_Other) + : m_u16NameLength(0) +{ + + operator=(p_Other); +} + +/* + MDNSResponder::stcMDNS_RRDomain::operator = +*/ +MDNSResponder::stcMDNS_RRDomain& MDNSResponder::stcMDNS_RRDomain::operator=(const stcMDNS_RRDomain& p_Other) +{ + + if (&p_Other != this) + { + memcpy(m_acName, p_Other.m_acName, sizeof(m_acName)); + m_u16NameLength = p_Other.m_u16NameLength; + } + return *this; +} + +/* + MDNSResponder::stcMDNS_RRDomain::clear +*/ +bool MDNSResponder::stcMDNS_RRDomain::clear(void) +{ + + memset(m_acName, 0, sizeof(m_acName)); + m_u16NameLength = 0; + return true; +} + +/* + MDNSResponder::stcMDNS_RRDomain::addLabel +*/ +bool MDNSResponder::stcMDNS_RRDomain::addLabel(const char* p_pcLabel, + bool p_bPrependUnderline /*= false*/) +{ + + bool bResult = false; + + size_t stLength = (p_pcLabel + ? (strlen(p_pcLabel) + (p_bPrependUnderline ? 1 : 0)) + : 0); + if ((MDNS_DOMAIN_LABEL_MAXLENGTH >= stLength) && + (MDNS_DOMAIN_MAXLENGTH >= (m_u16NameLength + (1 + stLength)))) + { + // Length byte + m_acName[m_u16NameLength] = (unsigned char)stLength; // Might be 0! + ++m_u16NameLength; + // Label + if (stLength) + { + if (p_bPrependUnderline) + { + m_acName[m_u16NameLength++] = '_'; + --stLength; + } + strncpy(&(m_acName[m_u16NameLength]), p_pcLabel, stLength); m_acName[m_u16NameLength + stLength] = 0; + m_u16NameLength += stLength; + } + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::stcMDNS_RRDomain::compare +*/ +bool MDNSResponder::stcMDNS_RRDomain::compare(const stcMDNS_RRDomain& p_Other) const +{ + + bool bResult = false; + + if (m_u16NameLength == p_Other.m_u16NameLength) + { + const char* pT = m_acName; + const char* pO = p_Other.m_acName; + while ((pT) && + (pO) && + (*((unsigned char*)pT) == *((unsigned char*)pO)) && // Same length AND + (0 == strncasecmp((pT + 1), (pO + 1), *((unsigned char*)pT)))) // Same content + { + if (*((unsigned char*)pT)) // Not 0 + { + pT += (1 + * ((unsigned char*)pT)); // Shift by length byte and lenght + pO += (1 + * ((unsigned char*)pO)); + } + else // Is 0 -> Successfully reached the end + { + bResult = true; + break; + } + } + } + return bResult; +} + +/* + MDNSResponder::stcMDNS_RRDomain::operator == +*/ +bool MDNSResponder::stcMDNS_RRDomain::operator==(const stcMDNS_RRDomain& p_Other) const +{ + + return compare(p_Other); +} + +/* + MDNSResponder::stcMDNS_RRDomain::operator != +*/ +bool MDNSResponder::stcMDNS_RRDomain::operator!=(const stcMDNS_RRDomain& p_Other) const +{ + + return !compare(p_Other); +} + +/* + MDNSResponder::stcMDNS_RRDomain::operator > +*/ +bool MDNSResponder::stcMDNS_RRDomain::operator>(const stcMDNS_RRDomain& p_Other) const +{ + + // TODO: Check, if this is a good idea... + return !compare(p_Other); +} + +/* + MDNSResponder::stcMDNS_RRDomain::c_strLength +*/ +size_t MDNSResponder::stcMDNS_RRDomain::c_strLength(void) const +{ + + size_t stLength = 0; + + unsigned char* pucLabelLength = (unsigned char*)m_acName; + while (*pucLabelLength) + { + stLength += (*pucLabelLength + 1 /* +1 for '.' or '\0'*/); + pucLabelLength += (*pucLabelLength + 1); + } + return stLength; +} + +/* + MDNSResponder::stcMDNS_RRDomain::c_str +*/ +bool MDNSResponder::stcMDNS_RRDomain::c_str(char* p_pcBuffer) +{ + + bool bResult = false; + + if (p_pcBuffer) + { + *p_pcBuffer = 0; + unsigned char* pucLabelLength = (unsigned char*)m_acName; + while (*pucLabelLength) + { + memcpy(p_pcBuffer, (const char*)(pucLabelLength + 1), *pucLabelLength); + p_pcBuffer += *pucLabelLength; + pucLabelLength += (*pucLabelLength + 1); + *p_pcBuffer++ = (*pucLabelLength ? '.' : '\0'); + } + bResult = true; + } + return bResult; +} + + +/** + MDNSResponder::stcMDNS_RRAttributes + + A MDNS attributes object. + +*/ + +/* + MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes constructor +*/ +MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes(uint16_t p_u16Type /*= 0*/, + uint16_t p_u16Class /*= 1 DNS_RRCLASS_IN Internet*/) + : m_u16Type(p_u16Type), + m_u16Class(p_u16Class) +{ + +} + +/* + MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes copy-constructor +*/ +MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes(const MDNSResponder::stcMDNS_RRAttributes& p_Other) +{ + + operator=(p_Other); +} + +/* + MDNSResponder::stcMDNS_RRAttributes::operator = +*/ +MDNSResponder::stcMDNS_RRAttributes& MDNSResponder::stcMDNS_RRAttributes::operator=(const MDNSResponder::stcMDNS_RRAttributes& p_Other) +{ + + if (&p_Other != this) + { + m_u16Type = p_Other.m_u16Type; + m_u16Class = p_Other.m_u16Class; + } + return *this; +} + + +/** + MDNSResponder::stcMDNS_RRHeader + + A MDNS record header (domain and attributes) object. + +*/ + +/* + MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader constructor +*/ +MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader(void) +{ + +} + +/* + MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader copy-constructor +*/ +MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader(const stcMDNS_RRHeader& p_Other) +{ + + operator=(p_Other); +} + +/* + MDNSResponder::stcMDNS_RRHeader::operator = +*/ +MDNSResponder::stcMDNS_RRHeader& MDNSResponder::stcMDNS_RRHeader::operator=(const MDNSResponder::stcMDNS_RRHeader& p_Other) +{ + + if (&p_Other != this) + { + m_Domain = p_Other.m_Domain; + m_Attributes = p_Other.m_Attributes; + } + return *this; +} + +/* + MDNSResponder::stcMDNS_RRHeader::clear +*/ +bool MDNSResponder::stcMDNS_RRHeader::clear(void) +{ + + m_Domain.clear(); + return true; +} + + +/** + MDNSResponder::stcMDNS_RRQuestion + + A MDNS question record object (header + question flags) + +*/ + +/* + MDNSResponder::stcMDNS_RRQuestion::stcMDNS_RRQuestion constructor +*/ +MDNSResponder::stcMDNS_RRQuestion::stcMDNS_RRQuestion(void) + : m_pNext(0), + m_bUnicast(false) +{ + +} + + +/** + MDNSResponder::stcMDNS_RRAnswer + + A MDNS answer record object (header + answer content). + This is a 'virtual' base class for all other MDNS answer classes. + +*/ + +/* + MDNSResponder::stcMDNS_RRAnswer::stcMDNS_RRAnswer constructor +*/ +MDNSResponder::stcMDNS_RRAnswer::stcMDNS_RRAnswer(enuAnswerType p_AnswerType, + const MDNSResponder::stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL) + : m_pNext(0), + m_AnswerType(p_AnswerType), + m_Header(p_Header), + m_u32TTL(p_u32TTL) +{ + + // Extract 'cache flush'-bit + m_bCacheFlush = (m_Header.m_Attributes.m_u16Class & 0x8000); + m_Header.m_Attributes.m_u16Class &= (~0x8000); +} + +/* + MDNSResponder::stcMDNS_RRAnswer::~stcMDNS_RRAnswer destructor +*/ +MDNSResponder::stcMDNS_RRAnswer::~stcMDNS_RRAnswer(void) +{ + +} + +/* + MDNSResponder::stcMDNS_RRAnswer::answerType +*/ +MDNSResponder::enuAnswerType MDNSResponder::stcMDNS_RRAnswer::answerType(void) const +{ + + return m_AnswerType; +} + +/* + MDNSResponder::stcMDNS_RRAnswer::clear +*/ +bool MDNSResponder::stcMDNS_RRAnswer::clear(void) +{ + + m_pNext = 0; + m_Header.clear(); + return true; +} + + +/** + MDNSResponder::stcMDNS_RRAnswerA + + A MDNS A answer object. + Extends the base class by an IP4 address member. + +*/ + +#ifdef MDNS_IP4_SUPPORT +/* + MDNSResponder::stcMDNS_RRAnswerA::stcMDNS_RRAnswerA constructor +*/ +MDNSResponder::stcMDNS_RRAnswerA::stcMDNS_RRAnswerA(const MDNSResponder::stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL) + : stcMDNS_RRAnswer(AnswerType_A, p_Header, p_u32TTL), + m_IPAddress(0, 0, 0, 0) +{ + +} + +/* + MDNSResponder::stcMDNS_RRAnswerA::stcMDNS_RRAnswerA destructor +*/ +MDNSResponder::stcMDNS_RRAnswerA::~stcMDNS_RRAnswerA(void) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNS_RRAnswerA::clear +*/ +bool MDNSResponder::stcMDNS_RRAnswerA::clear(void) +{ + + m_IPAddress = IPAddress(0, 0, 0, 0); + return true; +} +#endif + + +/** + MDNSResponder::stcMDNS_RRAnswerPTR + + A MDNS PTR answer object. + Extends the base class by a MDNS domain member. + +*/ + +/* + MDNSResponder::stcMDNS_RRAnswerPTR::stcMDNS_RRAnswerPTR constructor +*/ +MDNSResponder::stcMDNS_RRAnswerPTR::stcMDNS_RRAnswerPTR(const MDNSResponder::stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL) + : stcMDNS_RRAnswer(AnswerType_PTR, p_Header, p_u32TTL) +{ + +} + +/* + MDNSResponder::stcMDNS_RRAnswerPTR::~stcMDNS_RRAnswerPTR destructor +*/ +MDNSResponder::stcMDNS_RRAnswerPTR::~stcMDNS_RRAnswerPTR(void) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNS_RRAnswerPTR::clear +*/ +bool MDNSResponder::stcMDNS_RRAnswerPTR::clear(void) +{ + + m_PTRDomain.clear(); + return true; +} + + +/** + MDNSResponder::stcMDNS_RRAnswerTXT + + A MDNS TXT answer object. + Extends the base class by a MDNS TXT items list member. + +*/ + +/* + MDNSResponder::stcMDNS_RRAnswerTXT::stcMDNS_RRAnswerTXT constructor +*/ +MDNSResponder::stcMDNS_RRAnswerTXT::stcMDNS_RRAnswerTXT(const MDNSResponder::stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL) + : stcMDNS_RRAnswer(AnswerType_TXT, p_Header, p_u32TTL) +{ + +} + +/* + MDNSResponder::stcMDNS_RRAnswerTXT::~stcMDNS_RRAnswerTXT destructor +*/ +MDNSResponder::stcMDNS_RRAnswerTXT::~stcMDNS_RRAnswerTXT(void) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNS_RRAnswerTXT::clear +*/ +bool MDNSResponder::stcMDNS_RRAnswerTXT::clear(void) +{ + + m_Txts.clear(); + return true; +} + + +/** + MDNSResponder::stcMDNS_RRAnswerAAAA + + A MDNS AAAA answer object. + (Should) extend the base class by an IP6 address member. + +*/ + +#ifdef MDNS_IP6_SUPPORT +/* + MDNSResponder::stcMDNS_RRAnswerAAAA::stcMDNS_RRAnswerAAAA constructor +*/ +MDNSResponder::stcMDNS_RRAnswerAAAA::stcMDNS_RRAnswerAAAA(const MDNSResponder::stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL) + : stcMDNS_RRAnswer(AnswerType_AAAA, p_Header, p_u32TTL) +{ + +} + +/* + MDNSResponder::stcMDNS_RRAnswerAAAA::~stcMDNS_RRAnswerAAAA destructor +*/ +MDNSResponder::stcMDNS_RRAnswerAAAA::~stcMDNS_RRAnswerAAAA(void) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNS_RRAnswerAAAA::clear +*/ +bool MDNSResponder::stcMDNS_RRAnswerAAAA::clear(void) +{ + + return true; +} +#endif + + +/** + MDNSResponder::stcMDNS_RRAnswerSRV + + A MDNS SRV answer object. + Extends the base class by a port member. + +*/ + +/* + MDNSResponder::stcMDNS_RRAnswerSRV::stcMDNS_RRAnswerSRV constructor +*/ +MDNSResponder::stcMDNS_RRAnswerSRV::stcMDNS_RRAnswerSRV(const MDNSResponder::stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL) + : stcMDNS_RRAnswer(AnswerType_SRV, p_Header, p_u32TTL), + m_u16Priority(0), + m_u16Weight(0), + m_u16Port(0) +{ + +} + +/* + MDNSResponder::stcMDNS_RRAnswerSRV::~stcMDNS_RRAnswerSRV destructor +*/ +MDNSResponder::stcMDNS_RRAnswerSRV::~stcMDNS_RRAnswerSRV(void) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNS_RRAnswerSRV::clear +*/ +bool MDNSResponder::stcMDNS_RRAnswerSRV::clear(void) +{ + + m_u16Priority = 0; + m_u16Weight = 0; + m_u16Port = 0; + m_SRVDomain.clear(); + return true; +} + + +/** + MDNSResponder::stcMDNS_RRAnswerGeneric + + An unknown (generic) MDNS answer object. + Extends the base class by a RDATA buffer member. + +*/ + +/* + MDNSResponder::stcMDNS_RRAnswerGeneric::stcMDNS_RRAnswerGeneric constructor +*/ +MDNSResponder::stcMDNS_RRAnswerGeneric::stcMDNS_RRAnswerGeneric(const stcMDNS_RRHeader& p_Header, + uint32_t p_u32TTL) + : stcMDNS_RRAnswer(AnswerType_Generic, p_Header, p_u32TTL), + m_u16RDLength(0), + m_pu8RDData(0) +{ + +} + +/* + MDNSResponder::stcMDNS_RRAnswerGeneric::~stcMDNS_RRAnswerGeneric destructor +*/ +MDNSResponder::stcMDNS_RRAnswerGeneric::~stcMDNS_RRAnswerGeneric(void) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNS_RRAnswerGeneric::clear +*/ +bool MDNSResponder::stcMDNS_RRAnswerGeneric::clear(void) +{ + + if (m_pu8RDData) + { + delete[] m_pu8RDData; + m_pu8RDData = 0; + } + m_u16RDLength = 0; + + return true; +} + + +/** + MDNSResponder::stcProbeInformation + + Probing status information for a host or service domain + +*/ + +/* + MDNSResponder::stcProbeInformation::stcProbeInformation constructor +*/ +MDNSResponder::stcProbeInformation::stcProbeInformation(void) + : m_ProbingStatus(ProbingStatus_WaitingForData), + m_u8SentCount(0), + m_Timeout(esp8266::polledTimeout::oneShotMs::neverExpires), + m_bConflict(false), + m_bTiebreakNeeded(false), + m_fnHostProbeResultCallback(0), + m_fnServiceProbeResultCallback(0) +{ +} + +/* + MDNSResponder::stcProbeInformation::clear +*/ +bool MDNSResponder::stcProbeInformation::clear(bool p_bClearUserdata /*= false*/) +{ + + m_ProbingStatus = ProbingStatus_WaitingForData; + m_u8SentCount = 0; + m_Timeout.resetToNeverExpires(); + m_bConflict = false; + m_bTiebreakNeeded = false; + if (p_bClearUserdata) + { + m_fnHostProbeResultCallback = 0; + m_fnServiceProbeResultCallback = 0; + } + return true; +} + +/** + MDNSResponder::stcMDNSService + + A MDNS service object (to be announced by the MDNS responder) + The service instance may be '\0'; in this case the hostname is used + and the flag m_bAutoName is set. If the hostname changes, all 'auto- + named' services are renamed also. + m_u8Replymask is used while preparing a response to a MDNS query. It is + resetted in '_sendMDNSMessage' afterwards. +*/ + +/* + MDNSResponder::stcMDNSService::stcMDNSService constructor +*/ +MDNSResponder::stcMDNSService::stcMDNSService(const char* p_pcName /*= 0*/, + const char* p_pcService /*= 0*/, + const char* p_pcProtocol /*= 0*/) + : m_pNext(0), + m_pcName(0), + m_bAutoName(false), + m_pcService(0), + m_pcProtocol(0), + m_u16Port(0), + m_u8ReplyMask(0), + m_fnTxtCallback(0) +{ + + setName(p_pcName); + setService(p_pcService); + setProtocol(p_pcProtocol); +} + +/* + MDNSResponder::stcMDNSService::~stcMDNSService destructor +*/ +MDNSResponder::stcMDNSService::~stcMDNSService(void) +{ + + releaseName(); + releaseService(); + releaseProtocol(); +} + +/* + MDNSResponder::stcMDNSService::setName +*/ +bool MDNSResponder::stcMDNSService::setName(const char* p_pcName) +{ + + bool bResult = false; + + releaseName(); + size_t stLength = (p_pcName ? strlen(p_pcName) : 0); + if (stLength) + { + if ((bResult = (0 != (m_pcName = new char[stLength + 1])))) + { + strncpy(m_pcName, p_pcName, stLength); + m_pcName[stLength] = 0; + } + } + else + { + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::stcMDNSService::releaseName +*/ +bool MDNSResponder::stcMDNSService::releaseName(void) +{ + + if (m_pcName) + { + delete[] m_pcName; + m_pcName = 0; + } + return true; +} + +/* + MDNSResponder::stcMDNSService::setService +*/ +bool MDNSResponder::stcMDNSService::setService(const char* p_pcService) +{ + + bool bResult = false; + + releaseService(); + size_t stLength = (p_pcService ? strlen(p_pcService) : 0); + if (stLength) + { + if ((bResult = (0 != (m_pcService = new char[stLength + 1])))) + { + strncpy(m_pcService, p_pcService, stLength); + m_pcService[stLength] = 0; + } + } + else + { + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::stcMDNSService::releaseService +*/ +bool MDNSResponder::stcMDNSService::releaseService(void) +{ + + if (m_pcService) + { + delete[] m_pcService; + m_pcService = 0; + } + return true; +} + +/* + MDNSResponder::stcMDNSService::setProtocol +*/ +bool MDNSResponder::stcMDNSService::setProtocol(const char* p_pcProtocol) +{ + + bool bResult = false; + + releaseProtocol(); + size_t stLength = (p_pcProtocol ? strlen(p_pcProtocol) : 0); + if (stLength) + { + if ((bResult = (0 != (m_pcProtocol = new char[stLength + 1])))) + { + strncpy(m_pcProtocol, p_pcProtocol, stLength); + m_pcProtocol[stLength] = 0; + } + } + else + { + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::stcMDNSService::releaseProtocol +*/ +bool MDNSResponder::stcMDNSService::releaseProtocol(void) +{ + + if (m_pcProtocol) + { + delete[] m_pcProtocol; + m_pcProtocol = 0; + } + return true; +} + + +/** + MDNSResponder::stcMDNSServiceQuery + + A MDNS service query object. + Service queries may be static or dynamic. + As the static service query is processed in the blocking function 'queryService', + only one static service service may exist. The processing of the answers is done + on the WiFi-stack side of the ESP stack structure (via 'UDPContext.onRx(_update)'). + +*/ + +/** + MDNSResponder::stcMDNSServiceQuery::stcAnswer + + One answer for a service query. + Every answer must contain + - a service instance entry (pivot), + and may contain + - a host domain, + - a port + - an IP4 address + (- an IP6 address) + - a MDNS TXTs + The existance of a component is flaged in 'm_u32ContentFlags'. + For every answer component a TTL value is maintained. + Answer objects can be connected to a linked list. + + For the host domain, service domain and TXTs components, a char array + representation can be retrieved (which is created on demand). + +*/ + +/** + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL + + The TTL (Time-To-Live) for an specific answer content. + The 80% and outdated states are calculated based on the current time (millis) + and the 'set' time (also millis). + If the answer is scheduled for an update, the corresponding flag should be set. + + / + + / * + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL constructor + / + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL(uint32_t p_u32TTL / *= 0* /) + : m_bUpdateScheduled(false) { + + set(p_u32TTL * 1000); + } + + / * + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set + / + bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set(uint32_t p_u32TTL) { + + m_TTLTimeFlag.restart(p_u32TTL * 1000); + m_bUpdateScheduled = false; + + return true; + } + + / * + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::has80Percent + / + bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::has80Percent(void) const { + + return ((m_TTLTimeFlag.getTimeout()) && + (!m_bUpdateScheduled) && + (m_TTLTimeFlag.hypotheticalTimeout((m_TTLTimeFlag.getTimeout() * 800) / 1000))); + } + + / * + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::isOutdated + / + bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::isOutdated(void) const { + + return ((m_TTLTimeFlag.getTimeout()) && + (m_TTLTimeFlag.flagged())); + }*/ + + +/** + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL + + The TTL (Time-To-Live) for an specific answer content. + The 80% and outdated states are calculated based on the current time (millis) + and the 'set' time (also millis). + If the answer is scheduled for an update, the corresponding flag should be set. + +*/ + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL constructor +*/ +MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL(void) + : m_u32TTL(0), + m_TTLTimeout(esp8266::polledTimeout::oneShotMs::neverExpires), + m_timeoutLevel(TIMEOUTLEVEL_UNSET) +{ + +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set(uint32_t p_u32TTL) +{ + + m_u32TTL = p_u32TTL; + if (m_u32TTL) + { + m_timeoutLevel = TIMEOUTLEVEL_BASE; // Set to 80% + m_TTLTimeout.reset(timeout()); + } + else + { + m_timeoutLevel = TIMEOUTLEVEL_UNSET; // undef + m_TTLTimeout.resetToNeverExpires(); + } + return true; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged(void) +{ + + return ((m_u32TTL) && + (TIMEOUTLEVEL_UNSET != m_timeoutLevel) && + (m_TTLTimeout.expired())); +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::restart +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::restart(void) +{ + + bool bResult = true; + + if ((TIMEOUTLEVEL_BASE <= m_timeoutLevel) && // >= 80% AND + (TIMEOUTLEVEL_FINAL > m_timeoutLevel)) // < 100% + { + + m_timeoutLevel += TIMEOUTLEVEL_INTERVAL; // increment by 5% + m_TTLTimeout.reset(timeout()); + } + else + { + bResult = false; + m_TTLTimeout.resetToNeverExpires(); + m_timeoutLevel = TIMEOUTLEVEL_UNSET; + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::prepareDeletion +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::prepareDeletion(void) +{ + + m_timeoutLevel = TIMEOUTLEVEL_FINAL; + m_TTLTimeout.reset(1 * 1000); // See RFC 6762, 10.1 + + return true; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::finalTimeoutLevel +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::finalTimeoutLevel(void) const +{ + + return (TIMEOUTLEVEL_FINAL == m_timeoutLevel); +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::timeout +*/ +unsigned long MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::timeout(void) const +{ + + uint32_t u32Timeout = esp8266::polledTimeout::oneShotMs::neverExpires; + + if (TIMEOUTLEVEL_BASE == m_timeoutLevel) // 80% + { + u32Timeout = (m_u32TTL * 800); // to milliseconds + } + else if ((TIMEOUTLEVEL_BASE < m_timeoutLevel) && // >80% AND + (TIMEOUTLEVEL_FINAL >= m_timeoutLevel)) // <= 100% + { + + u32Timeout = (m_u32TTL * 50); + } // else: invalid + return u32Timeout; +} + + +#ifdef MDNS_IP4_SUPPORT +/** + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address + +*/ + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address::stcIP4Address constructor +*/ +MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address::stcIP4Address(IPAddress p_IPAddress, + uint32_t p_u32TTL /*= 0*/) + : m_pNext(0), + m_IPAddress(p_IPAddress) +{ + + m_TTL.set(p_u32TTL); +} +#endif + + +/** + MDNSResponder::stcMDNSServiceQuery::stcAnswer +*/ + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcAnswer constructor +*/ +MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcAnswer(void) + : m_pNext(0), + m_pcServiceDomain(0), + m_pcHostDomain(0), + m_u16Port(0), + m_pcTxts(0), +#ifdef MDNS_IP4_SUPPORT + m_pIP4Addresses(0), +#endif +#ifdef MDNS_IP6_SUPPORT + m_pIP6Addresses(0), +#endif + m_u32ContentFlags(0) +{ +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::~stcAnswer destructor +*/ +MDNSResponder::stcMDNSServiceQuery::stcAnswer::~stcAnswer(void) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::clear +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::clear(void) +{ + + return ((releaseTxts()) && +#ifdef MDNS_IP4_SUPPORT + (releaseIP4Addresses()) && +#endif +#ifdef MDNS_IP6_SUPPORT + (releaseIP6Addresses()) +#endif + (releaseHostDomain()) && + (releaseServiceDomain())); +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocServiceDomain + + Alloc memory for the char array representation of the service domain. + +*/ +char* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocServiceDomain(size_t p_stLength) +{ + + releaseServiceDomain(); + if (p_stLength) + { + m_pcServiceDomain = new char[p_stLength]; + } + return m_pcServiceDomain; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseServiceDomain +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseServiceDomain(void) +{ + + if (m_pcServiceDomain) + { + delete[] m_pcServiceDomain; + m_pcServiceDomain = 0; + } + return true; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocHostDomain + + Alloc memory for the char array representation of the host domain. + +*/ +char* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocHostDomain(size_t p_stLength) +{ + + releaseHostDomain(); + if (p_stLength) + { + m_pcHostDomain = new char[p_stLength]; + } + return m_pcHostDomain; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseHostDomain +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseHostDomain(void) +{ + + if (m_pcHostDomain) + { + delete[] m_pcHostDomain; + m_pcHostDomain = 0; + } + return true; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocTxts + + Alloc memory for the char array representation of the TXT items. + +*/ +char* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocTxts(size_t p_stLength) +{ + + releaseTxts(); + if (p_stLength) + { + m_pcTxts = new char[p_stLength]; + } + return m_pcTxts; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseTxts +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseTxts(void) +{ + + if (m_pcTxts) + { + delete[] m_pcTxts; + m_pcTxts = 0; + } + return true; +} + +#ifdef MDNS_IP4_SUPPORT +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP4Addresses +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP4Addresses(void) +{ + + while (m_pIP4Addresses) + { + stcIP4Address* pNext = m_pIP4Addresses->m_pNext; + delete m_pIP4Addresses; + m_pIP4Addresses = pNext; + } + return true; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP4Address +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP4Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* p_pIP4Address) +{ + + bool bResult = false; + + if (p_pIP4Address) + { + p_pIP4Address->m_pNext = m_pIP4Addresses; + m_pIP4Addresses = p_pIP4Address; + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP4Address +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP4Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* p_pIP4Address) +{ + + bool bResult = false; + + if (p_pIP4Address) + { + stcIP4Address* pPred = m_pIP4Addresses; + while ((pPred) && + (pPred->m_pNext != p_pIP4Address)) + { + pPred = pPred->m_pNext; + } + if (pPred) + { + pPred->m_pNext = p_pIP4Address->m_pNext; + delete p_pIP4Address; + bResult = true; + } + else if (m_pIP4Addresses == p_pIP4Address) // No predecesor, but first item + { + m_pIP4Addresses = p_pIP4Address->m_pNext; + delete p_pIP4Address; + bResult = true; + } + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address (const) +*/ +const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address(const IPAddress& p_IPAddress) const +{ + + return (stcIP4Address*)(((const stcAnswer*)this)->findIP4Address(p_IPAddress)); +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address +*/ +MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address(const IPAddress& p_IPAddress) +{ + + stcIP4Address* pIP4Address = m_pIP4Addresses; + while (pIP4Address) + { + if (pIP4Address->m_IPAddress == p_IPAddress) + { + break; + } + pIP4Address = pIP4Address->m_pNext; + } + return pIP4Address; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressCount +*/ +uint32_t MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressCount(void) const +{ + + uint32_t u32Count = 0; + + stcIP4Address* pIP4Address = m_pIP4Addresses; + while (pIP4Address) + { + ++u32Count; + pIP4Address = pIP4Address->m_pNext; + } + return u32Count; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex +*/ +MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex(uint32_t p_u32Index) +{ + + return (stcIP4Address*)(((const stcAnswer*)this)->IP4AddressAtIndex(p_u32Index)); +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex (const) +*/ +const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex(uint32_t p_u32Index) const +{ + + const stcIP4Address* pIP4Address = 0; + + if (((uint32_t)(-1) != p_u32Index) && + (m_pIP4Addresses)) + { + + uint32_t u32Index; + for (pIP4Address = m_pIP4Addresses, u32Index = 0; ((pIP4Address) && (u32Index < p_u32Index)); pIP4Address = pIP4Address->m_pNext, ++u32Index); + } + return pIP4Address; +} +#endif + +#ifdef MDNS_IP6_SUPPORT +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP6Addresses +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP6Addresses(void) +{ + + while (m_pIP6Addresses) + { + stcIP6Address* pNext = m_pIP6Addresses->m_pNext; + delete m_pIP6Addresses; + m_pIP6Addresses = pNext; + } + return true; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP6Address +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP6Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* p_pIP6Address) +{ + + bool bResult = false; + + if (p_pIP6Address) + { + p_pIP6Address->m_pNext = m_pIP6Addresses; + m_pIP6Addresses = p_pIP6Address; + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP6Address +*/ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP6Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* p_pIP6Address) +{ + + bool bResult = false; + + if (p_pIP6Address) + { + stcIP6Address* pPred = m_pIP6Addresses; + while ((pPred) && + (pPred->m_pNext != p_pIP6Address)) + { + pPred = pPred->m_pNext; + } + if (pPred) + { + pPred->m_pNext = p_pIP6Address->m_pNext; + delete p_pIP6Address; + bResult = true; + } + else if (m_pIP6Addresses == p_pIP6Address) // No predecesor, but first item + { + m_pIP6Addresses = p_pIP6Address->m_pNext; + delete p_pIP6Address; + bResult = true; + } + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address +*/ +MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address(const IP6Address& p_IPAddress) +{ + + return (stcIP6Address*)(((const stcAnswer*)this)->findIP6Address(p_IPAddress)); +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address (const) +*/ +const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address(const IPAddress& p_IPAddress) const +{ + + const stcIP6Address* pIP6Address = m_pIP6Addresses; + while (pIP6Address) + { + if (p_IP6Address->m_IPAddress == p_IPAddress) + { + break; + } + pIP6Address = pIP6Address->m_pNext; + } + return pIP6Address; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressCount +*/ +uint32_t MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressCount(void) const +{ + + uint32_t u32Count = 0; + + stcIP6Address* pIP6Address = m_pIP6Addresses; + while (pIP6Address) + { + ++u32Count; + pIP6Address = pIP6Address->m_pNext; + } + return u32Count; +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex (const) +*/ +const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex(uint32_t p_u32Index) const +{ + + return (stcIP6Address*)(((const stcAnswer*)this)->IP6AddressAtIndex(p_u32Index)); +} + +/* + MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex +*/ +MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex(uint32_t p_u32Index) +{ + + stcIP6Address* pIP6Address = 0; + + if (((uint32_t)(-1) != p_u32Index) && + (m_pIP6Addresses)) + { + + uint32_t u32Index; + for (pIP6Address = m_pIP6Addresses, u32Index = 0; ((pIP6Address) && (u32Index < p_u32Index)); pIP6Address = pIP6Address->m_pNext, ++u32Index); + } + return pIP6Address; +} +#endif + + +/** + MDNSResponder::stcMDNSServiceQuery + + A service query object. + A static query is flaged via 'm_bLegacyQuery'; while the function 'queryService' + is waiting for answers, the internal flag 'm_bAwaitingAnswers' is set. When the + timeout is reached, the flag is removed. These two flags are only used for static + service queries. + All answers to the service query are stored in 'm_pAnswers' list. + Individual answers may be addressed by index (in the list of answers). + Every time a answer component is added (or changes) in a dynamic service query, + the callback 'm_fnCallback' is called. + The answer list may be searched by service and host domain. + + Service query object may be connected to a linked list. +*/ + +/* + MDNSResponder::stcMDNSServiceQuery::stcMDNSServiceQuery constructor +*/ +MDNSResponder::stcMDNSServiceQuery::stcMDNSServiceQuery(void) + : m_pNext(0), + m_fnCallback(0), + m_bLegacyQuery(false), + m_u8SentCount(0), + m_ResendTimeout(esp8266::polledTimeout::oneShotMs::neverExpires), + m_bAwaitingAnswers(true), + m_pAnswers(0) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNSServiceQuery::~stcMDNSServiceQuery destructor +*/ +MDNSResponder::stcMDNSServiceQuery::~stcMDNSServiceQuery(void) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNSServiceQuery::clear +*/ +bool MDNSResponder::stcMDNSServiceQuery::clear(void) +{ + + m_fnCallback = 0; + m_bLegacyQuery = false; + m_u8SentCount = 0; + m_ResendTimeout.resetToNeverExpires(); + m_bAwaitingAnswers = true; + while (m_pAnswers) + { + stcAnswer* pNext = m_pAnswers->m_pNext; + delete m_pAnswers; + m_pAnswers = pNext; + } + return true; +} + +/* + MDNSResponder::stcMDNSServiceQuery::answerCount +*/ +uint32_t MDNSResponder::stcMDNSServiceQuery::answerCount(void) const +{ + + uint32_t u32Count = 0; + + stcAnswer* pAnswer = m_pAnswers; + while (pAnswer) + { + ++u32Count; + pAnswer = pAnswer->m_pNext; + } + return u32Count; +} + +/* + MDNSResponder::stcMDNSServiceQuery::answerAtIndex +*/ +const MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::answerAtIndex(uint32_t p_u32Index) const +{ + + const stcAnswer* pAnswer = 0; + + if (((uint32_t)(-1) != p_u32Index) && + (m_pAnswers)) + { + + uint32_t u32Index; + for (pAnswer = m_pAnswers, u32Index = 0; ((pAnswer) && (u32Index < p_u32Index)); pAnswer = pAnswer->m_pNext, ++u32Index); + } + return pAnswer; +} + +/* + MDNSResponder::stcMDNSServiceQuery::answerAtIndex +*/ +MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::answerAtIndex(uint32_t p_u32Index) +{ + + return (stcAnswer*)(((const stcMDNSServiceQuery*)this)->answerAtIndex(p_u32Index)); +} + +/* + MDNSResponder::stcMDNSServiceQuery::indexOfAnswer +*/ +uint32_t MDNSResponder::stcMDNSServiceQuery::indexOfAnswer(const MDNSResponder::stcMDNSServiceQuery::stcAnswer* p_pAnswer) const +{ + + uint32_t u32Index = 0; + + for (const stcAnswer* pAnswer = m_pAnswers; pAnswer; pAnswer = pAnswer->m_pNext, ++u32Index) + { + if (pAnswer == p_pAnswer) + { + return u32Index; + } + } + return ((uint32_t)(-1)); +} + +/* + MDNSResponder::stcMDNSServiceQuery::addAnswer +*/ +bool MDNSResponder::stcMDNSServiceQuery::addAnswer(MDNSResponder::stcMDNSServiceQuery::stcAnswer* p_pAnswer) +{ + + bool bResult = false; + + if (p_pAnswer) + { + p_pAnswer->m_pNext = m_pAnswers; + m_pAnswers = p_pAnswer; + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceQuery::removeAnswer +*/ +bool MDNSResponder::stcMDNSServiceQuery::removeAnswer(MDNSResponder::stcMDNSServiceQuery::stcAnswer* p_pAnswer) +{ + + bool bResult = false; + + if (p_pAnswer) + { + stcAnswer* pPred = m_pAnswers; + while ((pPred) && + (pPred->m_pNext != p_pAnswer)) + { + pPred = pPred->m_pNext; + } + if (pPred) + { + pPred->m_pNext = p_pAnswer->m_pNext; + delete p_pAnswer; + bResult = true; + } + else if (m_pAnswers == p_pAnswer) // No predecesor, but first item + { + m_pAnswers = p_pAnswer->m_pNext; + delete p_pAnswer; + bResult = true; + } + } + return bResult; +} + +/* + MDNSResponder::stcMDNSServiceQuery::findAnswerForServiceDomain +*/ +MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::findAnswerForServiceDomain(const MDNSResponder::stcMDNS_RRDomain& p_ServiceDomain) +{ + + stcAnswer* pAnswer = m_pAnswers; + while (pAnswer) + { + if (pAnswer->m_ServiceDomain == p_ServiceDomain) + { + break; + } + pAnswer = pAnswer->m_pNext; + } + return pAnswer; +} + +/* + MDNSResponder::stcMDNSServiceQuery::findAnswerForHostDomain +*/ +MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::findAnswerForHostDomain(const MDNSResponder::stcMDNS_RRDomain& p_HostDomain) +{ + + stcAnswer* pAnswer = m_pAnswers; + while (pAnswer) + { + if (pAnswer->m_HostDomain == p_HostDomain) + { + break; + } + pAnswer = pAnswer->m_pNext; + } + return pAnswer; +} + + +/** + MDNSResponder::stcMDNSSendParameter + + A 'collection' of properties and flags for one MDNS query or response. + Mainly managed by the 'Control' functions. + The current offset in the UPD output buffer is tracked to be able to do + a simple host or service domain compression. + +*/ + +/** + MDNSResponder::stcMDNSSendParameter::stcDomainCacheItem + + A cached host or service domain, incl. the offset in the UDP output buffer. + +*/ + +/* + MDNSResponder::stcMDNSSendParameter::stcDomainCacheItem::stcDomainCacheItem constructor +*/ +MDNSResponder::stcMDNSSendParameter::stcDomainCacheItem::stcDomainCacheItem(const void* p_pHostnameOrService, + bool p_bAdditionalData, + uint32_t p_u16Offset) + : m_pNext(0), + m_pHostnameOrService(p_pHostnameOrService), + m_bAdditionalData(p_bAdditionalData), + m_u16Offset(p_u16Offset) +{ + +} + +/** + MDNSResponder::stcMDNSSendParameter +*/ + +/* + MDNSResponder::stcMDNSSendParameter::stcMDNSSendParameter constructor +*/ +MDNSResponder::stcMDNSSendParameter::stcMDNSSendParameter(void) + : m_pQuestions(0), + m_pDomainCacheItems(0) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNSSendParameter::~stcMDNSSendParameter destructor +*/ +MDNSResponder::stcMDNSSendParameter::~stcMDNSSendParameter(void) +{ + + clear(); +} + +/* + MDNSResponder::stcMDNSSendParameter::clear +*/ +bool MDNSResponder::stcMDNSSendParameter::clear(void) +{ + + m_u16ID = 0; + m_u8HostReplyMask = 0; + m_u16Offset = 0; + + m_bLegacyQuery = false; + m_bResponse = false; + m_bAuthorative = false; + m_bUnicast = false; + m_bUnannounce = false; + + m_bCacheFlush = true; + + while (m_pQuestions) + { + stcMDNS_RRQuestion* pNext = m_pQuestions->m_pNext; + delete m_pQuestions; + m_pQuestions = pNext; + } + while (m_pDomainCacheItems) + { + stcDomainCacheItem* pNext = m_pDomainCacheItems->m_pNext; + delete m_pDomainCacheItems; + m_pDomainCacheItems = pNext; + } + return true; +} + +/* + MDNSResponder::stcMDNSSendParameter::shiftOffset +*/ +bool MDNSResponder::stcMDNSSendParameter::shiftOffset(uint16_t p_u16Shift) +{ + + m_u16Offset += p_u16Shift; + return true; +} + +/* + MDNSResponder::stcMDNSSendParameter::addDomainCacheItem +*/ +bool MDNSResponder::stcMDNSSendParameter::addDomainCacheItem(const void* p_pHostnameOrService, + bool p_bAdditionalData, + uint16_t p_u16Offset) +{ + + bool bResult = false; + + stcDomainCacheItem* pNewItem = 0; + if ((p_pHostnameOrService) && + (p_u16Offset) && + ((pNewItem = new stcDomainCacheItem(p_pHostnameOrService, p_bAdditionalData, p_u16Offset)))) + { + + pNewItem->m_pNext = m_pDomainCacheItems; + bResult = ((m_pDomainCacheItems = pNewItem)); + } + return bResult; +} + +/* + MDNSResponder::stcMDNSSendParameter::findCachedDomainOffset +*/ +uint16_t MDNSResponder::stcMDNSSendParameter::findCachedDomainOffset(const void* p_pHostnameOrService, + bool p_bAdditionalData) const +{ + + const stcDomainCacheItem* pCacheItem = m_pDomainCacheItems; + + for (; pCacheItem; pCacheItem = pCacheItem->m_pNext) + { + if ((pCacheItem->m_pHostnameOrService == p_pHostnameOrService) && + (pCacheItem->m_bAdditionalData == p_bAdditionalData)) // Found cache item + { + break; + } + } + return (pCacheItem ? pCacheItem->m_u16Offset : 0); +} + +} // namespace MDNSImplementation + +} // namespace esp8266 + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp new file mode 100644 index 0000000000..c5858690a5 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp @@ -0,0 +1,1780 @@ +/* + LEAmDNS_Transfer.cpp + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +extern "C" { +#include "user_interface.h" +} + +#include "ESP8266mDNS.h" +#include "LEAmDNS_lwIPdefs.h" +#include "LEAmDNS_Priv.h" + + +namespace esp8266 +{ + +/* + LEAmDNS +*/ +namespace MDNSImplementation +{ + +/** + CONST STRINGS +*/ +static const char* scpcLocal = "local"; +static const char* scpcServices = "services"; +static const char* scpcDNSSD = "dns-sd"; +static const char* scpcUDP = "udp"; +//static const char* scpcTCP = "tcp"; + +#ifdef MDNS_IP4_SUPPORT +static const char* scpcReverseIP4Domain = "in-addr"; +#endif +#ifdef MDNS_IP6_SUPPORT +static const char* scpcReverseIP6Domain = "ip6"; +#endif +static const char* scpcReverseTopDomain = "arpa"; + +/** + TRANSFER +*/ + + +/** + SENDING +*/ + +/* + MDNSResponder::_sendMDNSMessage + + Unicast responses are prepared and sent directly to the querier. + Multicast responses or queries are transferred to _sendMDNSMessage_Multicast + + Any reply flags in installed services are removed at the end! + +*/ +bool MDNSResponder::_sendMDNSMessage(MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + + bool bResult = true; + + if (p_rSendParameter.m_bResponse && + p_rSendParameter.m_bUnicast) // Unicast response -> Send to querier + { + DEBUG_EX_ERR(if (!m_pUDPContext->getRemoteAddress()) + { + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage: MISSING remote address for response!\n")); + }); + IPAddress ipRemote; + ipRemote = m_pUDPContext->getRemoteAddress(); + bResult = ((_prepareMDNSMessage(p_rSendParameter, _getResponseMulticastInterface())) && + (m_pUDPContext->send(ipRemote, m_pUDPContext->getRemotePort()))); + } + else // Multicast response + { + bResult = _sendMDNSMessage_Multicast(p_rSendParameter); + } + + // Finally clear service reply masks + for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) + { + pService->m_u8ReplyMask = 0; + } + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_sendMDNSMessage_Multicast + + Fills the UDP output buffer (via _prepareMDNSMessage) and sends the buffer + via the selected WiFi interface (Station or AP) +*/ +bool MDNSResponder::_sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + + bool bResult = false; + + IPAddress fromIPAddress; + fromIPAddress = _getResponseMulticastInterface(); + m_pUDPContext->setMulticastInterface(fromIPAddress); + +#ifdef MDNS_IP4_SUPPORT + IPAddress toMulticastAddress(DNS_MQUERY_IPV4_GROUP_INIT); +#endif +#ifdef MDNS_IP6_SUPPORT + //TODO: set multicast address + IPAddress toMulticastAddress(DNS_MQUERY_IPV6_GROUP_INIT); +#endif + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage_Multicast: Will send to '%s'.\n"), toMulticastAddress.toString().c_str());); + bResult = ((_prepareMDNSMessage(p_rSendParameter, fromIPAddress)) && + (m_pUDPContext->send(toMulticastAddress, DNS_MQUERY_PORT))); + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage_Multicast: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_prepareMDNSMessage + + The MDNS message is composed in a two-step process. + In the first loop 'only' the header informations (mainly number of answers) are collected, + while in the seconds loop, the header and all queries and answers are written to the UDP + output buffer. + +*/ +bool MDNSResponder::_prepareMDNSMessage(MDNSResponder::stcMDNSSendParameter& p_rSendParameter, + IPAddress p_IPAddress) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage\n"));); + bool bResult = true; + + // Prepare header; count answers + stcMDNS_MsgHeader msgHeader(p_rSendParameter.m_u16ID, p_rSendParameter.m_bResponse, 0, p_rSendParameter.m_bAuthorative); + // If this is a response, the answers are anwers, + // else this is a query or probe and the answers go into auth section + uint16_t& ru16Answers = (p_rSendParameter.m_bResponse + ? msgHeader.m_u16ANCount + : msgHeader.m_u16NSCount); + + /** + enuSequence + */ + enum enuSequence + { + Sequence_Count = 0, + Sequence_Send = 1 + }; + + // Two step sequence: 'Count' and 'Send' + for (uint32_t sequence = Sequence_Count; ((bResult) && (sequence <= Sequence_Send)); ++sequence) + { + DEBUG_EX_INFO( + if (Sequence_Send == sequence) + { + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), + (unsigned)msgHeader.m_u16ID, + (unsigned)msgHeader.m_1bQR, (unsigned)msgHeader.m_4bOpcode, (unsigned)msgHeader.m_1bAA, (unsigned)msgHeader.m_1bTC, (unsigned)msgHeader.m_1bRD, + (unsigned)msgHeader.m_1bRA, (unsigned)msgHeader.m_4bRCode, + (unsigned)msgHeader.m_u16QDCount, + (unsigned)msgHeader.m_u16ANCount, + (unsigned)msgHeader.m_u16NSCount, + (unsigned)msgHeader.m_u16ARCount); + } + ); + // Count/send + // Header + bResult = ((Sequence_Count == sequence) + ? true + : _writeMDNSMsgHeader(msgHeader, p_rSendParameter)); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSMsgHeader FAILED!\n"));); + // Questions + for (stcMDNS_RRQuestion* pQuestion = p_rSendParameter.m_pQuestions; ((bResult) && (pQuestion)); pQuestion = pQuestion->m_pNext) + { + ((Sequence_Count == sequence) + ? ++msgHeader.m_u16QDCount + : (bResult = _writeMDNSQuestion(*pQuestion, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSQuestion FAILED!\n"));); + } + + // Answers and authorative answers +#ifdef MDNS_IP4_SUPPORT + if ((bResult) && + (p_rSendParameter.m_u8HostReplyMask & ContentFlag_A)) + { + ((Sequence_Count == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_A(p_IPAddress, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_A(A) FAILED!\n"));); + } + if ((bResult) && + (p_rSendParameter.m_u8HostReplyMask & ContentFlag_PTR_IP4)) + { + ((Sequence_Count == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_PTR_IP4(p_IPAddress, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_PTR_IP4 FAILED!\n"));); + } +#endif +#ifdef MDNS_IP6_SUPPORT + if ((bResult) && + (p_rSendParameter.m_u8HostReplyMask & ContentFlag_AAAA)) + { + ((Sequence_Count == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_AAAA(p_IPAddress, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_AAAA(A) FAILED!\n"));); + } + if ((bResult) && + (p_rSendParameter.m_u8HostReplyMask & ContentFlag_PTR_IP6)) + { + ((Sequence_Count == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_PTR_IP6(p_IPAddress, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_PTR_IP6 FAILED!\n"));); + } +#endif + + for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + { + if ((bResult) && + (pService->m_u8ReplyMask & ContentFlag_PTR_TYPE)) + { + ((Sequence_Count == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_PTR_TYPE(*pService, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_PTR_TYPE FAILED!\n"));); + } + if ((bResult) && + (pService->m_u8ReplyMask & ContentFlag_PTR_NAME)) + { + ((Sequence_Count == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_PTR_NAME(*pService, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_PTR_NAME FAILED!\n"));); + } + if ((bResult) && + (pService->m_u8ReplyMask & ContentFlag_SRV)) + { + ((Sequence_Count == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_SRV(*pService, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_SRV(A) FAILED!\n"));); + } + if ((bResult) && + (pService->m_u8ReplyMask & ContentFlag_TXT)) + { + ((Sequence_Count == sequence) + ? ++ru16Answers + : (bResult = _writeMDNSAnswer_TXT(*pService, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_TXT(A) FAILED!\n"));); + } + } // for services + + // Additional answers +#ifdef MDNS_IP4_SUPPORT + bool bNeedsAdditionalAnswerA = false; +#endif +#ifdef MDNS_IP6_SUPPORT + bool bNeedsAdditionalAnswerAAAA = false; +#endif + for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) + { + if ((bResult) && + (pService->m_u8ReplyMask & ContentFlag_PTR_NAME) && // If PTR_NAME is requested, AND + (!(pService->m_u8ReplyMask & ContentFlag_SRV))) // NOT SRV -> add SRV as additional answer + { + ((Sequence_Count == sequence) + ? ++msgHeader.m_u16ARCount + : (bResult = _writeMDNSAnswer_SRV(*pService, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_SRV(B) FAILED!\n"));); + } + if ((bResult) && + (pService->m_u8ReplyMask & ContentFlag_PTR_NAME) && // If PTR_NAME is requested, AND + (!(pService->m_u8ReplyMask & ContentFlag_TXT))) // NOT TXT -> add TXT as additional answer + { + ((Sequence_Count == sequence) + ? ++msgHeader.m_u16ARCount + : (bResult = _writeMDNSAnswer_TXT(*pService, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_TXT(B) FAILED!\n"));); + } + if ((pService->m_u8ReplyMask & (ContentFlag_PTR_NAME | ContentFlag_SRV)) || // If service instance name or SRV OR + (p_rSendParameter.m_u8HostReplyMask & (ContentFlag_A | ContentFlag_AAAA))) // any host IP address is requested + { +#ifdef MDNS_IP4_SUPPORT + if ((bResult) && + (!(p_rSendParameter.m_u8HostReplyMask & ContentFlag_A))) // Add IP4 address + { + bNeedsAdditionalAnswerA = true; + } +#endif +#ifdef MDNS_IP6_SUPPORT + if ((bResult) && + (!(p_rSendParameter.m_u8HostReplyMask & ContentFlag_AAAA))) // Add IP6 address + { + bNeedsAdditionalAnswerAAAA = true; + } +#endif + } + } // for services + + // Answer A needed? +#ifdef MDNS_IP4_SUPPORT + if ((bResult) && + (bNeedsAdditionalAnswerA)) + { + ((Sequence_Count == sequence) + ? ++msgHeader.m_u16ARCount + : (bResult = _writeMDNSAnswer_A(p_IPAddress, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_A(B) FAILED!\n"));); + } +#endif +#ifdef MDNS_IP6_SUPPORT + // Answer AAAA needed? + if ((bResult) && + (bNeedsAdditionalAnswerAAAA)) + { + ((Sequence_Count == sequence) + ? ++msgHeader.m_u16ARCount + : (bResult = _writeMDNSAnswer_AAAA(p_IPAddress, p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_AAAA(B) FAILED!\n"));); + } +#endif + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: Loop %i FAILED!\n"), sequence);); + } // for sequence + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: FAILED!\n"));); + return bResult; +} + +/* + MDNSResponder::_sendMDNSServiceQuery + + Creates and sends a PTR query for the given service domain. + +*/ +bool MDNSResponder::_sendMDNSServiceQuery(const MDNSResponder::stcMDNSServiceQuery& p_ServiceQuery) +{ + + return _sendMDNSQuery(p_ServiceQuery.m_ServiceTypeDomain, DNS_RRTYPE_PTR); +} + +/* + MDNSResponder::_sendMDNSQuery + + Creates and sends a query for the given domain and query type. + +*/ +bool MDNSResponder::_sendMDNSQuery(const MDNSResponder::stcMDNS_RRDomain& p_QueryDomain, + uint16_t p_u16QueryType, + stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers /*= 0*/) +{ + + bool bResult = false; + + stcMDNSSendParameter sendParameter; + if (0 != ((sendParameter.m_pQuestions = new stcMDNS_RRQuestion))) + { + sendParameter.m_pQuestions->m_Header.m_Domain = p_QueryDomain; + + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = p_u16QueryType; + // It seems, that some mDNS implementations don't support 'unicast response' questions... + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (/*0x8000 |*/ DNS_RRCLASS_IN); // /*Unicast &*/ INternet + + // TODO: Add knwon answer to the query + (void)p_pKnownAnswers; + + bResult = _sendMDNSMessage(sendParameter); + } // else: FAILED to alloc question + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSQuery: FAILED to alloc question!\n"));); + return bResult; +} + +/** + HELPERS +*/ + +/** + RESOURCE RECORDS +*/ + +/* + MDNSResponder::_readRRQuestion + + Reads a question (eg. MyESP._http._tcp.local ANY IN) from the UPD input buffer. + +*/ +bool MDNSResponder::_readRRQuestion(MDNSResponder::stcMDNS_RRQuestion& p_rRRQuestion) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRQuestion\n"));); + + bool bResult = false; + + if ((bResult = _readRRHeader(p_rRRQuestion.m_Header))) + { + // Extract unicast flag from class field + p_rRRQuestion.m_bUnicast = (p_rRRQuestion.m_Header.m_Attributes.m_u16Class & 0x8000); + p_rRRQuestion.m_Header.m_Attributes.m_u16Class &= (~0x8000); + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRQuestion ")); + _printRRDomain(p_rRRQuestion.m_Header.m_Domain); + DEBUG_OUTPUT.printf_P(PSTR(" Type:0x%04X Class:0x%04X %s\n"), (unsigned)p_rRRQuestion.m_Header.m_Attributes.m_u16Type, (unsigned)p_rRRQuestion.m_Header.m_Attributes.m_u16Class, (p_rRRQuestion.m_bUnicast ? "Unicast" : "Multicast")); + ); + } + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRQuestion: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_readRRAnswer + + Reads an answer (eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local) + from the UDP input buffer. + After reading the domain and type info, the further processing of the answer + is transferred the answer specific reading functions. + Unknown answer types are processed by the generic answer reader (to remove them + from the input buffer). + +*/ +bool MDNSResponder::_readRRAnswer(MDNSResponder::stcMDNS_RRAnswer*& p_rpRRAnswer) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer\n"));); + + bool bResult = false; + + stcMDNS_RRHeader header; + uint32_t u32TTL; + uint16_t u16RDLength; + if ((_readRRHeader(header)) && + (_udpRead32(u32TTL)) && + (_udpRead16(u16RDLength))) + { + + /* DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer: Reading 0x%04X answer (class:0x%04X, TTL:%u, RDLength:%u) for "), header.m_Attributes.m_u16Type, header.m_Attributes.m_u16Class, u32TTL, u16RDLength); + _printRRDomain(header.m_Domain); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + );*/ + + switch (header.m_Attributes.m_u16Type & (~0x8000)) // Topmost bit might carry 'cache flush' flag + { +#ifdef MDNS_IP4_SUPPORT + case DNS_RRTYPE_A: + p_rpRRAnswer = new stcMDNS_RRAnswerA(header, u32TTL); + bResult = _readRRAnswerA(*(stcMDNS_RRAnswerA*&)p_rpRRAnswer, u16RDLength); + break; +#endif + case DNS_RRTYPE_PTR: + p_rpRRAnswer = new stcMDNS_RRAnswerPTR(header, u32TTL); + bResult = _readRRAnswerPTR(*(stcMDNS_RRAnswerPTR*&)p_rpRRAnswer, u16RDLength); + break; + case DNS_RRTYPE_TXT: + p_rpRRAnswer = new stcMDNS_RRAnswerTXT(header, u32TTL); + bResult = _readRRAnswerTXT(*(stcMDNS_RRAnswerTXT*&)p_rpRRAnswer, u16RDLength); + break; +#ifdef MDNS_IP6_SUPPORT + case DNS_RRTYPE_AAAA: + p_rpRRAnswer = new stcMDNS_RRAnswerAAAA(header, u32TTL); + bResult = _readRRAnswerAAAA(*(stcMDNS_RRAnswerAAAA*&)p_rpRRAnswer, u16RDLength); + break; +#endif + case DNS_RRTYPE_SRV: + p_rpRRAnswer = new stcMDNS_RRAnswerSRV(header, u32TTL); + bResult = _readRRAnswerSRV(*(stcMDNS_RRAnswerSRV*&)p_rpRRAnswer, u16RDLength); + break; + default: + p_rpRRAnswer = new stcMDNS_RRAnswerGeneric(header, u32TTL); + bResult = _readRRAnswerGeneric(*(stcMDNS_RRAnswerGeneric*&)p_rpRRAnswer, u16RDLength); + break; + } + DEBUG_EX_INFO( + if ((bResult) && + (p_rpRRAnswer)) + { + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer: ")); + _printRRDomain(p_rpRRAnswer->m_Header.m_Domain); + DEBUG_OUTPUT.printf_P(PSTR(" Type:0x%04X Class:0x%04X TTL:%u, RDLength:%u "), p_rpRRAnswer->m_Header.m_Attributes.m_u16Type, p_rpRRAnswer->m_Header.m_Attributes.m_u16Class, p_rpRRAnswer->m_u32TTL, u16RDLength); + switch (header.m_Attributes.m_u16Type & (~0x8000)) // Topmost bit might carry 'cache flush' flag + { +#ifdef MDNS_IP4_SUPPORT + case DNS_RRTYPE_A: + DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((stcMDNS_RRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); + break; +#endif + case DNS_RRTYPE_PTR: + DEBUG_OUTPUT.printf_P(PSTR("PTR ")); + _printRRDomain(((stcMDNS_RRAnswerPTR*&)p_rpRRAnswer)->m_PTRDomain); + break; + case DNS_RRTYPE_TXT: + { + size_t stTxtLength = ((stcMDNS_RRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_strLength(); + char* pTxts = new char[stTxtLength]; + if (pTxts) + { + ((stcMDNS_RRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_str(pTxts); + DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts); + delete[] pTxts; + } + break; + } +#ifdef MDNS_IP6_SUPPORT + case DNS_RRTYPE_AAAA: + DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((stcMDNS_RRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); + break; +#endif + case DNS_RRTYPE_SRV: + DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((stcMDNS_RRAnswerSRV*&)p_rpRRAnswer)->m_u16Port); + _printRRDomain(((stcMDNS_RRAnswerSRV*&)p_rpRRAnswer)->m_SRVDomain); + break; + default: + DEBUG_OUTPUT.printf_P(PSTR("generic ")); + break; + } + DEBUG_OUTPUT.printf_P(PSTR("\n")); + } + else + { + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer: FAILED to read specific answer of type 0x%04X!\n"), p_rpRRAnswer->m_Header.m_Attributes.m_u16Type); + } + ); // DEBUG_EX_INFO + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer: FAILED!\n"));); + return bResult; +} + +#ifdef MDNS_IP4_SUPPORT +/* + MDNSResponder::_readRRAnswerA +*/ +bool MDNSResponder::_readRRAnswerA(MDNSResponder::stcMDNS_RRAnswerA& p_rRRAnswerA, + uint16_t p_u16RDLength) +{ + + uint32_t u32IP4Address; + bool bResult = ((MDNS_IP4_SIZE == p_u16RDLength) && + (_udpReadBuffer((unsigned char*)&u32IP4Address, MDNS_IP4_SIZE)) && + ((p_rRRAnswerA.m_IPAddress = IPAddress(u32IP4Address)))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerA: FAILED!\n"));); + return bResult; +} +#endif + +/* + MDNSResponder::_readRRAnswerPTR +*/ +bool MDNSResponder::_readRRAnswerPTR(MDNSResponder::stcMDNS_RRAnswerPTR& p_rRRAnswerPTR, + uint16_t p_u16RDLength) +{ + + bool bResult = ((p_u16RDLength) && + (_readRRDomain(p_rRRAnswerPTR.m_PTRDomain))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerPTR: FAILED!\n"));); + return bResult; +} + +/* + MDNSResponder::_readRRAnswerTXT + + Read TXT items from a buffer like 4c#=15ff=20 +*/ +bool MDNSResponder::_readRRAnswerTXT(MDNSResponder::stcMDNS_RRAnswerTXT& p_rRRAnswerTXT, + uint16_t p_u16RDLength) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: RDLength:%u\n"), p_u16RDLength);); + bool bResult = true; + + p_rRRAnswerTXT.clear(); + if (p_u16RDLength) + { + bResult = false; + + unsigned char* pucBuffer = new unsigned char[p_u16RDLength]; + if (pucBuffer) + { + if (_udpReadBuffer(pucBuffer, p_u16RDLength)) + { + bResult = true; + + const unsigned char* pucCursor = pucBuffer; + while ((pucCursor < (pucBuffer + p_u16RDLength)) && + (bResult)) + { + bResult = false; + + stcMDNSServiceTxt* pTxt = 0; + unsigned char ucLength = *pucCursor++; // Length of the next txt item + if (ucLength) + { + DEBUG_EX_INFO( + static char sacBuffer[64]; *sacBuffer = 0; + uint8_t u8MaxLength = ((ucLength > (sizeof(sacBuffer) - 1)) ? (sizeof(sacBuffer) - 1) : ucLength); + os_strncpy(sacBuffer, (const char*)pucCursor, u8MaxLength); sacBuffer[u8MaxLength] = 0; + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: Item(%u): %s\n"), ucLength, sacBuffer); + ); + + unsigned char* pucEqualSign = (unsigned char*)os_strchr((const char*)pucCursor, '='); // Position of the '=' sign + unsigned char ucKeyLength; + if ((pucEqualSign) && + ((ucKeyLength = (pucEqualSign - pucCursor)))) + { + unsigned char ucValueLength = (ucLength - (pucEqualSign - pucCursor + 1)); + bResult = (((pTxt = new stcMDNSServiceTxt)) && + (pTxt->setKey((const char*)pucCursor, ucKeyLength)) && + (pTxt->setValue((const char*)(pucEqualSign + 1), ucValueLength))); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: INVALID TXT format (No '=')!\n"));); + } + pucCursor += ucLength; + } + else // no/zero length TXT + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: TXT answer contains no items.\n"));); + bResult = true; + } + + if ((bResult) && + (pTxt)) // Everythings fine so far + { + // Link TXT item to answer TXTs + pTxt->m_pNext = p_rRRAnswerTXT.m_Txts.m_pTxts; + p_rRRAnswerTXT.m_Txts.m_pTxts = pTxt; + } + else // At least no TXT (migth be OK, if length was 0) OR an error + { + if (!bResult) + { + DEBUG_EX_ERR( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: FAILED to read TXT item!\n")); + DEBUG_OUTPUT.printf_P(PSTR("RData dump:\n")); + _udpDump((m_pUDPContext->tell() - p_u16RDLength), p_u16RDLength); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + ); + } + if (pTxt) + { + delete pTxt; + pTxt = 0; + } + p_rRRAnswerTXT.clear(); + } + } // while + + DEBUG_EX_ERR( + if (!bResult) // Some failure + { + DEBUG_OUTPUT.printf_P(PSTR("RData dump:\n")); + _udpDump((m_pUDPContext->tell() - p_u16RDLength), p_u16RDLength); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + } + ); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: FAILED to read TXT content!\n"));); + } + // Clean up + delete[] pucBuffer; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: FAILED to alloc buffer for TXT content!\n"));); + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: WARNING! No content!\n"));); + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: FAILED!\n"));); + return bResult; +} + +#ifdef MDNS_IP6_SUPPORT +bool MDNSResponder::_readRRAnswerAAAA(MDNSResponder::stcMDNS_RRAnswerAAAA& p_rRRAnswerAAAA, + uint16_t p_u16RDLength) +{ + bool bResult = false; + // TODO: Implement + return bResult; +} +#endif + +/* + MDNSResponder::_readRRAnswerSRV +*/ +bool MDNSResponder::_readRRAnswerSRV(MDNSResponder::stcMDNS_RRAnswerSRV& p_rRRAnswerSRV, + uint16_t p_u16RDLength) +{ + + bool bResult = (((3 * sizeof(uint16_t)) < p_u16RDLength) && + (_udpRead16(p_rRRAnswerSRV.m_u16Priority)) && + (_udpRead16(p_rRRAnswerSRV.m_u16Weight)) && + (_udpRead16(p_rRRAnswerSRV.m_u16Port)) && + (_readRRDomain(p_rRRAnswerSRV.m_SRVDomain))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerSRV: FAILED!\n"));); + return bResult; +} + +/* + MDNSResponder::_readRRAnswerGeneric +*/ +bool MDNSResponder::_readRRAnswerGeneric(MDNSResponder::stcMDNS_RRAnswerGeneric& p_rRRAnswerGeneric, + uint16_t p_u16RDLength) +{ + bool bResult = (0 == p_u16RDLength); + + p_rRRAnswerGeneric.clear(); + if (((p_rRRAnswerGeneric.m_u16RDLength = p_u16RDLength)) && + ((p_rRRAnswerGeneric.m_pu8RDData = new unsigned char[p_rRRAnswerGeneric.m_u16RDLength]))) + { + + bResult = _udpReadBuffer(p_rRRAnswerGeneric.m_pu8RDData, p_rRRAnswerGeneric.m_u16RDLength); + } + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerGeneric: FAILED!\n"));); + return bResult; +} + +/* + MDNSResponder::_readRRHeader +*/ +bool MDNSResponder::_readRRHeader(MDNSResponder::stcMDNS_RRHeader& p_rRRHeader) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRHeader\n"));); + + bool bResult = ((_readRRDomain(p_rRRHeader.m_Domain)) && + (_readRRAttributes(p_rRRHeader.m_Attributes))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRHeader: FAILED!\n"));); + return bResult; +} + +/* + MDNSResponder::_readRRDomain + + Reads a (maybe multilevel compressed) domain from the UDP input buffer. + +*/ +bool MDNSResponder::_readRRDomain(MDNSResponder::stcMDNS_RRDomain& p_rRRDomain) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain\n"));); + + bool bResult = ((p_rRRDomain.clear()) && + (_readRRDomain_Loop(p_rRRDomain, 0))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain: FAILED!\n"));); + return bResult; +} + +/* + MDNSResponder::_readRRDomain_Loop + + Reads a domain from the UDP input buffer. For every compression level, the functions + calls itself recursively. To avoid endless recursion because of malformed MDNS records, + the maximum recursion depth is set by MDNS_DOMAIN_MAX_REDIRCTION. + +*/ +bool MDNSResponder::_readRRDomain_Loop(MDNSResponder::stcMDNS_RRDomain& p_rRRDomain, + uint8_t p_u8Depth) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u)\n"), p_u8Depth);); + + bool bResult = false; + + if (MDNS_DOMAIN_MAX_REDIRCTION >= p_u8Depth) + { + bResult = true; + + uint8_t u8Len = 0; + do + { + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): Offset:%u p0:%02x\n"), p_u8Depth, m_pUDPContext->tell(), m_pUDPContext->peek());); + _udpRead8(u8Len); + + if (u8Len & MDNS_DOMAIN_COMPRESS_MARK) + { + // Compressed label(s) + uint16_t u16Offset = ((u8Len & ~MDNS_DOMAIN_COMPRESS_MARK) << 8); // Implicit BE to LE conversion! + _udpRead8(u8Len); + u16Offset |= u8Len; + + if (m_pUDPContext->isValidOffset(u16Offset)) + { + size_t stCurrentPosition = m_pUDPContext->tell(); // Prepare return from recursion + + //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): Redirecting from %u to %u!\n"), p_u8Depth, stCurrentPosition, u16Offset);); + m_pUDPContext->seek(u16Offset); + if (_readRRDomain_Loop(p_rRRDomain, p_u8Depth + 1)) // Do recursion + { + //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): Succeeded to read redirected label! Returning to %u\n"), p_u8Depth, stCurrentPosition);); + m_pUDPContext->seek(stCurrentPosition); // Restore after recursion + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): FAILED to read redirected label!\n"), p_u8Depth);); + bResult = false; + } + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): INVALID offset in redirection!\n"), p_u8Depth);); + bResult = false; + } + break; + } + else + { + // Normal (uncompressed) label (maybe '\0' only) + if (MDNS_DOMAIN_MAXLENGTH > (p_rRRDomain.m_u16NameLength + u8Len)) + { + // Add length byte + p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength] = u8Len; + ++(p_rRRDomain.m_u16NameLength); + if (u8Len) // Add name + { + if ((bResult = _udpReadBuffer((unsigned char*) & (p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength]), u8Len))) + { + /* DEBUG_EX_INFO( + p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength + u8Len] = 0; // Closing '\0' for printing + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): Domain label (%u): %s\n"), p_u8Depth, (unsigned)(p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength - 1]), &(p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength])); + );*/ + + p_rRRDomain.m_u16NameLength += u8Len; + } + } + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(2) offset:%u p0:%x\n"), m_pUDPContext->tell(), m_pUDPContext->peek());); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): ERROR! Domain name too long (%u + %u)!\n"), p_u8Depth, p_rRRDomain.m_u16NameLength, u8Len);); + bResult = false; + break; + } + } + } while ((bResult) && + (0 != u8Len)); + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): ERROR! Too many redirections!\n"), p_u8Depth);); + } + return bResult; +} + +/* + MDNSResponder::_readRRAttributes +*/ +bool MDNSResponder::_readRRAttributes(MDNSResponder::stcMDNS_RRAttributes& p_rRRAttributes) +{ + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAttributes\n"));); + + bool bResult = ((_udpRead16(p_rRRAttributes.m_u16Type)) && + (_udpRead16(p_rRRAttributes.m_u16Class))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAttributes: FAILED!\n"));); + return bResult; +} + + +/* + DOMAIN NAMES +*/ + +/* + MDNSResponder::_buildDomainForHost + + Builds a MDNS host domain (eg. esp8266.local) for the given hostname. + +*/ +bool MDNSResponder::_buildDomainForHost(const char* p_pcHostname, + MDNSResponder::stcMDNS_RRDomain& p_rHostDomain) const +{ + + p_rHostDomain.clear(); + bool bResult = ((p_pcHostname) && + (*p_pcHostname) && + (p_rHostDomain.addLabel(p_pcHostname)) && + (p_rHostDomain.addLabel(scpcLocal)) && + (p_rHostDomain.addLabel(0))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForHost: FAILED!\n"));); + return bResult; +} + +/* + MDNSResponder::_buildDomainForDNSSD + + Builds the '_services._dns-sd._udp.local' domain. + Used while detecting generic service enum question (DNS-SD) and answering these questions. + +*/ +bool MDNSResponder::_buildDomainForDNSSD(MDNSResponder::stcMDNS_RRDomain& p_rDNSSDDomain) const +{ + + p_rDNSSDDomain.clear(); + bool bResult = ((p_rDNSSDDomain.addLabel(scpcServices, true)) && + (p_rDNSSDDomain.addLabel(scpcDNSSD, true)) && + (p_rDNSSDDomain.addLabel(scpcUDP, true)) && + (p_rDNSSDDomain.addLabel(scpcLocal)) && + (p_rDNSSDDomain.addLabel(0))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForDNSSD: FAILED!\n"));); + return bResult; +} + +/* + MDNSResponder::_buildDomainForService + + Builds the domain for the given service (eg. _http._tcp.local or + MyESP._http._tcp.local (if p_bIncludeName is set)). + +*/ +bool MDNSResponder::_buildDomainForService(const MDNSResponder::stcMDNSService& p_Service, + bool p_bIncludeName, + MDNSResponder::stcMDNS_RRDomain& p_rServiceDomain) const +{ + + p_rServiceDomain.clear(); + bool bResult = (((!p_bIncludeName) || + (p_rServiceDomain.addLabel(p_Service.m_pcName))) && + (p_rServiceDomain.addLabel(p_Service.m_pcService, true)) && + (p_rServiceDomain.addLabel(p_Service.m_pcProtocol, true)) && + (p_rServiceDomain.addLabel(scpcLocal)) && + (p_rServiceDomain.addLabel(0))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForService: FAILED!\n"));); + return bResult; +} + +/* + MDNSResponder::_buildDomainForService + + Builds the domain for the given service properties (eg. _http._tcp.local). + The usual prepended '_' are added, if missing in the input strings. + +*/ +bool MDNSResponder::_buildDomainForService(const char* p_pcService, + const char* p_pcProtocol, + MDNSResponder::stcMDNS_RRDomain& p_rServiceDomain) const +{ + + p_rServiceDomain.clear(); + bool bResult = ((p_pcService) && + (p_pcProtocol) && + (p_rServiceDomain.addLabel(p_pcService, ('_' != *p_pcService))) && + (p_rServiceDomain.addLabel(p_pcProtocol, ('_' != *p_pcProtocol))) && + (p_rServiceDomain.addLabel(scpcLocal)) && + (p_rServiceDomain.addLabel(0))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForService: FAILED for (%s.%s)!\n"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); + return bResult; +} + +#ifdef MDNS_IP4_SUPPORT +/* + MDNSResponder::_buildDomainForReverseIP4 + + The IP4 address is stringized by printing the four address bytes into a char buffer in reverse order + and adding 'in-addr.arpa' (eg. 012.789.456.123.in-addr.arpa). + Used while detecting reverse IP4 questions and answering these +*/ +bool MDNSResponder::_buildDomainForReverseIP4(IPAddress p_IP4Address, + MDNSResponder::stcMDNS_RRDomain& p_rReverseIP4Domain) const +{ + + bool bResult = true; + + p_rReverseIP4Domain.clear(); + + char acBuffer[32]; + for (int i = MDNS_IP4_SIZE; ((bResult) && (i >= 1)); --i) + { + itoa(p_IP4Address[i - 1], acBuffer, 10); + bResult = p_rReverseIP4Domain.addLabel(acBuffer); + } + bResult = ((bResult) && + (p_rReverseIP4Domain.addLabel(scpcReverseIP4Domain)) && + (p_rReverseIP4Domain.addLabel(scpcReverseTopDomain)) && + (p_rReverseIP4Domain.addLabel(0))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForReverseIP4: FAILED!\n"));); + return bResult; +} +#endif + +#ifdef MDNS_IP6_SUPPORT +/* + MDNSResponder::_buildDomainForReverseIP6 + + Used while detecting reverse IP6 questions and answering these +*/ +bool MDNSResponder::_buildDomainForReverseIP6(IPAddress p_IP4Address, + MDNSResponder::stcMDNS_RRDomain& p_rReverseIP6Domain) const +{ + // TODO: Implement + return false; +} +#endif + + +/* + UDP +*/ + +/* + MDNSResponder::_udpReadBuffer +*/ +bool MDNSResponder::_udpReadBuffer(unsigned char* p_pBuffer, + size_t p_stLength) +{ + + bool bResult = ((m_pUDPContext) && + (true/*m_pUDPContext->getSize() > p_stLength*/) && + (p_pBuffer) && + (p_stLength) && + ((p_stLength == m_pUDPContext->read((char*)p_pBuffer, p_stLength)))); + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _udpReadBuffer: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_udpRead8 +*/ +bool MDNSResponder::_udpRead8(uint8_t& p_ru8Value) +{ + + return _udpReadBuffer((unsigned char*)&p_ru8Value, sizeof(p_ru8Value)); +} + +/* + MDNSResponder::_udpRead16 +*/ +bool MDNSResponder::_udpRead16(uint16_t& p_ru16Value) +{ + + bool bResult = false; + + if (_udpReadBuffer((unsigned char*)&p_ru16Value, sizeof(p_ru16Value))) + { + p_ru16Value = lwip_ntohs(p_ru16Value); + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::_udpRead32 +*/ +bool MDNSResponder::_udpRead32(uint32_t& p_ru32Value) +{ + + bool bResult = false; + + if (_udpReadBuffer((unsigned char*)&p_ru32Value, sizeof(p_ru32Value))) + { + p_ru32Value = lwip_ntohl(p_ru32Value); + bResult = true; + } + return bResult; +} + +/* + MDNSResponder::_udpAppendBuffer +*/ +bool MDNSResponder::_udpAppendBuffer(const unsigned char* p_pcBuffer, + size_t p_stLength) +{ + + bool bResult = ((m_pUDPContext) && + (p_pcBuffer) && + (p_stLength) && + (p_stLength == m_pUDPContext->append((const char*)p_pcBuffer, p_stLength))); + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _udpAppendBuffer: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_udpAppend8 +*/ +bool MDNSResponder::_udpAppend8(uint8_t p_u8Value) +{ + + return (_udpAppendBuffer((unsigned char*)&p_u8Value, sizeof(p_u8Value))); +} + +/* + MDNSResponder::_udpAppend16 +*/ +bool MDNSResponder::_udpAppend16(uint16_t p_u16Value) +{ + + p_u16Value = lwip_htons(p_u16Value); + return (_udpAppendBuffer((unsigned char*)&p_u16Value, sizeof(p_u16Value))); +} + +/* + MDNSResponder::_udpAppend32 +*/ +bool MDNSResponder::_udpAppend32(uint32_t p_u32Value) +{ + + p_u32Value = lwip_htonl(p_u32Value); + return (_udpAppendBuffer((unsigned char*)&p_u32Value, sizeof(p_u32Value))); +} + +#ifdef DEBUG_ESP_MDNS_RESPONDER +/* + MDNSResponder::_udpDump +*/ +bool MDNSResponder::_udpDump(bool p_bMovePointer /*= false*/) +{ + + const uint8_t cu8BytesPerLine = 16; + + uint32_t u32StartPosition = m_pUDPContext->tell(); + DEBUG_OUTPUT.println("UDP Context Dump:"); + uint32_t u32Counter = 0; + uint8_t u8Byte = 0; + + while (_udpRead8(u8Byte)) + { + DEBUG_OUTPUT.printf_P(PSTR("%02x %s"), u8Byte, ((++u32Counter % cu8BytesPerLine) ? "" : "\n")); + } + DEBUG_OUTPUT.printf_P(PSTR("%sDone: %u bytes\n"), (((u32Counter) && (u32Counter % cu8BytesPerLine)) ? "\n" : ""), u32Counter); + + if (!p_bMovePointer) // Restore + { + m_pUDPContext->seek(u32StartPosition); + } + return true; +} + +/* + MDNSResponder::_udpDump +*/ +bool MDNSResponder::_udpDump(unsigned p_uOffset, + unsigned p_uLength) +{ + + if ((m_pUDPContext) && + (m_pUDPContext->isValidOffset(p_uOffset))) + { + unsigned uCurrentPosition = m_pUDPContext->tell(); // Remember start position + + m_pUDPContext->seek(p_uOffset); + uint8_t u8Byte; + for (unsigned u = 0; ((u < p_uLength) && (_udpRead8(u8Byte))); ++u) + { + DEBUG_OUTPUT.printf_P(PSTR("%02x "), u8Byte); + } + // Return to start position + m_pUDPContext->seek(uCurrentPosition); + } + return true; +} +#endif + + +/** + READ/WRITE MDNS STRUCTS +*/ + +/* + MDNSResponder::_readMDNSMsgHeader + + Read a MDNS header from the UDP input buffer. + | 8 | 8 | 8 | 8 | + 00| Identifier | Flags & Codes | + 01| Question count | Answer count | + 02| NS answer count | Ad answer count | + + All 16-bit and 32-bit elements need to be translated form network coding to host coding (done in _udpRead16 and _udpRead32) + In addition, bitfield memory order is undefined in C standard (GCC doesn't order them in the coded direction...), so they + need some mapping here +*/ +bool MDNSResponder::_readMDNSMsgHeader(MDNSResponder::stcMDNS_MsgHeader& p_rMsgHeader) +{ + + bool bResult = false; + + uint8_t u8B1; + uint8_t u8B2; + if ((_udpRead16(p_rMsgHeader.m_u16ID)) && + (_udpRead8(u8B1)) && + (_udpRead8(u8B2)) && + (_udpRead16(p_rMsgHeader.m_u16QDCount)) && + (_udpRead16(p_rMsgHeader.m_u16ANCount)) && + (_udpRead16(p_rMsgHeader.m_u16NSCount)) && + (_udpRead16(p_rMsgHeader.m_u16ARCount))) + { + + p_rMsgHeader.m_1bQR = (u8B1 & 0x80); // Query/Responde flag + p_rMsgHeader.m_4bOpcode = (u8B1 & 0x78); // Operation code (0: Standard query, others ignored) + p_rMsgHeader.m_1bAA = (u8B1 & 0x04); // Authorative answer + p_rMsgHeader.m_1bTC = (u8B1 & 0x02); // Truncation flag + p_rMsgHeader.m_1bRD = (u8B1 & 0x01); // Recursion desired + + p_rMsgHeader.m_1bRA = (u8B2 & 0x80); // Recursion available + p_rMsgHeader.m_3bZ = (u8B2 & 0x70); // Zero + p_rMsgHeader.m_4bRCode = (u8B2 & 0x0F); // Response code + + /* DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readMDNSMsgHeader: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), + (unsigned)p_rMsgHeader.m_u16ID, + (unsigned)p_rMsgHeader.m_1bQR, (unsigned)p_rMsgHeader.m_4bOpcode, (unsigned)p_rMsgHeader.m_1bAA, (unsigned)p_rMsgHeader.m_1bTC, (unsigned)p_rMsgHeader.m_1bRD, + (unsigned)p_rMsgHeader.m_1bRA, (unsigned)p_rMsgHeader.m_4bRCode, + (unsigned)p_rMsgHeader.m_u16QDCount, + (unsigned)p_rMsgHeader.m_u16ANCount, + (unsigned)p_rMsgHeader.m_u16NSCount, + (unsigned)p_rMsgHeader.m_u16ARCount););*/ + bResult = true; + } + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readMDNSMsgHeader: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_write8 +*/ +bool MDNSResponder::_write8(uint8_t p_u8Value, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + + return ((_udpAppend8(p_u8Value)) && + (p_rSendParameter.shiftOffset(sizeof(p_u8Value)))); +} + +/* + MDNSResponder::_write16 +*/ +bool MDNSResponder::_write16(uint16_t p_u16Value, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + + return ((_udpAppend16(p_u16Value)) && + (p_rSendParameter.shiftOffset(sizeof(p_u16Value)))); +} + +/* + MDNSResponder::_write32 +*/ +bool MDNSResponder::_write32(uint32_t p_u32Value, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + + return ((_udpAppend32(p_u32Value)) && + (p_rSendParameter.shiftOffset(sizeof(p_u32Value)))); +} + +/* + MDNSResponder::_writeMDNSMsgHeader + + Write MDNS header to the UDP output buffer. + + All 16-bit and 32-bit elements need to be translated form host coding to network coding (done in _udpAppend16 and _udpAppend32) + In addition, bitfield memory order is undefined in C standard (GCC doesn't order them in the coded direction...), so they + need some mapping here +*/ +bool MDNSResponder::_writeMDNSMsgHeader(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHeader, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + /* DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSMsgHeader: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), + (unsigned)p_MsgHeader.m_u16ID, + (unsigned)p_MsgHeader.m_1bQR, (unsigned)p_MsgHeader.m_4bOpcode, (unsigned)p_MsgHeader.m_1bAA, (unsigned)p_MsgHeader.m_1bTC, (unsigned)p_MsgHeader.m_1bRD, + (unsigned)p_MsgHeader.m_1bRA, (unsigned)p_MsgHeader.m_4bRCode, + (unsigned)p_MsgHeader.m_u16QDCount, + (unsigned)p_MsgHeader.m_u16ANCount, + (unsigned)p_MsgHeader.m_u16NSCount, + (unsigned)p_MsgHeader.m_u16ARCount););*/ + + uint8_t u8B1((p_MsgHeader.m_1bQR << 7) | (p_MsgHeader.m_4bOpcode << 3) | (p_MsgHeader.m_1bAA << 2) | (p_MsgHeader.m_1bTC << 1) | (p_MsgHeader.m_1bRD)); + uint8_t u8B2((p_MsgHeader.m_1bRA << 7) | (p_MsgHeader.m_3bZ << 4) | (p_MsgHeader.m_4bRCode)); + bool bResult = ((_write16(p_MsgHeader.m_u16ID, p_rSendParameter)) && + (_write8(u8B1, p_rSendParameter)) && + (_write8(u8B2, p_rSendParameter)) && + (_write16(p_MsgHeader.m_u16QDCount, p_rSendParameter)) && + (_write16(p_MsgHeader.m_u16ANCount, p_rSendParameter)) && + (_write16(p_MsgHeader.m_u16NSCount, p_rSendParameter)) && + (_write16(p_MsgHeader.m_u16ARCount, p_rSendParameter))); + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSMsgHeader: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_writeRRAttributes +*/ +bool MDNSResponder::_writeMDNSRRAttributes(const MDNSResponder::stcMDNS_RRAttributes& p_Attributes, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + + bool bResult = ((_write16(p_Attributes.m_u16Type, p_rSendParameter)) && + (_write16(p_Attributes.m_u16Class, p_rSendParameter))); + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSRRAttributes: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_writeMDNSRRDomain +*/ +bool MDNSResponder::_writeMDNSRRDomain(const MDNSResponder::stcMDNS_RRDomain& p_Domain, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + + bool bResult = ((_udpAppendBuffer((const unsigned char*)p_Domain.m_acName, p_Domain.m_u16NameLength)) && + (p_rSendParameter.shiftOffset(p_Domain.m_u16NameLength))); + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSRRDomain: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_writeMDNSHostDomain + + Write a host domain to the UDP output buffer. + If the domain record is part of the answer, the records length is + prepended (p_bPrependRDLength is set). + + A very simple form of name compression is applied here: + If the domain is written to the UDP output buffer, the write offset is stored + together with a domain id (the pointer) in a p_rSendParameter substructure (cache). + If the same domain (pointer) should be written to the UDP output later again, + the old offset is retrieved from the cache, marked as a compressed domain offset + and written to the output buffer. + +*/ +bool MDNSResponder::_writeMDNSHostDomain(const char* p_pcHostname, + bool p_bPrependRDLength, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + + // The 'skip-compression' version is handled in '_writeMDNSAnswer_SRV' + uint16_t u16CachedDomainOffset = p_rSendParameter.findCachedDomainOffset((const void*)p_pcHostname, false); + + stcMDNS_RRDomain hostDomain; + bool bResult = (u16CachedDomainOffset + // Found cached domain -> mark as compressed domain + ? ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset + ((!p_bPrependRDLength) || + (_write16(2, p_rSendParameter))) && // Length of 'Cxxx' + (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) + (_write8((uint8_t)(u16CachedDomainOffset & 0xFF), p_rSendParameter))) + // No cached domain -> add this domain to cache and write full domain name + : ((_buildDomainForHost(p_pcHostname, hostDomain)) && // eg. esp8266.local + ((!p_bPrependRDLength) || + (_write16(hostDomain.m_u16NameLength, p_rSendParameter))) && // RDLength (if needed) + (p_rSendParameter.addDomainCacheItem((const void*)p_pcHostname, false, p_rSendParameter.m_u16Offset)) && + (_writeMDNSRRDomain(hostDomain, p_rSendParameter)))); + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSHostDomain: FAILED!\n")); + }); + return bResult; + +} + +/* + MDNSResponder::_writeMDNSServiceDomain + + Write a service domain to the UDP output buffer. + If the domain record is part of the answer, the records length is + prepended (p_bPrependRDLength is set). + + A very simple form of name compression is applied here: see '_writeMDNSHostDomain' + The cache differentiates of course between service domains which includes + the instance name (p_bIncludeName is set) and thoose who don't. + +*/ +bool MDNSResponder::_writeMDNSServiceDomain(const MDNSResponder::stcMDNSService& p_Service, + bool p_bIncludeName, + bool p_bPrependRDLength, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + + // The 'skip-compression' version is handled in '_writeMDNSAnswer_SRV' + uint16_t u16CachedDomainOffset = p_rSendParameter.findCachedDomainOffset((const void*)&p_Service, p_bIncludeName); + + stcMDNS_RRDomain serviceDomain; + bool bResult = (u16CachedDomainOffset + // Found cached domain -> mark as compressed domain + ? ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset + ((!p_bPrependRDLength) || + (_write16(2, p_rSendParameter))) && // Lenght of 'Cxxx' + (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) + (_write8((uint8_t)(u16CachedDomainOffset & 0xFF), p_rSendParameter))) + // No cached domain -> add this domain to cache and write full domain name + : ((_buildDomainForService(p_Service, p_bIncludeName, serviceDomain)) && // eg. MyESP._http._tcp.local + ((!p_bPrependRDLength) || + (_write16(serviceDomain.m_u16NameLength, p_rSendParameter))) && // RDLength (if needed) + (p_rSendParameter.addDomainCacheItem((const void*)&p_Service, p_bIncludeName, p_rSendParameter.m_u16Offset)) && + (_writeMDNSRRDomain(serviceDomain, p_rSendParameter)))); + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSServiceDomain: FAILED!\n")); + }); + return bResult; + +} + +/* + MDNSResponder::_writeMDNSQuestion + + Write a MDNS question to the UDP output buffer + + QNAME (host/service domain, eg. esp8266.local) + QTYPE (16bit, eg. ANY) + QCLASS (16bit, eg. IN) + +*/ +bool MDNSResponder::_writeMDNSQuestion(MDNSResponder::stcMDNS_RRQuestion& p_Question, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSQuestion\n"));); + + bool bResult = ((_writeMDNSRRDomain(p_Question.m_Header.m_Domain, p_rSendParameter)) && + (_writeMDNSRRAttributes(p_Question.m_Header.m_Attributes, p_rSendParameter))); + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSQuestion: FAILED!\n")); + }); + return bResult; + +} + + +#ifdef MDNS_IP4_SUPPORT +/* + MDNSResponder::_writeMDNSAnswer_A + + Write a MDNS A answer to the UDP output buffer. + + NAME (var, host/service domain, eg. esp8266.local + TYPE (16bit, eg. A) + CLASS (16bit, eg. IN) + TTL (32bit, eg. 120) + RDLENGTH (16bit, eg 4) + RDATA (var, eg. 123.456.789.012) + + eg. esp8266.local A 0x8001 120 4 123.456.789.012 + Ref: http://www.zytrax.com/books/dns/ch8/a.html +*/ +bool MDNSResponder::_writeMDNSAnswer_A(IPAddress p_IPAddress, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_A (%s)\n"), p_IPAddress.toString().c_str());); + + stcMDNS_RRAttributes attributes(DNS_RRTYPE_A, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + const unsigned char aucIPAddress[MDNS_IP4_SIZE] = { p_IPAddress[0], p_IPAddress[1], p_IPAddress[2], p_IPAddress[3] }; + bool bResult = ((_writeMDNSHostDomain(m_pcHostname, false, p_rSendParameter)) && + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter)) && // TTL + (_write16(MDNS_IP4_SIZE, p_rSendParameter)) && // RDLength + (_udpAppendBuffer(aucIPAddress, MDNS_IP4_SIZE)) && // RData + (p_rSendParameter.shiftOffset(MDNS_IP4_SIZE))); + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_A: FAILED!\n")); + }); + return bResult; + +} + +/* + MDNSResponder::_writeMDNSAnswer_PTR_IP4 + + Write a MDNS reverse IP4 PTR answer to the UDP output buffer. + See: '_writeMDNSAnswer_A' + + eg. 012.789.456.123.in-addr.arpa PTR 0x8001 120 15 esp8266.local + Used while answering reverse IP4 questions +*/ +bool MDNSResponder::_writeMDNSAnswer_PTR_IP4(IPAddress p_IPAddress, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_IP4 (%s)\n"), p_IPAddress.toString().c_str());); + + stcMDNS_RRDomain reverseIP4Domain; + stcMDNS_RRAttributes attributes(DNS_RRTYPE_PTR, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + stcMDNS_RRDomain hostDomain; + bool bResult = ((_buildDomainForReverseIP4(p_IPAddress, reverseIP4Domain)) && // 012.789.456.123.in-addr.arpa + (_writeMDNSRRDomain(reverseIP4Domain, p_rSendParameter)) && + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter)) && // TTL + (_writeMDNSHostDomain(m_pcHostname, true, p_rSendParameter))); // RDLength & RData (host domain, eg. esp8266.local) + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_IP4: FAILED!\n")); + }); + return bResult; +} +#endif + +/* + MDNSResponder::_writeMDNSAnswer_PTR_TYPE + + Write a MDNS PTR answer to the UDP output buffer. + See: '_writeMDNSAnswer_A' + + PTR all-services -> service type + eg. _services._dns-sd._udp.local PTR 0x8001 5400 xx _http._tcp.local + http://www.zytrax.com/books/dns/ch8/ptr.html +*/ +bool MDNSResponder::_writeMDNSAnswer_PTR_TYPE(MDNSResponder::stcMDNSService& p_rService, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_TYPE\n"));); + + stcMDNS_RRDomain dnssdDomain; + stcMDNS_RRDomain serviceDomain; + stcMDNS_RRAttributes attributes(DNS_RRTYPE_PTR, DNS_RRCLASS_IN); // No cache flush! only INternet + bool bResult = ((_buildDomainForDNSSD(dnssdDomain)) && // _services._dns-sd._udp.local + (_writeMDNSRRDomain(dnssdDomain, p_rSendParameter)) && + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_SERVICE_TTL), p_rSendParameter)) && // TTL + (_writeMDNSServiceDomain(p_rService, false, true, p_rSendParameter))); // RDLength & RData (service domain, eg. _http._tcp.local) + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_TYPE: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_writeMDNSAnswer_PTR_NAME + + Write a MDNS PTR answer to the UDP output buffer. + See: '_writeMDNSAnswer_A' + + PTR service type -> service name + eg. _http.tcp.local PTR 0x8001 120 xx myESP._http._tcp.local + http://www.zytrax.com/books/dns/ch8/ptr.html +*/ +bool MDNSResponder::_writeMDNSAnswer_PTR_NAME(MDNSResponder::stcMDNSService& p_rService, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_NAME\n"));); + + stcMDNS_RRAttributes attributes(DNS_RRTYPE_PTR, DNS_RRCLASS_IN); // No cache flush! only INternet + bool bResult = ((_writeMDNSServiceDomain(p_rService, false, false, p_rSendParameter)) && // _http._tcp.local + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_SERVICE_TTL), p_rSendParameter)) && // TTL + (_writeMDNSServiceDomain(p_rService, true, true, p_rSendParameter))); // RDLength & RData (service domain, eg. MyESP._http._tcp.local) + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_NAME: FAILED!\n")); + }); + return bResult; +} + + +/* + MDNSResponder::_writeMDNSAnswer_TXT + + Write a MDNS TXT answer to the UDP output buffer. + See: '_writeMDNSAnswer_A' + + The TXT items in the RDATA block are 'length byte encoded': [len]vardata + + eg. myESP._http._tcp.local TXT 0x8001 120 4 c#=1 + http://www.zytrax.com/books/dns/ch8/txt.html +*/ +bool MDNSResponder::_writeMDNSAnswer_TXT(MDNSResponder::stcMDNSService& p_rService, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_TXT\n"));); + + bool bResult = false; + + stcMDNS_RRAttributes attributes(DNS_RRTYPE_TXT, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + + if ((_collectServiceTxts(p_rService)) && + (_writeMDNSServiceDomain(p_rService, true, false, p_rSendParameter)) && // MyESP._http._tcp.local + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_SERVICE_TTL), p_rSendParameter)) && // TTL + (_write16(p_rService.m_Txts.length(), p_rSendParameter))) // RDLength + { + + bResult = true; + // RData Txts + for (stcMDNSServiceTxt* pTxt = p_rService.m_Txts.m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) + { + unsigned char ucLengthByte = pTxt->length(); + bResult = ((_udpAppendBuffer((unsigned char*)&ucLengthByte, sizeof(ucLengthByte))) && // Length + (p_rSendParameter.shiftOffset(sizeof(ucLengthByte))) && + ((size_t)os_strlen(pTxt->m_pcKey) == m_pUDPContext->append(pTxt->m_pcKey, os_strlen(pTxt->m_pcKey))) && // Key + (p_rSendParameter.shiftOffset((size_t)os_strlen(pTxt->m_pcKey))) && + (1 == m_pUDPContext->append("=", 1)) && // = + (p_rSendParameter.shiftOffset(1)) && + ((!pTxt->m_pcValue) || + (((size_t)os_strlen(pTxt->m_pcValue) == m_pUDPContext->append(pTxt->m_pcValue, os_strlen(pTxt->m_pcValue))) && // Value + (p_rSendParameter.shiftOffset((size_t)os_strlen(pTxt->m_pcValue)))))); + + DEBUG_EX_ERR(if (!bResult) + { + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_TXT: FAILED to write %sTxt %s=%s!\n"), (pTxt->m_bTemp ? "temp. " : ""), (pTxt->m_pcKey ? : "?"), (pTxt->m_pcValue ? : "?")); + }); + } + } + _releaseTempServiceTxts(p_rService); + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_TXT: FAILED!\n")); + }); + return bResult; +} + +#ifdef MDNS_IP6_SUPPORT +/* + MDNSResponder::_writeMDNSAnswer_AAAA + + Write a MDNS AAAA answer to the UDP output buffer. + See: '_writeMDNSAnswer_A' + + eg. esp8266.local AAAA 0x8001 120 16 xxxx::xx + http://www.zytrax.com/books/dns/ch8/aaaa.html +*/ +bool MDNSResponder::_writeMDNSAnswer_AAAA(IPAddress p_IPAddress, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_AAAA\n"));); + + stcMDNS_RRAttributes attributes(DNS_RRTYPE_AAAA, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + bool bResult = ((_writeMDNSHostDomain(m_pcHostname, false, p_rSendParameter)) && // esp8266.local + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter)) && // TTL + (_write16(MDNS_IP6_SIZE, p_rSendParameter)) && // RDLength + (false /*TODO: IP6 version of: _udpAppendBuffer((uint32_t)p_IPAddress, MDNS_IP4_SIZE)*/)); // RData + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_AAAA: FAILED!\n")); + }); + return bResult; +} + +/* + MDNSResponder::_writeMDNSAnswer_PTR_IP6 + + Write a MDNS reverse IP6 PTR answer to the UDP output buffer. + See: '_writeMDNSAnswer_A' + + eg. xxxx::xx.in6.arpa PTR 0x8001 120 15 esp8266.local + Used while answering reverse IP6 questions +*/ +bool MDNSResponder::_writeMDNSAnswer_PTR_IP6(IPAddress p_IPAddress, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_IP6\n"));); + + stcMDNS_RRDomain reverseIP6Domain; + stcMDNS_RRAttributes attributes(DNS_RRTYPE_PTR, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + bool bResult = ((_buildDomainForReverseIP6(p_IPAddress, reverseIP6Domain)) && // xxxx::xx.ip6.arpa + (_writeMDNSRRDomain(reverseIP6Domain, p_rSendParameter)) && + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter)) && // TTL + (_writeMDNSHostDomain(m_pcHostname, true, p_rSendParameter))); // RDLength & RData (host domain, eg. esp8266.local) + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_IP6: FAILED!\n")); + }); + return bResult; +} +#endif + +/* + MDNSResponder::_writeMDNSAnswer_SRV + + eg. MyESP._http.tcp.local SRV 0x8001 120 0 0 60068 esp8266.local + http://www.zytrax.com/books/dns/ch8/srv.html ???? Include instance name ???? +*/ +bool MDNSResponder::_writeMDNSAnswer_SRV(MDNSResponder::stcMDNSService& p_rService, + MDNSResponder::stcMDNSSendParameter& p_rSendParameter) +{ + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_SRV\n"));); + + uint16_t u16CachedDomainOffset = (p_rSendParameter.m_bLegacyQuery + ? 0 + : p_rSendParameter.findCachedDomainOffset((const void*)m_pcHostname, false)); + + stcMDNS_RRAttributes attributes(DNS_RRTYPE_SRV, + ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet + stcMDNS_RRDomain hostDomain; + bool bResult = ((_writeMDNSServiceDomain(p_rService, true, false, p_rSendParameter)) && // MyESP._http._tcp.local + (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS + (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_SERVICE_TTL), p_rSendParameter)) && // TTL + (!u16CachedDomainOffset + // No cache for domain name (or no compression allowed) + ? ((_buildDomainForHost(m_pcHostname, hostDomain)) && + (_write16((sizeof(uint16_t /*Prio*/) + // RDLength + sizeof(uint16_t /*Weight*/) + + sizeof(uint16_t /*Port*/) + + hostDomain.m_u16NameLength), p_rSendParameter)) && // Domain length + (_write16(MDNS_SRV_PRIORITY, p_rSendParameter)) && // Priority + (_write16(MDNS_SRV_WEIGHT, p_rSendParameter)) && // Weight + (_write16(p_rService.m_u16Port, p_rSendParameter)) && // Port + (p_rSendParameter.addDomainCacheItem((const void*)m_pcHostname, false, p_rSendParameter.m_u16Offset)) && + (_writeMDNSRRDomain(hostDomain, p_rSendParameter))) // Host, eg. esp8266.local + // Cache available for domain + : ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset + (_write16((sizeof(uint16_t /*Prio*/) + // RDLength + sizeof(uint16_t /*Weight*/) + + sizeof(uint16_t /*Port*/) + + 2), p_rSendParameter)) && // Length of 'C0xx' + (_write16(MDNS_SRV_PRIORITY, p_rSendParameter)) && // Priority + (_write16(MDNS_SRV_WEIGHT, p_rSendParameter)) && // Weight + (_write16(p_rService.m_u16Port, p_rSendParameter)) && // Port + (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) + (_write8((uint8_t)u16CachedDomainOffset, p_rSendParameter))))); // Offset + + DEBUG_EX_ERR(if (!bResult) +{ + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_SRV: FAILED!\n")); + }); + return bResult; +} + +} // namespace MDNSImplementation + +} // namespace esp8266 + + + + + + diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_lwIPdefs.h b/libraries/ESP8266mDNS/src/LEAmDNS_lwIPdefs.h new file mode 100644 index 0000000000..a3bcc4b370 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS_lwIPdefs.h @@ -0,0 +1,44 @@ +/* + LEAmDNS_Priv.h + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#ifndef MDNS_LWIPDEFS_H +#define MDNS_LWIPDEFS_H + +#include <lwip/init.h> +#if LWIP_VERSION_MAJOR == 1 + +#include <lwip/mdns.h> // DNS_RRTYPE_xxx + +// cherry pick from lwip1 dns.c/mdns.c source files: +#define DNS_MQUERY_PORT 5353 +#define DNS_MQUERY_IPV4_GROUP_INIT IPAddress(224,0,0,251) /* resolver1.opendns.com */ +#define DNS_RRCLASS_ANY 255 /* any class */ + +#else // lwIP > 1 + +#include <lwip/prot/dns.h> // DNS_RRTYPE_xxx, DNS_MQUERY_PORT + +#endif + +#endif // MDNS_LWIPDEFS_H From 0e692c3993ac222cd41bc2f33df63350ed2245ec Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 8 May 2020 21:45:55 +0200 Subject: [PATCH 007/152] add enableArduino() into LEAmDNSv2 --- .../OLDmDNS/ESP8266mDNS_Legacy.cpp | 1523 ---------- .../ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.h | 166 -- libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.cpp | 1381 --------- libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.h | 1461 ---------- .../ESP8266mDNS/OLDmDNS/LEAmDNS_Control.cpp | 2134 -------------- .../ESP8266mDNS/OLDmDNS/LEAmDNS_Helpers.cpp | 850 ------ libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Priv.h | 182 -- .../ESP8266mDNS/OLDmDNS/LEAmDNS_Structs.cpp | 2476 ----------------- .../ESP8266mDNS/OLDmDNS/LEAmDNS_Transfer.cpp | 1779 ------------ .../ESP8266mDNS/OLDmDNS/LEAmDNS_lwIPdefs.h | 44 - ...-mDNS-SPIFFS.ino => OTA-mDNS-LittleFS.ino} | 0 libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 30 + libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 2 + 13 files changed, 32 insertions(+), 11996 deletions(-) delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.cpp delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.h delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.cpp delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.h delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Control.cpp delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Helpers.cpp delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Priv.h delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Structs.cpp delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Transfer.cpp delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_lwIPdefs.h rename libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/{OTA-mDNS-SPIFFS.ino => OTA-mDNS-LittleFS.ino} (100%) diff --git a/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.cpp b/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.cpp deleted file mode 100644 index 8791195523..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.cpp +++ /dev/null @@ -1,1523 +0,0 @@ -/* - - ESP8266 Multicast DNS (port of CC3000 Multicast DNS library) - Version 1.1 - Copyright (c) 2013 Tony DiCola (tony@tonydicola.com) - ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com) - MDNS-SD Suport 2015 Hristo Gochkov - Extended MDNS-SD support 2016 Lars Englund (lars.englund@gmail.com) - - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -// Important RFC's for reference: -// - DNS request and response: http://www.ietf.org/rfc/rfc1035.txt -// - Multicast DNS: http://www.ietf.org/rfc/rfc6762.txt -// - MDNS-SD: https://tools.ietf.org/html/rfc6763 - -#ifndef LWIP_OPEN_SRC -#define LWIP_OPEN_SRC -#endif - -#include "ESP8266mDNS.h" -#include <functional> - -#include "debug.h" - -extern "C" { -#include "osapi.h" -#include "ets_sys.h" -#include "user_interface.h" -} - -#include "WiFiUdp.h" -#include "lwip/opt.h" -#include "lwip/udp.h" -#include "lwip/inet.h" -#include "lwip/igmp.h" -#include "lwip/mem.h" -#include "include/UdpContext.h" - - - -namespace Legacy_MDNSResponder -{ - - -#ifdef DEBUG_ESP_MDNS -#define DEBUG_ESP_MDNS_ERR -#define DEBUG_ESP_MDNS_TX -#define DEBUG_ESP_MDNS_RX -#endif - -#define MDNS_NAME_REF 0xC000 - -#define MDNS_TYPE_AAAA 0x001C -#define MDNS_TYPE_A 0x0001 -#define MDNS_TYPE_PTR 0x000C -#define MDNS_TYPE_SRV 0x0021 -#define MDNS_TYPE_TXT 0x0010 - -#define MDNS_CLASS_IN 0x0001 -#define MDNS_CLASS_IN_FLUSH_CACHE 0x8001 - -#define MDNS_ANSWERS_ALL 0x0F -#define MDNS_ANSWER_PTR 0x08 -#define MDNS_ANSWER_TXT 0x04 -#define MDNS_ANSWER_SRV 0x02 -#define MDNS_ANSWER_A 0x01 - -#define _conn_read32() (((uint32_t)_conn->read() << 24) | ((uint32_t)_conn->read() << 16) | ((uint32_t)_conn->read() << 8) | _conn->read()) -#define _conn_read16() (((uint16_t)_conn->read() << 8) | _conn->read()) -#define _conn_read8() _conn->read() -#define _conn_readS(b,l) _conn->read((char*)(b),l); - -static const IPAddress MDNS_MULTICAST_ADDR(224, 0, 0, 251); -static const int MDNS_MULTICAST_TTL = 1; -static const int MDNS_PORT = 5353; - -struct MDNSService -{ - MDNSService* _next; - char _name[32]; - char _proto[4]; - uint16_t _port; - uint16_t _txtLen; // length of all txts - struct MDNSTxt * _txts; -}; - -struct MDNSTxt -{ - MDNSTxt * _next; - String _txt; -}; - -struct MDNSAnswer -{ - MDNSAnswer* next; - uint8_t ip[4]; - uint16_t port; - char *hostname; -}; - -struct MDNSQuery -{ - char _service[32]; - char _proto[4]; -}; - - -MDNSResponder::MDNSResponder() : _conn(0) -{ - _services = 0; - _instanceName = ""; - _answers = 0; - _query = 0; - _newQuery = false; - _waitingForAnswers = false; -} -MDNSResponder::~MDNSResponder() -{ - if (_query != 0) - { - os_free(_query); - _query = 0; - } - - // Clear answer list - MDNSAnswer *answer; - int numAnswers = _getNumAnswers(); - for (int n = numAnswers - 1; n >= 0; n--) - { - answer = _getAnswerFromIdx(n); - os_free(answer->hostname); - os_free(answer); - answer = 0; - } - _answers = 0; - - if (_conn) - { - _conn->unref(); - } -} - -bool MDNSResponder::begin(const char* hostname) -{ - size_t n = strlen(hostname); - if (n > 63) // max size for a single label. - { - return false; - } - - // Copy in hostname characters as lowercase - _hostName = hostname; - _hostName.toLowerCase(); - - // If instance name is not already set copy hostname to instance name - if (_instanceName.equals("")) - { - _instanceName = hostname; - } - - _gotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP & event) - { - (void) event; - _restart(); - }); - - _disconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected & event) - { - (void) event; - _restart(); - }); - - return _listen(); -} - -void MDNSResponder::notifyAPChange() -{ - _restart(); -} - -void MDNSResponder::_restart() -{ - if (_conn) - { - _conn->unref(); - _conn = nullptr; - } - _listen(); -} - -bool MDNSResponder::_listen() -{ - // Open the MDNS socket if it isn't already open. - if (!_conn) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.println("MDNS listening"); -#endif - - IPAddress mdns(MDNS_MULTICAST_ADDR); - - if (igmp_joingroup(IP4_ADDR_ANY4, mdns) != ERR_OK) - { - return false; - } - - _conn = new UdpContext; - _conn->ref(); - - if (!_conn->listen(IP_ADDR_ANY, MDNS_PORT)) - { - return false; - } - _conn->setMulticastTTL(MDNS_MULTICAST_TTL); - _conn->onRx(std::bind(&MDNSResponder::update, this)); - _conn->connect(mdns, MDNS_PORT); - } - return true; -} - -void MDNSResponder::update() -{ - if (!_conn || !_conn->next()) - { - return; - } - _parsePacket(); -} - - -void MDNSResponder::setInstanceName(String name) -{ - if (name.length() > 63) - { - return; - } - _instanceName = name; -} - - -bool MDNSResponder::addServiceTxt(char *name, char *proto, char *key, char *value) -{ - MDNSService* servicePtr; - - uint8_t txtLen = os_strlen(key) + os_strlen(value) + 1; // Add one for equals sign - txtLen += 1; //accounts for length byte added when building the txt responce - //Find the service - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - //Checking Service names - if (strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) - { - //found a service name match - if (servicePtr->_txtLen + txtLen > 1300) - { - return false; //max txt record size - } - MDNSTxt *newtxt = new MDNSTxt; - newtxt->_txt = String(key) + '=' + String(value); - newtxt->_next = 0; - if (servicePtr->_txts == 0) //no services have been added - { - //Adding First TXT to service - servicePtr->_txts = newtxt; - servicePtr->_txtLen += txtLen; - return true; - } - else - { - MDNSTxt * txtPtr = servicePtr->_txts; - while (txtPtr->_next != 0) - { - txtPtr = txtPtr->_next; - } - //adding another TXT to service - txtPtr->_next = newtxt; - servicePtr->_txtLen += txtLen; - return true; - } - } - } - return false; -} - -void MDNSResponder::addService(char *name, char *proto, uint16_t port) -{ - if (_getServicePort(name, proto) != 0) - { - return; - } - if (os_strlen(name) > 32 || os_strlen(proto) != 3) - { - return; //bad arguments - } - struct MDNSService *srv = (struct MDNSService*)(os_malloc(sizeof(struct MDNSService))); - os_strcpy(srv->_name, name); - os_strcpy(srv->_proto, proto); - srv->_port = port; - srv->_next = 0; - srv->_txts = 0; - srv->_txtLen = 0; - - if (_services == 0) - { - _services = srv; - } - else - { - MDNSService* servicePtr = _services; - while (servicePtr->_next != 0) - { - servicePtr = servicePtr->_next; - } - servicePtr->_next = srv; - } - -} - -int MDNSResponder::queryService(char *service, char *proto) -{ -#ifdef DEBUG_ESP_MDNS_TX - DEBUG_ESP_PORT.printf("queryService %s %s\n", service, proto); -#endif - while (_answers != 0) - { - MDNSAnswer *currAnswer = _answers; - _answers = _answers->next; - os_free(currAnswer->hostname); - os_free(currAnswer); - currAnswer = 0; - } - if (_query != 0) - { - os_free(_query); - _query = 0; - } - _query = (struct MDNSQuery*)(os_malloc(sizeof(struct MDNSQuery))); - os_strcpy(_query->_service, service); - os_strcpy(_query->_proto, proto); - _newQuery = true; - - char underscore[] = "_"; - - // build service name with _ - char serviceName[os_strlen(service) + 2]; - os_strcpy(serviceName, underscore); - os_strcat(serviceName, service); - size_t serviceNameLen = os_strlen(serviceName); - - //build proto name with _ - char protoName[5]; - os_strcpy(protoName, underscore); - os_strcat(protoName, proto); - size_t protoNameLen = 4; - - //local string - char localName[] = "local"; - size_t localNameLen = 5; - - //terminator - char terminator[] = "\0"; - - // Only supports sending one PTR query - uint8_t questionCount = 1; - - _waitingForAnswers = true; - for (int itfn = 0; itfn < 2; itfn++) - { - struct ip_info ip_info; - - wifi_get_ip_info((!itfn) ? SOFTAP_IF : STATION_IF, &ip_info); - if (!ip_info.ip.addr) - { - continue; - } - _conn->setMulticastInterface(IPAddress(ip_info.ip.addr)); - - // Write the header - _conn->flush(); - uint8_t head[12] = - { - 0x00, 0x00, //ID = 0 - 0x00, 0x00, //Flags = response + authoritative answer - 0x00, questionCount, //Question count - 0x00, 0x00, //Answer count - 0x00, 0x00, //Name server records - 0x00, 0x00 //Additional records - }; - _conn->append(reinterpret_cast<const char*>(head), 12); - - // Only supports sending one PTR query - // Send the Name field (eg. "_http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // lenght of "_" + service - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_" + service - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // lenght of "_" + proto - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_" + proto - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // lenght of "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type and class - uint8_t ptrAttrs[4] = - { - 0x00, 0x0c, //PTR record query - 0x00, 0x01 //Class IN - }; - _conn->append(reinterpret_cast<const char*>(ptrAttrs), 4); - _conn->send(); - } - -#ifdef DEBUG_ESP_MDNS_TX - DEBUG_ESP_PORT.println("Waiting for answers.."); -#endif - delay(1000); - - _waitingForAnswers = false; - - return _getNumAnswers(); -} - -String MDNSResponder::hostname(int idx) -{ - MDNSAnswer *answer = _getAnswerFromIdx(idx); - if (answer == 0) - { - return String(); - } - return answer->hostname; -} - -IPAddress MDNSResponder::IP(int idx) -{ - MDNSAnswer *answer = _getAnswerFromIdx(idx); - if (answer == 0) - { - return IPAddress(); - } - return IPAddress(answer->ip); -} - -uint16_t MDNSResponder::port(int idx) -{ - MDNSAnswer *answer = _getAnswerFromIdx(idx); - if (answer == 0) - { - return 0; - } - return answer->port; -} - -MDNSAnswer* MDNSResponder::_getAnswerFromIdx(int idx) -{ - MDNSAnswer *answer = _answers; - while (answer != 0 && idx-- > 0) - { - answer = answer->next; - } - if (idx > 0) - { - return 0; - } - return answer; -} - -int MDNSResponder::_getNumAnswers() -{ - int numAnswers = 0; - MDNSAnswer *answer = _answers; - while (answer != 0) - { - numAnswers++; - answer = answer->next; - } - return numAnswers; -} - -MDNSTxt * MDNSResponder::_getServiceTxt(char *name, char *proto) -{ - MDNSService* servicePtr; - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - if (servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) - { - if (servicePtr->_txts == 0) - { - return nullptr; - } - return servicePtr->_txts; - } - } - return nullptr; -} - -uint16_t MDNSResponder::_getServiceTxtLen(char *name, char *proto) -{ - MDNSService* servicePtr; - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - if (servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) - { - if (servicePtr->_txts == 0) - { - return false; - } - return servicePtr->_txtLen; - } - } - return 0; -} - -uint16_t MDNSResponder::_getServicePort(char *name, char *proto) -{ - MDNSService* servicePtr; - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - if (servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) - { - return servicePtr->_port; - } - } - return 0; -} - -IPAddress MDNSResponder::_getRequestMulticastInterface() -{ - struct ip_info ip_info; - bool match_ap = false; - if (wifi_get_opmode() & SOFTAP_MODE) - { - const IPAddress& remote_ip = _conn->getRemoteAddress(); - wifi_get_ip_info(SOFTAP_IF, &ip_info); - IPAddress infoIp(ip_info.ip); - IPAddress infoMask(ip_info.netmask); - if (ip_info.ip.addr && ip_addr_netcmp((const ip_addr_t*)remote_ip, (const ip_addr_t*)infoIp, ip_2_ip4((const ip_addr_t*)infoMask))) - { - match_ap = true; - } - } - if (!match_ap) - { - wifi_get_ip_info(STATION_IF, &ip_info); - } - return IPAddress(ip_info.ip.addr); -} - -void MDNSResponder::_parsePacket() -{ - int i; - char tmp; - bool serviceParsed = false; - bool protoParsed = false; - bool localParsed = false; - - char hostName[255]; - uint8_t hostNameLen; - - char serviceName[32]; - uint8_t serviceNameLen; - uint16_t servicePort = 0; - - char protoName[32]; - protoName[0] = 0; - uint8_t protoNameLen = 0; - - uint16_t packetHeader[6]; - - for (i = 0; i < 6; i++) - { - packetHeader[i] = _conn_read16(); - } - - if ((packetHeader[1] & 0x8000) != 0) // Read answers - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("Reading answers RX: REQ, ID:%u, Q:%u, A:%u, NS:%u, ADD:%u\n", packetHeader[0], packetHeader[2], packetHeader[3], packetHeader[4], packetHeader[5]); -#endif - - if (!_waitingForAnswers) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.println("Not expecting any answers right now, returning"); -#endif - _conn->flush(); - return; - } - - int numAnswers = packetHeader[3] + packetHeader[5]; - // Assume that the PTR answer always comes first and that it is always accompanied by a TXT, SRV, AAAA (optional) and A answer in the same packet. - if (numAnswers < 4) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("Expected a packet with 4 or more answers, got %u\n", numAnswers); -#endif - _conn->flush(); - return; - } - - uint8_t tmp8; - uint16_t answerPort = 0; - uint8_t answerIp[4] = { 0, 0, 0, 0 }; - char answerHostName[255]; - bool serviceMatch = false; - MDNSAnswer *answer; - uint8_t partsCollected = 0; - uint8_t stringsRead = 0; - - answerHostName[0] = '\0'; - - // Clear answer list - if (_newQuery) - { - int oldAnswers = _getNumAnswers(); - for (int n = oldAnswers - 1; n >= 0; n--) - { - answer = _getAnswerFromIdx(n); - os_free(answer->hostname); - os_free(answer); - answer = 0; - } - _answers = 0; - _newQuery = false; - } - - while (numAnswers--) - { - // Read name - stringsRead = 0; - size_t last_bufferpos = 0; - do - { - tmp8 = _conn_read8(); - if (tmp8 == 0x00) // End of name - { - break; - } - if (tmp8 & 0xC0) // Compressed pointer - { - uint16_t offset = ((((uint16_t)tmp8) & ~0xC0) << 8) | _conn_read8(); - if (_conn->isValidOffset(offset)) - { - if (0 == last_bufferpos) - { - last_bufferpos = _conn->tell(); - } -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Compressed pointer, jumping from "); - DEBUG_ESP_PORT.print(last_bufferpos); - DEBUG_ESP_PORT.print(" to "); - DEBUG_ESP_PORT.println(offset); -#endif - _conn->seek(offset); - tmp8 = _conn_read8(); - } - else - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Skipping malformed compressed pointer"); -#endif - tmp8 = _conn_read8(); - break; - } - } - if (stringsRead > 3) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.println("failed to read the response name"); -#endif - _conn->flush(); - return; - } - _conn_readS(serviceName, tmp8); - serviceName[tmp8] = '\0'; -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf(" %d ", tmp8); - for (int n = 0; n < tmp8; n++) - { - DEBUG_ESP_PORT.printf("%c", serviceName[n]); - } - DEBUG_ESP_PORT.println(); -#endif - if (serviceName[0] == '_') - { - if (strcmp(&serviceName[1], _query->_service) == 0) - { - serviceMatch = true; -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("found matching service: %s\n", _query->_service); -#endif - } - } - stringsRead++; - } while (true); - if (last_bufferpos > 0) - { - _conn->seek(last_bufferpos); -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Compressed pointer, jumping back to "); - DEBUG_ESP_PORT.println(last_bufferpos); -#endif - } - - uint16_t answerType = _conn_read16(); // Read type - uint16_t answerClass = _conn_read16(); // Read class - uint32_t answerTtl = _conn_read32(); // Read ttl - uint16_t answerRdlength = _conn_read16(); // Read rdlength - - (void) answerClass; - (void) answerTtl; - - if (answerRdlength > 255) - { - if (answerType == MDNS_TYPE_TXT && answerRdlength < 1460) - { - while (--answerRdlength) - { - _conn->read(); - } - } - else - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("Data len too long! %u\n", answerRdlength); -#endif - _conn->flush(); - return; - } - } - -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("type: %04x rdlength: %d\n", answerType, answerRdlength); -#endif - - if (answerType == MDNS_TYPE_PTR) - { - partsCollected |= 0x01; - _conn_readS(hostName, answerRdlength); // Read rdata - if (hostName[answerRdlength - 2] & 0xc0) - { - memcpy(answerHostName, hostName + 1, answerRdlength - 3); - answerHostName[answerRdlength - 3] = '\0'; - } -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("PTR %d ", answerRdlength); - for (int n = 0; n < answerRdlength; n++) - { - DEBUG_ESP_PORT.printf("%c", hostName[n]); - } - DEBUG_ESP_PORT.println(); -#endif - } - - else if (answerType == MDNS_TYPE_TXT) - { - partsCollected |= 0x02; - _conn_readS(hostName, answerRdlength); // Read rdata -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("TXT %d ", answerRdlength); - for (int n = 0; n < answerRdlength; n++) - { - DEBUG_ESP_PORT.printf("%c", hostName[n]); - } - DEBUG_ESP_PORT.println(); -#endif - } - - else if (answerType == MDNS_TYPE_SRV) - { - partsCollected |= 0x04; - uint16_t answerPrio = _conn_read16(); // Read priority - uint16_t answerWeight = _conn_read16(); // Read weight - answerPort = _conn_read16(); // Read port - last_bufferpos = 0; - - (void) answerPrio; - (void) answerWeight; - - // Read hostname - tmp8 = _conn_read8(); - if (tmp8 & 0xC0) // Compressed pointer - { - uint16_t offset = ((((uint16_t)tmp8) & ~0xC0) << 8) | _conn_read8(); - if (_conn->isValidOffset(offset)) - { - last_bufferpos = _conn->tell(); -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Compressed pointer, jumping from "); - DEBUG_ESP_PORT.print(last_bufferpos); - DEBUG_ESP_PORT.print(" to "); - DEBUG_ESP_PORT.println(offset); -#endif - _conn->seek(offset); - tmp8 = _conn_read8(); - } - else - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Skipping malformed compressed pointer"); -#endif - tmp8 = _conn_read8(); - break; - } - } - _conn_readS(answerHostName, tmp8); - answerHostName[tmp8] = '\0'; -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("SRV %d ", tmp8); - for (int n = 0; n < tmp8; n++) - { - DEBUG_ESP_PORT.printf("%02x ", answerHostName[n]); - } - DEBUG_ESP_PORT.printf("\n%s\n", answerHostName); -#endif - if (last_bufferpos > 0) - { - _conn->seek(last_bufferpos); - tmp8 = 2; // Size of compression octets -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Compressed pointer, jumping back to "); - DEBUG_ESP_PORT.println(last_bufferpos); -#endif - } - if (answerRdlength - (6 + 1 + tmp8) > 0) // Skip any remaining rdata - { - _conn_readS(hostName, answerRdlength - (6 + 1 + tmp8)); - } - } - - else if (answerType == MDNS_TYPE_A) - { - partsCollected |= 0x08; - for (int i = 0; i < 4; i++) - { - answerIp[i] = _conn_read8(); - } - } - else - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("Ignoring unsupported type %02x\n", tmp8); -#endif - for (int n = 0; n < answerRdlength; n++) - { - (void)_conn_read8(); - } - } - - if ((partsCollected == 0x0F) && serviceMatch) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.println("All answers parsed, adding to _answers list.."); -#endif - // Add new answer to answer list - if (_answers == 0) - { - _answers = (struct MDNSAnswer*)(os_malloc(sizeof(struct MDNSAnswer))); - answer = _answers; - } - else - { - answer = _answers; - while (answer->next != 0) - { - answer = answer->next; - } - answer->next = (struct MDNSAnswer*)(os_malloc(sizeof(struct MDNSAnswer))); - answer = answer->next; - } - answer->next = 0; - answer->hostname = 0; - - // Populate new answer - answer->port = answerPort; - for (int i = 0; i < 4; i++) - { - answer->ip[i] = answerIp[i]; - } - answer->hostname = (char *)os_malloc(strlen(answerHostName) + 1); - os_strcpy(answer->hostname, answerHostName); - _conn->flush(); - return; - } - } - - _conn->flush(); - return; - } - - // PARSE REQUEST NAME - - hostNameLen = _conn_read8() % 255; - _conn_readS(hostName, hostNameLen); - hostName[hostNameLen] = '\0'; - - if (hostName[0] == '_') - { - serviceParsed = true; - memcpy(serviceName, hostName + 1, hostNameLen); - serviceNameLen = hostNameLen - 1; - hostNameLen = 0; - } - - if (hostNameLen > 0 && !_hostName.equals(hostName) && !_instanceName.equals(hostName)) - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_NO_HOST: %s\n", hostName); - DEBUG_ESP_PORT.printf("hostname: %s\n", _hostName.c_str()); - DEBUG_ESP_PORT.printf("instance: %s\n", _instanceName.c_str()); -#endif - _conn->flush(); - return; - } - - if (!serviceParsed) - { - serviceNameLen = _conn_read8() % 255; - _conn_readS(serviceName, serviceNameLen); - serviceName[serviceNameLen] = '\0'; - - if (serviceName[0] == '_') - { - memmove(serviceName, serviceName + 1, serviceNameLen); - serviceNameLen--; - serviceParsed = true; - } - else if (serviceNameLen == 5 && strcmp("local", serviceName) == 0) - { - tmp = _conn_read8(); - if (tmp == 0) - { - serviceParsed = true; - serviceNameLen = 0; - protoParsed = true; - protoNameLen = 0; - localParsed = true; - } - else - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_FQDN: %s\n", serviceName); -#endif - _conn->flush(); - return; - } - } - else - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_SERVICE: %s\n", serviceName); -#endif - _conn->flush(); - return; - } - } - - if (!protoParsed) - { - protoNameLen = _conn_read8() % 255; - _conn_readS(protoName, protoNameLen); - protoName[protoNameLen] = '\0'; - if (protoNameLen == 4 && protoName[0] == '_') - { - memmove(protoName, protoName + 1, protoNameLen); - protoNameLen--; - protoParsed = true; - } - else if (strcmp("services", serviceName) == 0 && strcmp("_dns-sd", protoName) == 0) - { - _conn->flush(); - IPAddress interface = _getRequestMulticastInterface(); - _replyToTypeEnumRequest(interface); - return; - } - else - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_PROTO: %s\n", protoName); -#endif - _conn->flush(); - return; - } - } - - if (!localParsed) - { - char localName[32]; - uint8_t localNameLen = _conn_read8() % 31; - _conn_readS(localName, localNameLen); - localName[localNameLen] = '\0'; - tmp = _conn_read8(); - if (localNameLen == 5 && strcmp("local", localName) == 0 && tmp == 0) - { - localParsed = true; - } - else - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_FQDN: %s\n", localName); -#endif - _conn->flush(); - return; - } - } - - if (serviceNameLen > 0 && protoNameLen > 0) - { - servicePort = _getServicePort(serviceName, protoName); - if (servicePort == 0) - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_NO_SERVICE: %s\n", serviceName); -#endif - _conn->flush(); - return; - } - } - else if (serviceNameLen > 0 || protoNameLen > 0) - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_SERVICE_PROTO: %s\n", serviceName); -#endif - _conn->flush(); - return; - } - - // RESPOND - -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("RX: REQ, ID:%u, Q:%u, A:%u, NS:%u, ADD:%u\n", packetHeader[0], packetHeader[2], packetHeader[3], packetHeader[4], packetHeader[5]); -#endif - - uint16_t currentType; - uint16_t currentClass; - - int numQuestions = packetHeader[2]; - if (numQuestions > 4) - { - numQuestions = 4; - } - uint16_t questions[4]; - int question = 0; - - while (numQuestions--) - { - currentType = _conn_read16(); - if (currentType & MDNS_NAME_REF) //new header handle it better! - { - currentType = _conn_read16(); - } - currentClass = _conn_read16(); - if (currentClass & MDNS_CLASS_IN) - { - questions[question++] = currentType; - } - - if (numQuestions > 0) - { - if (_conn_read16() != 0xC00C) //new question but for another host/service - { - _conn->flush(); - numQuestions = 0; - } - } - -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("REQ: "); - if (hostNameLen > 0) - { - DEBUG_ESP_PORT.printf("%s.", hostName); - } - if (serviceNameLen > 0) - { - DEBUG_ESP_PORT.printf("_%s.", serviceName); - } - if (protoNameLen > 0) - { - DEBUG_ESP_PORT.printf("_%s.", protoName); - } - DEBUG_ESP_PORT.printf("local. "); - - if (currentType == MDNS_TYPE_AAAA) - { - DEBUG_ESP_PORT.printf(" AAAA "); - } - else if (currentType == MDNS_TYPE_A) - { - DEBUG_ESP_PORT.printf(" A "); - } - else if (currentType == MDNS_TYPE_PTR) - { - DEBUG_ESP_PORT.printf(" PTR "); - } - else if (currentType == MDNS_TYPE_SRV) - { - DEBUG_ESP_PORT.printf(" SRV "); - } - else if (currentType == MDNS_TYPE_TXT) - { - DEBUG_ESP_PORT.printf(" TXT "); - } - else - { - DEBUG_ESP_PORT.printf(" 0x%04X ", currentType); - } - - if (currentClass == MDNS_CLASS_IN) - { - DEBUG_ESP_PORT.printf(" IN "); - } - else if (currentClass == MDNS_CLASS_IN_FLUSH_CACHE) - { - DEBUG_ESP_PORT.printf(" IN[F] "); - } - else - { - DEBUG_ESP_PORT.printf(" 0x%04X ", currentClass); - } - - DEBUG_ESP_PORT.printf("\n"); -#endif - } - uint8_t questionMask = 0; - uint8_t responseMask = 0; - for (i = 0; i < question; i++) - { - if (questions[i] == MDNS_TYPE_A) - { - questionMask |= 0x1; - responseMask |= 0x1; - } - else if (questions[i] == MDNS_TYPE_SRV) - { - questionMask |= 0x2; - responseMask |= 0x3; - } - else if (questions[i] == MDNS_TYPE_TXT) - { - questionMask |= 0x4; - responseMask |= 0x4; - } - else if (questions[i] == MDNS_TYPE_PTR) - { - questionMask |= 0x8; - responseMask |= 0xF; - } - } - - IPAddress interface = _getRequestMulticastInterface(); - return _replyToInstanceRequest(questionMask, responseMask, serviceName, protoName, servicePort, interface); -} - - -/** - STRINGIZE -*/ -#ifndef STRINGIZE -#define STRINGIZE(x) #x -#endif -#ifndef STRINGIZE_VALUE_OF -#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) -#endif - - -void MDNSResponder::enableArduino(uint16_t port, bool auth) -{ - - addService("arduino", "tcp", port); - addServiceTxt("arduino", "tcp", "tcp_check", "no"); - addServiceTxt("arduino", "tcp", "ssh_upload", "no"); - addServiceTxt("arduino", "tcp", "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD)); - addServiceTxt("arduino", "tcp", "auth_upload", (auth) ? "yes" : "no"); -} - -void MDNSResponder::_replyToTypeEnumRequest(IPAddress multicastInterface) -{ - MDNSService* servicePtr; - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - if (servicePtr->_port > 0) - { - char *service = servicePtr->_name; - char *proto = servicePtr->_proto; - //uint16_t port = servicePtr->_port; - -#ifdef DEBUG_ESP_MDNS_TX - DEBUG_ESP_PORT.printf("TX: service:%s, proto:%s\n", service, proto); -#endif - - char sdHostName[] = "_services"; - size_t sdHostNameLen = 9; - char sdServiceName[] = "_dns-sd"; - size_t sdServiceNameLen = 7; - char sdProtoName[] = "_udp"; - size_t sdProtoNameLen = 4; - - char underscore[] = "_"; - - // build service name with _ - char serviceName[os_strlen(service) + 2]; - os_strcpy(serviceName, underscore); - os_strcat(serviceName, service); - size_t serviceNameLen = os_strlen(serviceName); - - //build proto name with _ - char protoName[5]; - os_strcpy(protoName, underscore); - os_strcat(protoName, proto); - size_t protoNameLen = 4; - - //local string - char localName[] = "local"; - size_t localNameLen = 5; - - //terminator - char terminator[] = "\0"; - - //Write the header - _conn->flush(); - uint8_t head[12] = - { - 0x00, 0x00, //ID = 0 - 0x84, 0x00, //Flags = response + authoritative answer - 0x00, 0x00, //Question count - 0x00, 0x01, //Answer count - 0x00, 0x00, //Name server records - 0x00, 0x00, //Additional records - }; - _conn->append(reinterpret_cast<const char*>(head), 12); - - // Send the Name field (ie. "_services._dns-sd._udp.local") - _conn->append(reinterpret_cast<const char*>(&sdHostNameLen), 1); // length of "_services" - _conn->append(reinterpret_cast<const char*>(sdHostName), sdHostNameLen); // "_services" - _conn->append(reinterpret_cast<const char*>(&sdServiceNameLen), 1); // length of "_dns-sd" - _conn->append(reinterpret_cast<const char*>(sdServiceName), sdServiceNameLen);// "_dns-sd" - _conn->append(reinterpret_cast<const char*>(&sdProtoNameLen), 1); // length of "_udp" - _conn->append(reinterpret_cast<const char*>(sdProtoName), sdProtoNameLen); // "_udp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type, class, ttl and rdata length - uint8_t ptrDataLen = serviceNameLen + protoNameLen + localNameLen + 4; // 4 is three label sizes and the terminator - uint8_t ptrAttrs[10] = - { - 0x00, 0x0c, //PTR record query - 0x00, 0x01, //Class IN - 0x00, 0x00, 0x11, 0x94, //TTL 4500 - 0x00, ptrDataLen, //RData length - }; - _conn->append(reinterpret_cast<const char*>(ptrAttrs), 10); - - //Send the RData (ie. "_http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - _conn->setMulticastInterface(multicastInterface); - _conn->send(); - } - } -} - -void MDNSResponder::_replyToInstanceRequest(uint8_t questionMask, uint8_t responseMask, char * service, char *proto, uint16_t port, IPAddress multicastInterface) -{ - int i; - if (questionMask == 0) - { - return; - } - if (responseMask == 0) - { - return; - } - -#ifdef DEBUG_ESP_MDNS_TX - DEBUG_ESP_PORT.printf("TX: qmask:%01X, rmask:%01X, service:%s, proto:%s, port:%u\n", questionMask, responseMask, service, proto, port); -#endif - - - String instanceName = _instanceName; - size_t instanceNameLen = instanceName.length(); - - String hostName = _hostName; - size_t hostNameLen = hostName.length(); - - char underscore[] = "_"; - - // build service name with _ - char serviceName[os_strlen(service) + 2]; - os_strcpy(serviceName, underscore); - os_strcat(serviceName, service); - size_t serviceNameLen = os_strlen(serviceName); - - //build proto name with _ - char protoName[5]; - os_strcpy(protoName, underscore); - os_strcat(protoName, proto); - size_t protoNameLen = 4; - - //local string - char localName[] = "local"; - size_t localNameLen = 5; - - //terminator - char terminator[] = "\0"; - - uint8_t answerMask = responseMask & questionMask; - uint8_t answerCount = 0; - uint8_t additionalMask = responseMask & ~questionMask; - uint8_t additionalCount = 0; - for (i = 0; i < 4; i++) - { - if (answerMask & (1 << i)) - { - answerCount++; - } - if (additionalMask & (1 << i)) - { - additionalCount++; - } - } - - - //Write the header - _conn->flush(); - uint8_t head[12] = - { - 0x00, 0x00, //ID = 0 - 0x84, 0x00, //Flags = response + authoritative answer - 0x00, 0x00, //Question count - 0x00, answerCount, //Answer count - 0x00, 0x00, //Name server records - 0x00, additionalCount, //Additional records - }; - _conn->append(reinterpret_cast<const char*>(head), 12); - - for (int responseSection = 0; responseSection < 2; ++responseSection) - { - - // PTR Response - if ((responseSection == 0 ? answerMask : additionalMask) & 0x8) - { - // Send the Name field (ie. "_http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type, class, ttl and rdata length - uint8_t ptrDataLen = instanceNameLen + serviceNameLen + protoNameLen + localNameLen + 5; // 5 is four label sizes and the terminator - uint8_t ptrAttrs[10] = - { - 0x00, 0x0c, //PTR record query - 0x00, 0x01, //Class IN - 0x00, 0x00, 0x00, 0x78, //TTL 120 - 0x00, ptrDataLen, //RData length - }; - _conn->append(reinterpret_cast<const char*>(ptrAttrs), 10); - - //Send the RData (ie. "My IOT device._http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // length of "My IOT device" - _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - } - - //TXT Responce - if ((responseSection == 0 ? answerMask : additionalMask) & 0x4) - { - //Send the name field (ie. "My IOT device._http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // length of "My IOT device" - _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type, class, ttl and rdata length - uint8_t txtDataLen = _getServiceTxtLen(service, proto); - uint8_t txtAttrs[10] = - { - 0x00, 0x10, //TXT record query - 0x80, 0x01, //Class IN, with cache flush - 0x00, 0x00, 0x11, 0x94, //TTL 4500 - 0x00, txtDataLen, //RData length - }; - _conn->append(reinterpret_cast<const char*>(txtAttrs), 10); - - //Send the RData - MDNSTxt * txtPtr = _getServiceTxt(service, proto); - while (txtPtr != 0) - { - uint8_t txtLen = txtPtr->_txt.length(); - _conn->append(reinterpret_cast<const char*>(&txtLen), 1); // length of txt - _conn->append(reinterpret_cast<const char*>(txtPtr->_txt.c_str()), txtLen);// the txt - txtPtr = txtPtr->_next; - } - } - - - //SRV Responce - if ((responseSection == 0 ? answerMask : additionalMask) & 0x2) - { - //Send the name field (ie. "My IOT device._http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // length of "My IOT device" - _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type, class, ttl, rdata length, priority and weight - uint8_t srvDataSize = hostNameLen + localNameLen + 3; // 3 is 2 lable size bytes and the terminator - srvDataSize += 6; // Size of Priority, weight and port - uint8_t srvAttrs[10] = - { - 0x00, 0x21, //Type SRV - 0x80, 0x01, //Class IN, with cache flush - 0x00, 0x00, 0x00, 0x78, //TTL 120 - 0x00, srvDataSize, //RData length - }; - _conn->append(reinterpret_cast<const char*>(srvAttrs), 10); - - //Send the RData Priority weight and port - uint8_t srvRData[6] = - { - 0x00, 0x00, //Priority 0 - 0x00, 0x00, //Weight 0 - (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF) - }; - _conn->append(reinterpret_cast<const char*>(srvRData), 6); - //Send the RData (ie. "esp8266.local") - _conn->append(reinterpret_cast<const char*>(&hostNameLen), 1); // length of "esp8266" - _conn->append(reinterpret_cast<const char*>(hostName.c_str()), hostNameLen);// "esp8266" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - } - - // A Response - if ((responseSection == 0 ? answerMask : additionalMask) & 0x1) - { - //Send the RData (ie. "esp8266.local") - _conn->append(reinterpret_cast<const char*>(&hostNameLen), 1); // length of "esp8266" - _conn->append(reinterpret_cast<const char*>(hostName.c_str()), hostNameLen);// "esp8266" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - uint8_t aaaAttrs[10] = - { - 0x00, 0x01, //TYPE A - 0x80, 0x01, //Class IN, with cache flush - 0x00, 0x00, 0x00, 0x78, //TTL 120 - 0x00, 0x04, //DATA LEN - }; - _conn->append(reinterpret_cast<const char*>(aaaAttrs), 10); - - // Send RData - uint32_t ip = multicastInterface; - uint8_t aaaRData[4] = - { - (uint8_t)(ip & 0xFF), //IP first octet - (uint8_t)((ip >> 8) & 0xFF), //IP second octet - (uint8_t)((ip >> 16) & 0xFF), //IP third octet - (uint8_t)((ip >> 24) & 0xFF) //IP fourth octet - }; - _conn->append(reinterpret_cast<const char*>(aaaRData), 4); - } - } - - _conn->setMulticastInterface(multicastInterface); - _conn->send(); -} - -#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) -MDNSResponder MDNS; -#endif - -} // namespace Legacy_MDNSResponder - - - - diff --git a/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.h b/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.h deleted file mode 100644 index 9d3cfd2f62..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - ESP8266 Multicast DNS (port of CC3000 Multicast DNS library) - Version 1.1 - Copyright (c) 2013 Tony DiCola (tony@tonydicola.com) - ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com) - Extended MDNS-SD support 2016 Lars Englund (lars.englund@gmail.com) - - This is a simple implementation of multicast DNS query support for an Arduino - running on ESP8266 chip. Only support for resolving address queries is currently - implemented. - - Requirements: - - ESP8266WiFi library - - Usage: - - Include the ESP8266 Multicast DNS library in the sketch. - - Call the begin method in the sketch's setup and provide a domain name (without - the '.local' suffix, i.e. just provide 'foo' to resolve 'foo.local'), and the - Adafruit CC3000 class instance. Optionally provide a time to live (in seconds) - for the DNS record--the default is 1 hour. - - Call the update method in each iteration of the sketch's loop function. - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ -#ifndef ESP8266MDNS_LEGACY_H -#define ESP8266MDNS_LEGACY_H - -#include "ESP8266WiFi.h" -#include "WiFiUdp.h" - -//this should be defined at build time -#ifndef ARDUINO_BOARD -#define ARDUINO_BOARD "generic" -#endif - -class UdpContext; - - -namespace Legacy_MDNSResponder -{ - - -struct MDNSService; -struct MDNSTxt; -struct MDNSAnswer; - -class MDNSResponder -{ -public: - MDNSResponder(); - ~MDNSResponder(); - bool begin(const char* hostName); - bool begin(const String& hostName) - { - return begin(hostName.c_str()); - } - //for compatibility - bool begin(const char* hostName, IPAddress ip, uint32_t ttl = 120) - { - (void) ip; - (void) ttl; - return begin(hostName); - } - bool begin(const String& hostName, IPAddress ip, uint32_t ttl = 120) - { - return begin(hostName.c_str(), ip, ttl); - } - /* Application should call this whenever AP is configured/disabled */ - void notifyAPChange(); - void update(); - - void addService(char *service, char *proto, uint16_t port); - void addService(const char *service, const char *proto, uint16_t port) - { - addService((char *)service, (char *)proto, port); - } - void addService(const String& service, const String& proto, uint16_t port) - { - addService(service.c_str(), proto.c_str(), port); - } - - bool addServiceTxt(char *name, char *proto, char * key, char * value); - bool addServiceTxt(const char *name, const char *proto, const char *key, const char * value) - { - return addServiceTxt((char *)name, (char *)proto, (char *)key, (char *)value); - } - bool addServiceTxt(const String& name, const String& proto, const String& key, const String& value) - { - return addServiceTxt(name.c_str(), proto.c_str(), key.c_str(), value.c_str()); - } - - int queryService(char *service, char *proto); - int queryService(const char *service, const char *proto) - { - return queryService((char *)service, (char *)proto); - } - int queryService(const String& service, const String& proto) - { - return queryService(service.c_str(), proto.c_str()); - } - String hostname(int idx); - IPAddress IP(int idx); - uint16_t port(int idx); - - void enableArduino(uint16_t port, bool auth = false); - - void setInstanceName(String name); - void setInstanceName(const char * name) - { - setInstanceName(String(name)); - } - void setInstanceName(char * name) - { - setInstanceName(String(name)); - } - -private: - struct MDNSService * _services; - UdpContext* _conn; - String _hostName; - String _instanceName; - struct MDNSAnswer * _answers; - struct MDNSQuery * _query; - bool _newQuery; - bool _waitingForAnswers; - WiFiEventHandler _disconnectedHandler; - WiFiEventHandler _gotIPHandler; - - - uint16_t _getServicePort(char *service, char *proto); - MDNSTxt * _getServiceTxt(char *name, char *proto); - uint16_t _getServiceTxtLen(char *name, char *proto); - IPAddress _getRequestMulticastInterface(); - void _parsePacket(); - void _replyToTypeEnumRequest(IPAddress multicastInterface); - void _replyToInstanceRequest(uint8_t questionMask, uint8_t responseMask, char * service, char *proto, uint16_t port, IPAddress multicastInterface); - MDNSAnswer* _getAnswerFromIdx(int idx); - int _getNumAnswers(); - bool _listen(); - void _restart(); -}; - -} // namespace Legacy_MDNSResponder - -#endif //ESP8266MDNS_H - - - diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.cpp deleted file mode 100644 index 87ff5167ff..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.cpp +++ /dev/null @@ -1,1381 +0,0 @@ -/* - LEAmDNS.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#include <Schedule.h> -#include <AddrList.h> - -#include "LEAmDNS_Priv.h" - - -namespace esp8266 -{ - -/* - LEAmDNS -*/ -namespace MDNSImplementation -{ - -/** - STRINGIZE -*/ -#ifndef STRINGIZE -#define STRINGIZE(x) #x -#endif -#ifndef STRINGIZE_VALUE_OF -#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) -#endif - - -/** - INTERFACE -*/ - -/** - MDNSResponder::MDNSResponder -*/ -MDNSResponder::MDNSResponder(void) - : m_pServices(0), - m_pUDPContext(0), - m_pcHostname(0), - m_pServiceQueries(0), - m_fnServiceTxtCallback(0), -#ifdef ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE - m_bPassivModeEnabled(true), -#else - m_bPassivModeEnabled(false), -#endif - m_netif(nullptr) -{ -} - -/* - MDNSResponder::~MDNSResponder -*/ -MDNSResponder::~MDNSResponder(void) -{ - - _resetProbeStatus(false); - _releaseServiceQueries(); - _releaseHostname(); - _releaseUDPContext(); - _releaseServices(); -} - -/* - MDNSResponder::begin - - Set the host domain (for probing) and install WiFi event handlers for - IP assignment and disconnection management. In both cases, the MDNS responder - is restarted (reset and restart probe status) - Finally the responder is (re)started - -*/ -bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& p_IPAddress, uint32_t p_u32TTL) -{ - - (void)p_u32TTL; // ignored - bool bResult = false; - - if (0 == m_pUDPContext) - { - if (_setHostname(p_pcHostname)) - { - - //// select interface - - m_netif = nullptr; - IPAddress ipAddress = p_IPAddress; - - if (!ipAddress.isSet()) - { - - IPAddress sta = WiFi.localIP(); - IPAddress ap = WiFi.softAPIP(); - - if (sta.isSet()) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] STA interface selected\n"))); - ipAddress = sta; - } - else if (ap.isSet()) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] AP interface selected\n"))); - ipAddress = ap; - } - else - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] standard interfaces are not up, please specify one in ::begin()\n"))); - return false; - } - - // continue to ensure interface is UP - } - - // check existence of this IP address in the interface list - bool found = false; - m_netif = nullptr; - for (auto a : addrList) - if (ipAddress == a.addr()) - { - if (a.ifUp()) - { - found = true; - m_netif = a.interface(); - break; - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] found interface for IP '%s' but it is not UP\n"), ipAddress.toString().c_str());); - } - if (!found) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] interface defined by IP '%s' not found\n"), ipAddress.toString().c_str());); - return false; - } - - //// done selecting the interface - - if (m_netif->num == STATION_IF) - { - - m_GotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP & pEvent) - { - (void) pEvent; - // Ensure that _restart() runs in USER context - schedule_function([this]() - { - MDNSResponder::_restart(); - }); - }); - - m_DisconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected & pEvent) - { - (void) pEvent; - // Ensure that _restart() runs in USER context - schedule_function([this]() - { - MDNSResponder::_restart(); - }); - }); - } - - bResult = _restart(); - } - DEBUG_EX_ERR(if (!bResult) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] begin: FAILED for '%s'!\n"), (p_pcHostname ? : "-")); - }); - } - else - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] begin: Ignoring multiple calls to begin (Ignored host domain: '%s')!\n"), (p_pcHostname ? : "-"));); - } - return bResult; -} - -/* - MDNSResponder::close - - Ends the MDNS responder. - Announced services are unannounced (by multicasting a goodbye message) - -*/ -bool MDNSResponder::close(void) -{ - bool bResult = false; - - if (0 != m_pUDPContext) - { - m_GotIPHandler.reset(); // reset WiFi event callbacks. - m_DisconnectedHandler.reset(); - - _announce(false, true); - _resetProbeStatus(false); // Stop probing - _releaseServiceQueries(); - _releaseUDPContext(); - _releaseHostname(); - - bResult = true; - } - else - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] close: Ignoring call to close!\n"));); - } - return bResult; -} - -/* - MDNSResponder::end - - Ends the MDNS responder. - for compatibility with esp32 - -*/ - -bool MDNSResponder::end(void) -{ - return close(); -} - -/* - MDNSResponder::setHostname - - Replaces the current hostname and restarts probing. - For services without own instance name (when the host name was used a instance - name), the instance names are replaced also (and the probing is restarted). - -*/ -bool MDNSResponder::setHostname(const char* p_pcHostname) -{ - - bool bResult = false; - - if (_setHostname(p_pcHostname)) - { - m_HostProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart; - - // Replace 'auto-set' service names - bResult = true; - for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) - { - if (pService->m_bAutoName) - { - bResult = pService->setName(p_pcHostname); - pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart; - } - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setHostname: FAILED for '%s'!\n"), (p_pcHostname ? : "-")); - }); - return bResult; -} - -/* - MDNSResponder::setHostname (LEGACY) -*/ -bool MDNSResponder::setHostname(const String& p_strHostname) -{ - - return setHostname(p_strHostname.c_str()); -} - - -/* - SERVICES -*/ - -/* - MDNSResponder::addService - - Add service; using hostname if no name is explicitly provided for the service - The usual '_' underline, which is prepended to service and protocol, eg. _http, - may be given. If not, it is added automatically. - -*/ -MDNSResponder::hMDNSService MDNSResponder::addService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port) -{ - - hMDNSService hResult = 0; - - if (((!p_pcName) || // NO name OR - (MDNS_DOMAIN_LABEL_MAXLENGTH >= os_strlen(p_pcName))) && // Fitting name - (p_pcService) && - (MDNS_SERVICE_NAME_LENGTH >= os_strlen(p_pcService)) && - (p_pcProtocol) && - ((MDNS_SERVICE_PROTOCOL_LENGTH - 1) != os_strlen(p_pcProtocol)) && - (p_u16Port)) - { - - if (!_findService((p_pcName ? : m_pcHostname), p_pcService, p_pcProtocol)) // Not already used - { - if (0 != (hResult = (hMDNSService)_allocService(p_pcName, p_pcService, p_pcProtocol, p_u16Port))) - { - - // Start probing - ((stcMDNSService*)hResult)->m_ProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart; - } - } - } // else: bad arguments - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addService: %s to add '%s.%s.%s'!\n"), (hResult ? "Succeeded" : "FAILED"), (p_pcName ? : "-"), p_pcService, p_pcProtocol);); - DEBUG_EX_ERR(if (!hResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addService: FAILED to add '%s.%s.%s'!\n"), (p_pcName ? : "-"), p_pcService, p_pcProtocol); - }); - return hResult; -} - -/* - MDNSResponder::removeService - - Unanounce a service (by sending a goodbye message) and remove it - from the MDNS responder - -*/ -bool MDNSResponder::removeService(const MDNSResponder::hMDNSService p_hService) -{ - - stcMDNSService* pService = 0; - bool bResult = (((pService = _findService(p_hService))) && - (_announceService(*pService, false)) && - (_releaseService(pService))); - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeService: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::removeService -*/ -bool MDNSResponder::removeService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol) -{ - - return removeService((hMDNSService)_findService((p_pcName ? : m_pcHostname), p_pcService, p_pcProtocol)); -} - -/* - MDNSResponder::addService (LEGACY) -*/ -bool MDNSResponder::addService(const String& p_strService, - const String& p_strProtocol, - uint16_t p_u16Port) -{ - - return (0 != addService(m_pcHostname, p_strService.c_str(), p_strProtocol.c_str(), p_u16Port)); -} - -/* - MDNSResponder::setServiceName -*/ -bool MDNSResponder::setServiceName(const MDNSResponder::hMDNSService p_hService, - const char* p_pcInstanceName) -{ - - stcMDNSService* pService = 0; - bool bResult = (((!p_pcInstanceName) || - (MDNS_DOMAIN_LABEL_MAXLENGTH >= os_strlen(p_pcInstanceName))) && - ((pService = _findService(p_hService))) && - (pService->setName(p_pcInstanceName)) && - ((pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart))); - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setServiceName: FAILED for '%s'!\n"), (p_pcInstanceName ? : "-")); - }); - return bResult; -} - -/* - SERVICE TXT -*/ - -/* - MDNSResponder::addServiceTxt - - Add a static service TXT item ('Key'='Value') to a service. - -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue) -{ - - hMDNSTxt hTxt = 0; - stcMDNSService* pService = _findService(p_hService); - if (pService) - { - hTxt = (hMDNSTxt)_addServiceTxt(pService, p_pcKey, p_pcValue, false); - } - DEBUG_EX_ERR(if (!hTxt) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addServiceTxt: FAILED for '%s=%s'!\n"), (p_pcKey ? : "-"), (p_pcValue ? : "-")); - }); - return hTxt; -} - -/* - MDNSResponder::addServiceTxt (uint32_t) - - Formats: http://www.cplusplus.com/reference/cstdio/printf/ -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - char acBuffer[32]; *acBuffer = 0; - sprintf(acBuffer, "%u", p_u32Value); - - return addServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (uint16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - char acBuffer[16]; *acBuffer = 0; - sprintf(acBuffer, "%hu", p_u16Value); - - return addServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (uint8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - char acBuffer[8]; *acBuffer = 0; - sprintf(acBuffer, "%hhu", p_u8Value); - - return addServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (int32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value) -{ - char acBuffer[32]; *acBuffer = 0; - sprintf(acBuffer, "%i", p_i32Value); - - return addServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (int16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value) -{ - char acBuffer[16]; *acBuffer = 0; - sprintf(acBuffer, "%hi", p_i16Value); - - return addServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (int8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value) -{ - char acBuffer[8]; *acBuffer = 0; - sprintf(acBuffer, "%hhi", p_i8Value); - - return addServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::removeServiceTxt - - Remove a static service TXT item from a service. -*/ -bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSService p_hService, - const MDNSResponder::hMDNSTxt p_hTxt) -{ - - bool bResult = false; - - stcMDNSService* pService = _findService(p_hService); - if (pService) - { - stcMDNSServiceTxt* pTxt = _findServiceTxt(pService, p_hTxt); - if (pTxt) - { - bResult = _releaseServiceTxt(pService, pTxt); - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeServiceTxt: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::removeServiceTxt -*/ -bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey) -{ - - bool bResult = false; - - stcMDNSService* pService = _findService(p_hService); - if (pService) - { - stcMDNSServiceTxt* pTxt = _findServiceTxt(pService, p_pcKey); - if (pTxt) - { - bResult = _releaseServiceTxt(pService, pTxt); - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeServiceTxt: FAILED for '%s'!\n"), (p_pcKey ? : "-")); - }); - return bResult; -} - -/* - MDNSResponder::removeServiceTxt -*/ -bool MDNSResponder::removeServiceTxt(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - const char* p_pcKey) -{ - - bool bResult = false; - - stcMDNSService* pService = _findService((p_pcName ? : m_pcHostname), p_pcService, p_pcProtocol); - if (pService) - { - stcMDNSServiceTxt* pTxt = _findServiceTxt(pService, p_pcKey); - if (pTxt) - { - bResult = _releaseServiceTxt(pService, pTxt); - } - } - return bResult; -} - -/* - MDNSResponder::addServiceTxt (LEGACY) -*/ -bool MDNSResponder::addServiceTxt(const char* p_pcService, - const char* p_pcProtocol, - const char* p_pcKey, - const char* p_pcValue) -{ - - return (0 != _addServiceTxt(_findService(m_pcHostname, p_pcService, p_pcProtocol), p_pcKey, p_pcValue, false)); -} - -/* - MDNSResponder::addServiceTxt (LEGACY) -*/ -bool MDNSResponder::addServiceTxt(const String& p_strService, - const String& p_strProtocol, - const String& p_strKey, - const String& p_strValue) -{ - - return (0 != _addServiceTxt(_findService(m_pcHostname, p_strService.c_str(), p_strProtocol.c_str()), p_strKey.c_str(), p_strValue.c_str(), false)); -} - -/* - MDNSResponder::setDynamicServiceTxtCallback (global) - - Set a global callback for dynamic service TXT items. The callback is called, whenever - service TXT items are needed. - -*/ -bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::MDNSDynamicServiceTxtCallbackFunc p_fnCallback) -{ - - m_fnServiceTxtCallback = p_fnCallback; - - return true; -} - -/* - MDNSResponder::setDynamicServiceTxtCallback (service specific) - - Set a service specific callback for dynamic service TXT items. The callback is called, whenever - service TXT items are needed for the given service. - -*/ -bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::hMDNSService p_hService, - MDNSResponder::MDNSDynamicServiceTxtCallbackFunc p_fnCallback) -{ - - bool bResult = false; - - stcMDNSService* pService = _findService(p_hService); - if (pService) - { - pService->m_fnTxtCallback = p_fnCallback; - - bResult = true; - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setDynamicServiceTxtCallback: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::addDynamicServiceTxt -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addDynamicServiceTxt (%s=%s)\n"), p_pcKey, p_pcValue);); - - hMDNSTxt hTxt = 0; - - stcMDNSService* pService = _findService(p_hService); - if (pService) - { - hTxt = _addServiceTxt(pService, p_pcKey, p_pcValue, true); - } - DEBUG_EX_ERR(if (!hTxt) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addDynamicServiceTxt: FAILED for '%s=%s'!\n"), (p_pcKey ? : "-"), (p_pcValue ? : "-")); - }); - return hTxt; -} - -/* - MDNSResponder::addDynamicServiceTxt (uint32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - - char acBuffer[32]; *acBuffer = 0; - sprintf(acBuffer, "%u", p_u32Value); - - return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (uint16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - - char acBuffer[16]; *acBuffer = 0; - sprintf(acBuffer, "%hu", p_u16Value); - - return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (uint8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - - char acBuffer[8]; *acBuffer = 0; - sprintf(acBuffer, "%hhu", p_u8Value); - - return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (int32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value) -{ - - char acBuffer[32]; *acBuffer = 0; - sprintf(acBuffer, "%i", p_i32Value); - - return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (int16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value) -{ - - char acBuffer[16]; *acBuffer = 0; - sprintf(acBuffer, "%hi", p_i16Value); - - return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (int8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value) -{ - - char acBuffer[8]; *acBuffer = 0; - sprintf(acBuffer, "%hhi", p_i8Value); - - return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); -} - - -/** - STATIC SERVICE QUERY (LEGACY) -*/ - -/* - MDNSResponder::queryService - - Perform a (blocking) static service query. - The arrived answers can be queried by calling: - - answerHostname (or 'hostname') - - answerIP (or 'IP') - - answerPort (or 'port') - -*/ -uint32_t MDNSResponder::queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) -{ - if (0 == m_pUDPContext) - { - // safeguard against misuse - return 0; - } - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService '%s.%s'\n"), p_pcService, p_pcProtocol);); - - uint32_t u32Result = 0; - - stcMDNSServiceQuery* pServiceQuery = 0; - if ((p_pcService) && - (os_strlen(p_pcService)) && - (p_pcProtocol) && - (os_strlen(p_pcProtocol)) && - (p_u16Timeout) && - (_removeLegacyServiceQuery()) && - ((pServiceQuery = _allocServiceQuery())) && - (_buildDomainForService(p_pcService, p_pcProtocol, pServiceQuery->m_ServiceTypeDomain))) - { - - pServiceQuery->m_bLegacyQuery = true; - - if (_sendMDNSServiceQuery(*pServiceQuery)) - { - // Wait for answers to arrive - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService: Waiting %u ms for answers...\n"), p_u16Timeout);); - delay(p_u16Timeout); - - // All answers should have arrived by now -> stop adding new answers - pServiceQuery->m_bAwaitingAnswers = false; - u32Result = pServiceQuery->answerCount(); - } - else // FAILED to send query - { - _removeServiceQuery(pServiceQuery); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService: INVALID input data!\n"));); - } - return u32Result; -} - -/* - MDNSResponder::removeQuery - - Remove the last static service query (and all answers). - -*/ -bool MDNSResponder::removeQuery(void) -{ - - return _removeLegacyServiceQuery(); -} - -/* - MDNSResponder::queryService (LEGACY) -*/ -uint32_t MDNSResponder::queryService(const String& p_strService, - const String& p_strProtocol) -{ - - return queryService(p_strService.c_str(), p_strProtocol.c_str()); -} - -/* - MDNSResponder::answerHostname -*/ -const char* MDNSResponder::answerHostname(const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery(); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - - if ((pSQAnswer) && - (pSQAnswer->m_HostDomain.m_u16NameLength) && - (!pSQAnswer->m_pcHostDomain)) - { - - char* pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); - if (pcHostDomain) - { - pSQAnswer->m_HostDomain.c_str(pcHostDomain); - } - } - return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); -} - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::answerIP -*/ -IPAddress MDNSResponder::answerIP(const uint32_t p_u32AnswerIndex) -{ - - const stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery(); - const stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - const stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address = (((pSQAnswer) && (pSQAnswer->m_pIP4Addresses)) ? pSQAnswer->IP4AddressAtIndex(0) : 0); - return (pIP4Address ? pIP4Address->m_IPAddress : IPAddress()); -} -#endif - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::answerIP6 -*/ -IPAddress MDNSResponder::answerIP6(const uint32_t p_u32AnswerIndex) -{ - - const stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery(); - const stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - const stcMDNSServiceQuery::stcAnswer::stcIP6Address* pIP6Address = (((pSQAnswer) && (pSQAnswer->m_pIP6Addresses)) ? pSQAnswer->IP6AddressAtIndex(0) : 0); - return (pIP6Address ? pIP6Address->m_IPAddress : IP6Address()); -} -#endif - -/* - MDNSResponder::answerPort -*/ -uint16_t MDNSResponder::answerPort(const uint32_t p_u32AnswerIndex) -{ - - const stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery(); - const stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->m_u16Port : 0); -} - -/* - MDNSResponder::hostname (LEGACY) -*/ -String MDNSResponder::hostname(const uint32_t p_u32AnswerIndex) -{ - - return String(answerHostname(p_u32AnswerIndex)); -} - -/* - MDNSResponder::IP (LEGACY) -*/ -IPAddress MDNSResponder::IP(const uint32_t p_u32AnswerIndex) -{ - - return answerIP(p_u32AnswerIndex); -} - -/* - MDNSResponder::port (LEGACY) -*/ -uint16_t MDNSResponder::port(const uint32_t p_u32AnswerIndex) -{ - - return answerPort(p_u32AnswerIndex); -} - - -/** - DYNAMIC SERVICE QUERY -*/ - -/* - MDNSResponder::installServiceQuery - - Add a dynamic service query and a corresponding callback to the MDNS responder. - The callback will be called for every answer update. - The answers can also be queried by calling: - - answerServiceDomain - - answerHostDomain - - answerIP4Address/answerIP6Address - - answerPort - - answerTxts - -*/ -MDNSResponder::hMDNSServiceQuery MDNSResponder::installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - MDNSResponder::MDNSServiceQueryCallbackFunc p_fnCallback) -{ - hMDNSServiceQuery hResult = 0; - - stcMDNSServiceQuery* pServiceQuery = 0; - if ((p_pcService) && - (os_strlen(p_pcService)) && - (p_pcProtocol) && - (os_strlen(p_pcProtocol)) && - (p_fnCallback) && - ((pServiceQuery = _allocServiceQuery())) && - (_buildDomainForService(p_pcService, p_pcProtocol, pServiceQuery->m_ServiceTypeDomain))) - { - - pServiceQuery->m_fnCallback = p_fnCallback; - pServiceQuery->m_bLegacyQuery = false; - - if (_sendMDNSServiceQuery(*pServiceQuery)) - { - pServiceQuery->m_u8SentCount = 1; - pServiceQuery->m_ResendTimeout.reset(MDNS_DYNAMIC_QUERY_RESEND_DELAY); - - hResult = (hMDNSServiceQuery)pServiceQuery; - } - else - { - _removeServiceQuery(pServiceQuery); - } - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] installServiceQuery: %s for '%s.%s'!\n\n"), (hResult ? "Succeeded" : "FAILED"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); - DEBUG_EX_ERR(if (!hResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] installServiceQuery: FAILED for '%s.%s'!\n\n"), (p_pcService ? : "-"), (p_pcProtocol ? : "-")); - }); - return hResult; -} - -/* - MDNSResponder::removeServiceQuery - - Remove a dynamic service query (and all collected answers) from the MDNS responder - -*/ -bool MDNSResponder::removeServiceQuery(MDNSResponder::hMDNSServiceQuery p_hServiceQuery) -{ - - stcMDNSServiceQuery* pServiceQuery = 0; - bool bResult = (((pServiceQuery = _findServiceQuery(p_hServiceQuery))) && - (_removeServiceQuery(pServiceQuery))); - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeServiceQuery: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::answerCount -*/ -uint32_t MDNSResponder::answerCount(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - return (pServiceQuery ? pServiceQuery->answerCount() : 0); -} - -std::vector<MDNSResponder::MDNSServiceInfo> MDNSResponder::answerInfo(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery) -{ - std::vector<MDNSResponder::MDNSServiceInfo> tempVector; - for (uint32_t i = 0; i < answerCount(p_hServiceQuery); i++) - { - tempVector.emplace_back(*this, p_hServiceQuery, i); - } - return tempVector; -} - -/* - MDNSResponder::answerServiceDomain - - Returns the domain for the given service. - If not already existing, the string is allocated, filled and attached to the answer. - -*/ -const char* MDNSResponder::answerServiceDomain(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcServiceDomain (if not already done) - if ((pSQAnswer) && - (pSQAnswer->m_ServiceDomain.m_u16NameLength) && - (!pSQAnswer->m_pcServiceDomain)) - { - - pSQAnswer->m_pcServiceDomain = pSQAnswer->allocServiceDomain(pSQAnswer->m_ServiceDomain.c_strLength()); - if (pSQAnswer->m_pcServiceDomain) - { - pSQAnswer->m_ServiceDomain.c_str(pSQAnswer->m_pcServiceDomain); - } - } - return (pSQAnswer ? pSQAnswer->m_pcServiceDomain : 0); -} - -/* - MDNSResponder::hasAnswerHostDomain -*/ -bool MDNSResponder::hasAnswerHostDomain(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_HostDomainAndPort)); -} - -/* - MDNSResponder::answerHostDomain - - Returns the host domain for the given service. - If not already existing, the string is allocated, filled and attached to the answer. - -*/ -const char* MDNSResponder::answerHostDomain(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcHostDomain (if not already done) - if ((pSQAnswer) && - (pSQAnswer->m_HostDomain.m_u16NameLength) && - (!pSQAnswer->m_pcHostDomain)) - { - - pSQAnswer->m_pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); - if (pSQAnswer->m_pcHostDomain) - { - pSQAnswer->m_HostDomain.c_str(pSQAnswer->m_pcHostDomain); - } - } - return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); -} - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::hasAnswerIP4Address -*/ -bool MDNSResponder::hasAnswerIP4Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_IP4Address)); -} - -/* - MDNSResponder::answerIP4AddressCount -*/ -uint32_t MDNSResponder::answerIP4AddressCount(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->IP4AddressCount() : 0); -} - -/* - MDNSResponder::answerIP4Address -*/ -IPAddress MDNSResponder::answerIP4Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address = (pSQAnswer ? pSQAnswer->IP4AddressAtIndex(p_u32AddressIndex) : 0); - return (pIP4Address ? pIP4Address->m_IPAddress : IPAddress()); -} -#endif - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::hasAnswerIP6Address -*/ -bool MDNSResponder::hasAnswerIP6Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_HostIP6Address)); -} - -/* - MDNSResponder::answerIP6AddressCount -*/ -uint32_t MDNSResponder::answerIP6AddressCount(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->IP6AddressCount() : 0); -} - -/* - MDNSResponder::answerIP6Address -*/ -IPAddress MDNSResponder::answerIP6Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - stcMDNSServiceQuery::stcAnswer::stcIP6Address* pIP6Address = (pSQAnswer ? pSQAnswer->IP6AddressAtIndex(p_u32AddressIndex) : 0); - return (pIP6Address ? pIP6Address->m_IPAddress : IPAddress()); -} -#endif - -/* - MDNSResponder::hasAnswerPort -*/ -bool MDNSResponder::hasAnswerPort(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_HostDomainAndPort)); -} - -/* - MDNSResponder::answerPort -*/ -uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->m_u16Port : 0); -} - -/* - MDNSResponder::hasAnswerTxts -*/ -bool MDNSResponder::hasAnswerTxts(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_Txts)); -} - -/* - MDNSResponder::answerTxts - - Returns all TXT items for the given service as a ';'-separated string. - If not already existing; the string is alloced, filled and attached to the answer. - -*/ -const char* MDNSResponder::answerTxts(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcTxts (if not already done) - if ((pSQAnswer) && - (pSQAnswer->m_Txts.m_pTxts) && - (!pSQAnswer->m_pcTxts)) - { - - pSQAnswer->m_pcTxts = pSQAnswer->allocTxts(pSQAnswer->m_Txts.c_strLength()); - if (pSQAnswer->m_pcTxts) - { - pSQAnswer->m_Txts.c_str(pSQAnswer->m_pcTxts); - } - } - return (pSQAnswer ? pSQAnswer->m_pcTxts : 0); -} - -/* - PROBING -*/ - -/* - MDNSResponder::setProbeResultCallback - - Set a global callback for probe results. The callback is called, when probing - for the host domain (or a service domain, without specific probe result callback) - failes or succeedes. - In the case of failure, the domain name should be changed via 'setHostname' or 'setServiceName'. - When succeeded, the host or service domain will be announced by the MDNS responder. - -*/ -bool MDNSResponder::setHostProbeResultCallback(MDNSResponder::MDNSHostProbeFn p_fnCallback) -{ - - m_HostProbeInformation.m_fnHostProbeResultCallback = p_fnCallback; - - return true; -} - -bool MDNSResponder::setHostProbeResultCallback(MDNSHostProbeFn1 pfn) -{ - using namespace std::placeholders; - return setHostProbeResultCallback([this, pfn](const char* p_pcDomainName, bool p_bProbeResult) - { - pfn(*this, p_pcDomainName, p_bProbeResult); - }); -} - -/* - MDNSResponder::setServiceProbeResultCallback - - Set a service specific callback for probe results. The callback is called, when probing - for the service domain failes or succeedes. - In the case of failure, the service name should be changed via 'setServiceName'. - When succeeded, the service domain will be announced by the MDNS responder. - -*/ -bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService, - MDNSResponder::MDNSServiceProbeFn p_fnCallback) -{ - - bool bResult = false; - - stcMDNSService* pService = _findService(p_hService); - if (pService) - { - pService->m_ProbeInformation.m_fnServiceProbeResultCallback = p_fnCallback; - - bResult = true; - } - return bResult; -} - -bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService, - MDNSResponder::MDNSServiceProbeFn1 p_fnCallback) -{ - using namespace std::placeholders; - return setServiceProbeResultCallback(p_hService, [this, p_fnCallback](const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) - { - p_fnCallback(*this, p_pcServiceName, p_hMDNSService, p_bProbeResult); - }); -} - - -/* - MISC -*/ - -/* - MDNSResponder::notifyAPChange - - Should be called, whenever the AP for the MDNS responder changes. - A bit of this is caught by the event callbacks installed in the constructor. - -*/ -bool MDNSResponder::notifyAPChange(void) -{ - - return _restart(); -} - -/* - MDNSResponder::update - - Should be called in every 'loop'. - -*/ -bool MDNSResponder::update(void) -{ - - if (m_bPassivModeEnabled) - { - m_bPassivModeEnabled = false; - } - return _process(true); -} - -/* - MDNSResponder::announce - - Should be called, if the 'configuration' changes. Mainly this will be changes in the TXT items... -*/ -bool MDNSResponder::announce(void) -{ - - return (_announce(true, true)); -} - -/* - MDNSResponder::enableArduino - - Enable the OTA update service. - -*/ -MDNSResponder::hMDNSService MDNSResponder::enableArduino(uint16_t p_u16Port, - bool p_bAuthUpload /*= false*/) -{ - - hMDNSService hService = addService(0, "arduino", "tcp", p_u16Port); - if (hService) - { - if ((!addServiceTxt(hService, "tcp_check", "no")) || - (!addServiceTxt(hService, "ssh_upload", "no")) || - (!addServiceTxt(hService, "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD))) || - (!addServiceTxt(hService, "auth_upload", (p_bAuthUpload) ? "yes" : "no"))) - { - - removeService(hService); - hService = 0; - } - } - return hService; -} - - -} //namespace MDNSImplementation - -} //namespace esp8266 - - diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.h b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.h deleted file mode 100644 index fe02560aec..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.h +++ /dev/null @@ -1,1461 +0,0 @@ -/* - LEAmDNS.h - (c) 2018, LaborEtArs - - Version 0.9 beta - - Some notes (from LaborEtArs, 2018): - Essentially, this is an rewrite of the original EPS8266 Multicast DNS code (ESP8266mDNS). - The target of this rewrite was to keep the existing interface as stable as possible while - adding and extending the supported set of mDNS features. - A lot of the additions were basicly taken from Erik Ekman's lwIP mdns app code. - - Supported mDNS features (in some cases somewhat limited): - - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service - - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented - - Probing host and service domains for uniqueness in the local network - - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak) - - Announcing available services after successful probing - - Using fixed service TXT items or - - Using dynamic service TXT items for presented services (via callback) - - Remove services (and un-announcing them to the observers by sending goodbye-messages) - - Static queries for DNS-SD services (creating a fixed answer set after a certain timeout period) - - Dynamic queries for DNS-SD services with cached and updated answers and user notifications - - - Usage: - In most cases, this implementation should work as a 'drop-in' replacement for the original - ESP8266 Multicast DNS code. Adjustments to the existing code would only be needed, if some - of the new features should be used. - - For presenting services: - In 'setup()': - Install a callback for the probing of host (and service) domains via 'MDNS.setProbeResultCallback(probeResultCallback, &userData);' - Register DNS-SD services with 'MDNSResponder::hMDNSService hService = MDNS.addService("MyESP", "http", "tcp", 5000);' - (Install additional callbacks for the probing of these service domains via 'MDNS.setServiceProbeResultCallback(hService, probeResultCallback, &userData);') - Add service TXT items with 'MDNS.addServiceTxt(hService, "c#", "1");' or by installing a service TXT callback - using 'MDNS.setDynamicServiceTxtCallback(dynamicServiceTxtCallback, &userData);' or service specific - 'MDNS.setDynamicServiceTxtCallback(hService, dynamicServiceTxtCallback, &userData);' - Call MDNS.begin("MyHostname"); - - In 'probeResultCallback(MDNSResponder* p_MDNSResponder, const char* p_pcDomain, MDNSResponder:hMDNSService p_hService, bool p_bProbeResult, void* p_pUserdata)': - Check the probe result and update the host or service domain name if the probe failed - - In 'dynamicServiceTxtCallback(MDNSResponder* p_MDNSResponder, const hMDNSService p_hService, void* p_pUserdata)': - Add dynamic TXT items by calling 'MDNS.addDynamicServiceTxt(p_hService, "c#", "1");' - - In loop(): - Call 'MDNS.update();' - - - For querying services: - Static: - Call 'uint32_t u32AnswerCount = MDNS.queryService("http", "tcp");' - Iterate answers by: 'for (uint32_t u=0; u<u32AnswerCount; ++u) { const char* pHostname = MDNS.answerHostname(u); }' - You should call MDNS.removeQuery() sometimes later (when the answers are nott needed anymore) - - Dynamic: - Install a dynamic query by calling 'DNSResponder::hMDNSServiceQuery hServiceQuery = MDNS.installServiceQuery("http", "tcp", serviceQueryCallback, &userData);' - The callback 'serviceQueryCallback(MDNSResponder* p_MDNSResponder, const hMDNSServiceQuery p_hServiceQuery, uint32_t p_u32AnswerIndex, - enuServiceQueryAnswerType p_ServiceQueryAnswerType, bool p_bSetContent, void* p_pUserdata)' - is called for any change in the answer set. - Call 'MDNS.removeServiceQuery(hServiceQuery);' when the answers are not needed anymore - - - Reference: - Used mDNS messages: - A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 - AAAA (0x1C): eg. esp8266.local AAAA OP TTL 1234:5678::90 - PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local - PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local - PTR (0x0C, IP4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local - PTR (0x0C, IP6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local - SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local - TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 - - Some NOT used message types: - OPT (0x29): eDNS - NSEC (0x2F): DNSSEC - - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#ifndef MDNS_H -#define MDNS_H - -#include <functional> // for UdpContext.h -#include "WiFiUdp.h" -#include "lwip/udp.h" -#include "debug.h" -#include "include/UdpContext.h" -#include <limits> -#include <PolledTimeout.h> -#include <map> - - -#include "ESP8266WiFi.h" - - -namespace esp8266 -{ - -/** - LEAmDNS -*/ -namespace MDNSImplementation -{ - -//this should be defined at build time -#ifndef ARDUINO_BOARD -#define ARDUINO_BOARD "generic" -#endif - -#define MDNS_IP4_SUPPORT -//#define MDNS_IP6_SUPPORT - - -#ifdef MDNS_IP4_SUPPORT -#define MDNS_IP4_SIZE 4 -#endif -#ifdef MDNS_IP6_SUPPORT -#define MDNS_IP6_SIZE 16 -#endif -/* - Maximum length for all service txts for one service -*/ -#define MDNS_SERVICE_TXT_MAXLENGTH 1300 -/* - Maximum length for a full domain name eg. MyESP._http._tcp.local -*/ -#define MDNS_DOMAIN_MAXLENGTH 256 -/* - Maximum length of on label in a domain name (length info fits into 6 bits) -*/ -#define MDNS_DOMAIN_LABEL_MAXLENGTH 63 -/* - Maximum length of a service name eg. http -*/ -#define MDNS_SERVICE_NAME_LENGTH 15 -/* - Maximum length of a service protocol name eg. tcp -*/ -#define MDNS_SERVICE_PROTOCOL_LENGTH 3 -/* - Default timeout for static service queries -*/ -#define MDNS_QUERYSERVICES_WAIT_TIME 1000 - - -/** - MDNSResponder -*/ -class MDNSResponder -{ -public: - /* INTERFACE */ - MDNSResponder(void); - virtual ~MDNSResponder(void); - - // Start the MDNS responder by setting the default hostname - // Later call MDNS::update() in every 'loop' to run the process loop - // (probing, announcing, responding, ...) - // if interfaceAddress is not specified, default interface is STA, or AP when STA is not set - bool begin(const char* p_pcHostname, const IPAddress& p_IPAddress = INADDR_ANY, uint32_t p_u32TTL = 120 /*ignored*/); - bool begin(const String& p_strHostname, const IPAddress& p_IPAddress = INADDR_ANY, uint32_t p_u32TTL = 120 /*ignored*/) - { - return begin(p_strHostname.c_str(), p_IPAddress, p_u32TTL); - } - - // Finish MDNS processing - bool close(void); - // for esp32 compatability - bool end(void); - // Change hostname (probing is restarted) - bool setHostname(const char* p_pcHostname); - // for compatibility... - bool setHostname(const String& p_strHostname); - - bool isRunning(void) - { - return (m_pUDPContext != 0); - } - - /** - hMDNSService (opaque handle to access the service) - */ - typedef const void* hMDNSService; - - // Add a new service to the MDNS responder. If no name (instance name) is given (p_pcName = 0) - // the current hostname is used. If the hostname is changed later, the instance names for - // these 'auto-named' services are changed to the new name also (and probing is restarted). - // The usual '_' before p_pcService (eg. http) and protocol (eg. tcp) may be given. - hMDNSService addService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port); - // Removes a service from the MDNS responder - bool removeService(const hMDNSService p_hService); - bool removeService(const char* p_pcInstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol); - // for compatibility... - bool addService(const String& p_strServiceName, - const String& p_strProtocol, - uint16_t p_u16Port); - - - // Change the services instance name (and restart probing). - bool setServiceName(const hMDNSService p_hService, - const char* p_pcInstanceName); - //for compatibility - //Warning: this has the side effect of changing the hostname. - //TODO: implement instancename different from hostname - void setInstanceName(const char* p_pcHostname) - { - setHostname(p_pcHostname); - } - // for esp32 compatibilty - void setInstanceName(const String& s_pcHostname) - { - setInstanceName(s_pcHostname.c_str()); - } - - /** - hMDNSTxt (opaque handle to access the TXT items) - */ - typedef void* hMDNSTxt; - - // 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); - - // Remove an existing (static) MDNS TXT item from the service - bool removeServiceTxt(const hMDNSService p_hService, - const hMDNSTxt p_hTxt); - bool removeServiceTxt(const hMDNSService p_hService, - const char* p_pcKey); - bool removeServiceTxt(const char* p_pcinstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol, - const char* p_pcKey); - // for compatibility... - bool addServiceTxt(const char* p_pcService, - const char* p_pcProtocol, - const char* p_pcKey, - const char* p_pcValue); - bool addServiceTxt(const String& p_strService, - const String& p_strProtocol, - const String& p_strKey, - const String& p_strValue); - - /** - MDNSDynamicServiceTxtCallbackFn - Callback function for dynamic MDNS TXT items - */ - - typedef std::function<void(const hMDNSService p_hService)> MDNSDynamicServiceTxtCallbackFunc; - - // Set a global callback for dynamic MDNS TXT items. The callback function is called - // every time, a TXT item is needed for one of the installed services. - bool setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFunc p_fnCallback); - // Set a service specific callback for dynamic MDNS TXT items. The callback function - // is called every time, a TXT item is needed for the given service. - bool setDynamicServiceTxtCallback(const hMDNSService p_hService, - MDNSDynamicServiceTxtCallbackFunc p_fnCallback); - - // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service - // Dynamic TXT items are removed right after one-time use. So they need to be added - // every time the value s needed (via callback). - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value); - - // Perform a (static) service query. The function returns after p_u16Timeout milliseconds - // The answers (the number of received answers is returned) can be retrieved by calling - // - answerHostname (or hostname) - // - answerIP (or IP) - // - answerPort (or port) - uint32_t queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); - bool removeQuery(void); - // for compatibility... - uint32_t queryService(const String& p_strService, - const String& p_strProtocol); - - const char* answerHostname(const uint32_t p_u32AnswerIndex); - IPAddress answerIP(const uint32_t p_u32AnswerIndex); - uint16_t answerPort(const uint32_t p_u32AnswerIndex); - // for compatibility... - String hostname(const uint32_t p_u32AnswerIndex); - IPAddress IP(const uint32_t p_u32AnswerIndex); - uint16_t port(const uint32_t p_u32AnswerIndex); - - /** - hMDNSServiceQuery (opaque handle to access dynamic service queries) - */ - typedef const void* hMDNSServiceQuery; - - /** - enuServiceQueryAnswerType - */ - typedef enum _enuServiceQueryAnswerType - { - ServiceQueryAnswerType_ServiceDomain = (1 << 0), // Service instance name - ServiceQueryAnswerType_HostDomainAndPort = (1 << 1), // Host domain and service port - ServiceQueryAnswerType_Txts = (1 << 2), // TXT items -#ifdef MDNS_IP4_SUPPORT - ServiceQueryAnswerType_IP4Address = (1 << 3), // IP4 address -#endif -#ifdef MDNS_IP6_SUPPORT - ServiceQueryAnswerType_IP6Address = (1 << 4), // IP6 address -#endif - } enuServiceQueryAnswerType; - - enum class AnswerType : uint32_t - { - Unknown = 0, - ServiceDomain = ServiceQueryAnswerType_ServiceDomain, - HostDomainAndPort = ServiceQueryAnswerType_HostDomainAndPort, - Txt = ServiceQueryAnswerType_Txts, -#ifdef MDNS_IP4_SUPPORT - IP4Address = ServiceQueryAnswerType_IP4Address, -#endif -#ifdef MDNS_IP6_SUPPORT - IP6Address = ServiceQueryAnswerType_IP6Address, -#endif - }; - - /** - MDNSServiceQueryCallbackFn - Callback function for received answers for dynamic service queries - */ - struct MDNSServiceInfo; // forward declaration - typedef std::function<void(const MDNSServiceInfo& mdnsServiceInfo, - AnswerType answerType, // flag for the updated answer item - bool p_bSetContent // true: Answer component set, false: component deleted - )> MDNSServiceQueryCallbackFunc; - - // Install a dynamic service query. For every received answer (part) the given callback - // function is called. The query will be updated every time, the TTL for an answer - // has timed-out. - // The answers can also be retrieved by calling - // - answerCount - // - answerServiceDomain - // - hasAnswerHostDomain/answerHostDomain - // - hasAnswerIP4Address/answerIP4Address - // - hasAnswerIP6Address/answerIP6Address - // - hasAnswerPort/answerPort - // - hasAnswerTxts/answerTxts - hMDNSServiceQuery installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - MDNSServiceQueryCallbackFunc p_fnCallback); - // Remove a dynamic service query - bool removeServiceQuery(hMDNSServiceQuery p_hServiceQuery); - - uint32_t answerCount(const hMDNSServiceQuery p_hServiceQuery); - std::vector<MDNSResponder::MDNSServiceInfo> answerInfo(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery); - - const char* answerServiceDomain(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerHostDomain(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - const char* answerHostDomain(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); -#ifdef MDNS_IP4_SUPPORT - bool hasAnswerIP4Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIP4AddressCount(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIP4Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); -#endif -#ifdef MDNS_IP6_SUPPORT - bool hasAnswerIP6Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIP6AddressCount(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIP6Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); -#endif - bool hasAnswerPort(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - uint16_t answerPort(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerTxts(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - // Get the TXT items as a ';'-separated string - const char* answerTxts(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - - /** - MDNSProbeResultCallbackFn - Callback function for (host and service domain) probe results - */ - typedef std::function<void(const char* p_pcDomainName, - bool p_bProbeResult)> MDNSHostProbeFn; - - typedef std::function<void(MDNSResponder& resp, - const char* p_pcDomainName, - bool p_bProbeResult)> MDNSHostProbeFn1; - - typedef std::function<void(const char* p_pcServiceName, - const hMDNSService p_hMDNSService, - bool p_bProbeResult)> MDNSServiceProbeFn; - - typedef std::function<void(MDNSResponder& resp, - const char* p_pcServiceName, - const hMDNSService p_hMDNSService, - bool p_bProbeResult)> MDNSServiceProbeFn1; - - // Set a global callback function for host and service probe results - // The callback function is called, when the probing for the host domain - // (or a service domain, which hasn't got a service specific callback) - // Succeeds or fails. - // In case of failure, the failed domain name should be changed. - bool setHostProbeResultCallback(MDNSHostProbeFn p_fnCallback); - bool setHostProbeResultCallback(MDNSHostProbeFn1 p_fnCallback); - - // Set a service specific probe result callback - bool setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService, - MDNSServiceProbeFn p_fnCallback); - bool setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService, - MDNSServiceProbeFn1 p_fnCallback); - - // Application should call this whenever AP is configured/disabled - bool notifyAPChange(void); - - // 'update' should be called in every 'loop' to run the MDNS processing - bool update(void); - - // 'announce' can be called every time, the configuration of some service - // changes. Mainly, this would be changed content of TXT items. - bool announce(void); - - // Enable OTA update - hMDNSService enableArduino(uint16_t p_u16Port, - bool p_bAuthUpload = false); - - // Domain name helper - static bool indexDomain(char*& p_rpcDomain, - const char* p_pcDivider = "-", - const char* p_pcDefaultDomain = 0); - - /** STRUCTS **/ - -public: - /** - MDNSServiceInfo, used in application callbacks - */ - struct MDNSServiceInfo - { - MDNSServiceInfo(MDNSResponder& p_pM, MDNSResponder::hMDNSServiceQuery p_hS, uint32_t p_u32A) - : p_pMDNSResponder(p_pM), - p_hServiceQuery(p_hS), - p_u32AnswerIndex(p_u32A) - {}; - struct CompareKey - { - bool operator()(char const *a, char const *b) const - { - return strcmp(a, b) < 0; - } - }; - using KeyValueMap = std::map<const char*, const char*, CompareKey>; - protected: - MDNSResponder& p_pMDNSResponder; - MDNSResponder::hMDNSServiceQuery p_hServiceQuery; - uint32_t p_u32AnswerIndex; - KeyValueMap keyValueMap; - public: - const char* serviceDomain() - { - return p_pMDNSResponder.answerServiceDomain(p_hServiceQuery, p_u32AnswerIndex); - }; - bool hostDomainAvailable() - { - return (p_pMDNSResponder.hasAnswerHostDomain(p_hServiceQuery, p_u32AnswerIndex)); - } - const char* hostDomain() - { - return (hostDomainAvailable()) ? - p_pMDNSResponder.answerHostDomain(p_hServiceQuery, p_u32AnswerIndex) : nullptr; - }; - bool hostPortAvailable() - { - return (p_pMDNSResponder.hasAnswerPort(p_hServiceQuery, p_u32AnswerIndex)); - } - uint16_t hostPort() - { - return (hostPortAvailable()) ? - p_pMDNSResponder.answerPort(p_hServiceQuery, p_u32AnswerIndex) : 0; - }; - bool IP4AddressAvailable() - { - return (p_pMDNSResponder.hasAnswerIP4Address(p_hServiceQuery, p_u32AnswerIndex)); - } - std::vector<IPAddress> IP4Adresses() - { - std::vector<IPAddress> internalIP; - if (IP4AddressAvailable()) - { - uint16_t cntIP4Adress = p_pMDNSResponder.answerIP4AddressCount(p_hServiceQuery, p_u32AnswerIndex); - for (uint32_t u2 = 0; u2 < cntIP4Adress; ++u2) - { - internalIP.emplace_back(p_pMDNSResponder.answerIP4Address(p_hServiceQuery, p_u32AnswerIndex, u2)); - } - } - return internalIP; - }; - bool txtAvailable() - { - return (p_pMDNSResponder.hasAnswerTxts(p_hServiceQuery, p_u32AnswerIndex)); - } - const char* strKeyValue() - { - return (txtAvailable()) ? - p_pMDNSResponder.answerTxts(p_hServiceQuery, p_u32AnswerIndex) : nullptr; - }; - const KeyValueMap& keyValues() - { - if (txtAvailable() && keyValueMap.size() == 0) - { - for (auto kv = p_pMDNSResponder._answerKeyValue(p_hServiceQuery, p_u32AnswerIndex); kv != nullptr; kv = kv->m_pNext) - { - keyValueMap.emplace(std::pair<const char*, const char*>(kv->m_pcKey, kv->m_pcValue)); - } - } - return keyValueMap; - } - const char* value(const char* key) - { - char* result = nullptr; - - for (stcMDNSServiceTxt* pTxt = p_pMDNSResponder._answerKeyValue(p_hServiceQuery, p_u32AnswerIndex); pTxt; pTxt = pTxt->m_pNext) - { - if ((key) && - (0 == strcmp(pTxt->m_pcKey, key))) - { - result = pTxt->m_pcValue; - break; - } - } - return result; - } - }; -protected: - - /** - stcMDNSServiceTxt - */ - struct stcMDNSServiceTxt - { - stcMDNSServiceTxt* m_pNext; - char* m_pcKey; - char* m_pcValue; - bool m_bTemp; - - stcMDNSServiceTxt(const char* p_pcKey = 0, - const char* p_pcValue = 0, - bool p_bTemp = false); - stcMDNSServiceTxt(const stcMDNSServiceTxt& p_Other); - ~stcMDNSServiceTxt(void); - - stcMDNSServiceTxt& operator=(const stcMDNSServiceTxt& p_Other); - bool clear(void); - - char* allocKey(size_t p_stLength); - bool setKey(const char* p_pcKey, - size_t p_stLength); - bool setKey(const char* p_pcKey); - bool releaseKey(void); - - char* allocValue(size_t p_stLength); - bool setValue(const char* p_pcValue, - size_t p_stLength); - bool setValue(const char* p_pcValue); - bool releaseValue(void); - - bool set(const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp = false); - - bool update(const char* p_pcValue); - - size_t length(void) const; - }; - - /** - stcMDNSTxts - */ - struct stcMDNSServiceTxts - { - stcMDNSServiceTxt* m_pTxts; - - stcMDNSServiceTxts(void); - stcMDNSServiceTxts(const stcMDNSServiceTxts& p_Other); - ~stcMDNSServiceTxts(void); - - stcMDNSServiceTxts& operator=(const stcMDNSServiceTxts& p_Other); - - bool clear(void); - - bool add(stcMDNSServiceTxt* p_pTxt); - bool remove(stcMDNSServiceTxt* p_pTxt); - - bool removeTempTxts(void); - - stcMDNSServiceTxt* find(const char* p_pcKey); - const stcMDNSServiceTxt* find(const char* p_pcKey) const; - stcMDNSServiceTxt* find(const stcMDNSServiceTxt* p_pTxt); - - uint16_t length(void) const; - - size_t c_strLength(void) const; - bool c_str(char* p_pcBuffer); - - size_t bufferLength(void) const; - bool buffer(char* p_pcBuffer); - - bool compare(const stcMDNSServiceTxts& p_Other) const; - bool operator==(const stcMDNSServiceTxts& p_Other) const; - bool operator!=(const stcMDNSServiceTxts& p_Other) const; - }; - - /** - enuContentFlags - */ - typedef enum _enuContentFlags - { - // Host - ContentFlag_A = 0x01, - ContentFlag_PTR_IP4 = 0x02, - ContentFlag_PTR_IP6 = 0x04, - ContentFlag_AAAA = 0x08, - // Service - ContentFlag_PTR_TYPE = 0x10, - ContentFlag_PTR_NAME = 0x20, - ContentFlag_TXT = 0x40, - ContentFlag_SRV = 0x80, - } enuContentFlags; - - /** - stcMDNS_MsgHeader - */ - struct stcMDNS_MsgHeader - { - uint16_t m_u16ID; // Identifier - bool m_1bQR : 1; // Query/Response flag - unsigned char m_4bOpcode : 4; // Operation code - bool m_1bAA : 1; // Authoritative Answer flag - bool m_1bTC : 1; // Truncation flag - bool m_1bRD : 1; // Recursion desired - bool m_1bRA : 1; // Recursion available - unsigned char m_3bZ : 3; // Zero - unsigned char m_4bRCode : 4; // Response code - uint16_t m_u16QDCount; // Question count - uint16_t m_u16ANCount; // Answer count - uint16_t m_u16NSCount; // Authority Record count - uint16_t m_u16ARCount; // Additional Record count - - stcMDNS_MsgHeader(uint16_t p_u16ID = 0, - bool p_bQR = false, - unsigned char p_ucOpcode = 0, - bool p_bAA = false, - bool p_bTC = false, - bool p_bRD = false, - bool p_bRA = false, - unsigned char p_ucRCode = 0, - uint16_t p_u16QDCount = 0, - uint16_t p_u16ANCount = 0, - uint16_t p_u16NSCount = 0, - uint16_t p_u16ARCount = 0); - }; - - /** - stcMDNS_RRDomain - */ - struct stcMDNS_RRDomain - { - char m_acName[MDNS_DOMAIN_MAXLENGTH]; // Encoded domain name - uint16_t m_u16NameLength; // Length (incl. '\0') - - stcMDNS_RRDomain(void); - stcMDNS_RRDomain(const stcMDNS_RRDomain& p_Other); - - stcMDNS_RRDomain& operator=(const stcMDNS_RRDomain& p_Other); - - bool clear(void); - - bool addLabel(const char* p_pcLabel, - bool p_bPrependUnderline = false); - - bool compare(const stcMDNS_RRDomain& p_Other) const; - bool operator==(const stcMDNS_RRDomain& p_Other) const; - bool operator!=(const stcMDNS_RRDomain& p_Other) const; - bool operator>(const stcMDNS_RRDomain& p_Other) const; - - size_t c_strLength(void) const; - bool c_str(char* p_pcBuffer); - }; - - /** - stcMDNS_RRAttributes - */ - struct stcMDNS_RRAttributes - { - uint16_t m_u16Type; // Type - uint16_t m_u16Class; // Class, nearly always 'IN' - - stcMDNS_RRAttributes(uint16_t p_u16Type = 0, - uint16_t p_u16Class = 1 /*DNS_RRCLASS_IN Internet*/); - stcMDNS_RRAttributes(const stcMDNS_RRAttributes& p_Other); - - stcMDNS_RRAttributes& operator=(const stcMDNS_RRAttributes& p_Other); - }; - - /** - stcMDNS_RRHeader - */ - struct stcMDNS_RRHeader - { - stcMDNS_RRDomain m_Domain; - stcMDNS_RRAttributes m_Attributes; - - stcMDNS_RRHeader(void); - stcMDNS_RRHeader(const stcMDNS_RRHeader& p_Other); - - stcMDNS_RRHeader& operator=(const stcMDNS_RRHeader& p_Other); - - bool clear(void); - }; - - /** - stcMDNS_RRQuestion - */ - struct stcMDNS_RRQuestion - { - stcMDNS_RRQuestion* m_pNext; - stcMDNS_RRHeader m_Header; - bool m_bUnicast; // Unicast reply requested - - stcMDNS_RRQuestion(void); - }; - - /** - enuAnswerType - */ - typedef enum _enuAnswerType - { - AnswerType_A, - AnswerType_PTR, - AnswerType_TXT, - AnswerType_AAAA, - AnswerType_SRV, - AnswerType_Generic - } enuAnswerType; - - /** - stcMDNS_RRAnswer - */ - struct stcMDNS_RRAnswer - { - stcMDNS_RRAnswer* m_pNext; - const enuAnswerType m_AnswerType; - stcMDNS_RRHeader m_Header; - bool m_bCacheFlush; // Cache flush command bit - uint32_t m_u32TTL; // Validity time in seconds - - virtual ~stcMDNS_RRAnswer(void); - - enuAnswerType answerType(void) const; - - bool clear(void); - - protected: - stcMDNS_RRAnswer(enuAnswerType p_AnswerType, - const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - }; - -#ifdef MDNS_IP4_SUPPORT - /** - stcMDNS_RRAnswerA - */ - struct stcMDNS_RRAnswerA : public stcMDNS_RRAnswer - { - IPAddress m_IPAddress; - - stcMDNS_RRAnswerA(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - ~stcMDNS_RRAnswerA(void); - - bool clear(void); - }; -#endif - - /** - stcMDNS_RRAnswerPTR - */ - struct stcMDNS_RRAnswerPTR : public stcMDNS_RRAnswer - { - stcMDNS_RRDomain m_PTRDomain; - - stcMDNS_RRAnswerPTR(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - ~stcMDNS_RRAnswerPTR(void); - - bool clear(void); - }; - - /** - stcMDNS_RRAnswerTXT - */ - struct stcMDNS_RRAnswerTXT : public stcMDNS_RRAnswer - { - stcMDNSServiceTxts m_Txts; - - stcMDNS_RRAnswerTXT(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - ~stcMDNS_RRAnswerTXT(void); - - bool clear(void); - }; - -#ifdef MDNS_IP6_SUPPORT - /** - stcMDNS_RRAnswerAAAA - */ - struct stcMDNS_RRAnswerAAAA : public stcMDNS_RRAnswer - { - //TODO: IP6Address m_IPAddress; - - stcMDNS_RRAnswerAAAA(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - ~stcMDNS_RRAnswerAAAA(void); - - bool clear(void); - }; -#endif - - /** - stcMDNS_RRAnswerSRV - */ - struct stcMDNS_RRAnswerSRV : public stcMDNS_RRAnswer - { - uint16_t m_u16Priority; - uint16_t m_u16Weight; - uint16_t m_u16Port; - stcMDNS_RRDomain m_SRVDomain; - - stcMDNS_RRAnswerSRV(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - ~stcMDNS_RRAnswerSRV(void); - - bool clear(void); - }; - - /** - stcMDNS_RRAnswerGeneric - */ - struct stcMDNS_RRAnswerGeneric : public stcMDNS_RRAnswer - { - uint16_t m_u16RDLength; // Length of variable answer - uint8_t* m_pu8RDData; // Offset of start of variable answer in packet - - stcMDNS_RRAnswerGeneric(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - ~stcMDNS_RRAnswerGeneric(void); - - bool clear(void); - }; - - - /** - enuProbingStatus - */ - typedef enum _enuProbingStatus - { - ProbingStatus_WaitingForData, - ProbingStatus_ReadyToStart, - ProbingStatus_InProgress, - ProbingStatus_Done - } enuProbingStatus; - - /** - stcProbeInformation - */ - struct stcProbeInformation - { - enuProbingStatus m_ProbingStatus; - uint8_t m_u8SentCount; // Used for probes and announcements - esp8266::polledTimeout::oneShotMs m_Timeout; // Used for probes and announcements - //clsMDNSTimeFlag m_TimeFlag; // Used for probes and announcements - bool m_bConflict; - bool m_bTiebreakNeeded; - MDNSHostProbeFn m_fnHostProbeResultCallback; - MDNSServiceProbeFn m_fnServiceProbeResultCallback; - - stcProbeInformation(void); - - bool clear(bool p_bClearUserdata = false); - }; - - - /** - stcMDNSService - */ - struct stcMDNSService - { - stcMDNSService* m_pNext; - char* m_pcName; - bool m_bAutoName; // Name was set automatically to hostname (if no name was supplied) - char* m_pcService; - char* m_pcProtocol; - uint16_t m_u16Port; - uint8_t m_u8ReplyMask; - stcMDNSServiceTxts m_Txts; - MDNSDynamicServiceTxtCallbackFunc m_fnTxtCallback; - stcProbeInformation m_ProbeInformation; - - stcMDNSService(const char* p_pcName = 0, - const char* p_pcService = 0, - const char* p_pcProtocol = 0); - ~stcMDNSService(void); - - bool setName(const char* p_pcName); - bool releaseName(void); - - bool setService(const char* p_pcService); - bool releaseService(void); - - bool setProtocol(const char* p_pcProtocol); - bool releaseProtocol(void); - }; - - /** - stcMDNSServiceQuery - */ - struct stcMDNSServiceQuery - { - /** - stcAnswer - */ - struct stcAnswer - { - /** - stcTTL - */ - struct stcTTL - { - /** - timeoutLevel_t - */ - typedef uint8_t timeoutLevel_t; - /** - TIMEOUTLEVELs - */ - const timeoutLevel_t TIMEOUTLEVEL_UNSET = 0; - const timeoutLevel_t TIMEOUTLEVEL_BASE = 80; - const timeoutLevel_t TIMEOUTLEVEL_INTERVAL = 5; - const timeoutLevel_t TIMEOUTLEVEL_FINAL = 100; - - uint32_t m_u32TTL; - esp8266::polledTimeout::oneShotMs m_TTLTimeout; - timeoutLevel_t m_timeoutLevel; - - stcTTL(void); - bool set(uint32_t p_u32TTL); - - bool flagged(void); - bool restart(void); - - bool prepareDeletion(void); - bool finalTimeoutLevel(void) const; - - unsigned long timeout(void) const; - }; -#ifdef MDNS_IP4_SUPPORT - /** - stcIP4Address - */ - struct stcIP4Address - { - stcIP4Address* m_pNext; - IPAddress m_IPAddress; - stcTTL m_TTL; - - stcIP4Address(IPAddress p_IPAddress, - uint32_t p_u32TTL = 0); - }; -#endif -#ifdef MDNS_IP6_SUPPORT - /** - stcIP6Address - */ - struct stcIP6Address - { - stcIP6Address* m_pNext; - IP6Address m_IPAddress; - stcTTL m_TTL; - - stcIP6Address(IPAddress p_IPAddress, - uint32_t p_u32TTL = 0); - }; -#endif - - stcAnswer* m_pNext; - // The service domain is the first 'answer' (from PTR answer, using service and protocol) to be set - // Defines the key for additional answer, like host domain, etc. - stcMDNS_RRDomain m_ServiceDomain; // 1. level answer (PTR), eg. MyESP._http._tcp.local - char* m_pcServiceDomain; - stcTTL m_TTLServiceDomain; - stcMDNS_RRDomain m_HostDomain; // 2. level answer (SRV, using service domain), eg. esp8266.local - char* m_pcHostDomain; - uint16_t m_u16Port; // 2. level answer (SRV, using service domain), eg. 5000 - stcTTL m_TTLHostDomainAndPort; - stcMDNSServiceTxts m_Txts; // 2. level answer (TXT, using service domain), eg. c#=1 - char* m_pcTxts; - stcTTL m_TTLTxts; -#ifdef MDNS_IP4_SUPPORT - stcIP4Address* m_pIP4Addresses; // 3. level answer (A, using host domain), eg. 123.456.789.012 -#endif -#ifdef MDNS_IP6_SUPPORT - stcIP6Address* m_pIP6Addresses; // 3. level answer (AAAA, using host domain), eg. 1234::09 -#endif - uint32_t m_u32ContentFlags; - - stcAnswer(void); - ~stcAnswer(void); - - bool clear(void); - - char* allocServiceDomain(size_t p_stLength); - bool releaseServiceDomain(void); - - char* allocHostDomain(size_t p_stLength); - bool releaseHostDomain(void); - - char* allocTxts(size_t p_stLength); - bool releaseTxts(void); - -#ifdef MDNS_IP4_SUPPORT - bool releaseIP4Addresses(void); - bool addIP4Address(stcIP4Address* p_pIP4Address); - bool removeIP4Address(stcIP4Address* p_pIP4Address); - const stcIP4Address* findIP4Address(const IPAddress& p_IPAddress) const; - stcIP4Address* findIP4Address(const IPAddress& p_IPAddress); - uint32_t IP4AddressCount(void) const; - const stcIP4Address* IP4AddressAtIndex(uint32_t p_u32Index) const; - stcIP4Address* IP4AddressAtIndex(uint32_t p_u32Index); -#endif -#ifdef MDNS_IP6_SUPPORT - bool releaseIP6Addresses(void); - bool addIP6Address(stcIP6Address* p_pIP6Address); - bool removeIP6Address(stcIP6Address* p_pIP6Address); - const stcIP6Address* findIP6Address(const IPAddress& p_IPAddress) const; - stcIP6Address* findIP6Address(const IPAddress& p_IPAddress); - uint32_t IP6AddressCount(void) const; - const stcIP6Address* IP6AddressAtIndex(uint32_t p_u32Index) const; - stcIP6Address* IP6AddressAtIndex(uint32_t p_u32Index); -#endif - }; - - stcMDNSServiceQuery* m_pNext; - stcMDNS_RRDomain m_ServiceTypeDomain; // eg. _http._tcp.local - MDNSServiceQueryCallbackFunc m_fnCallback; - bool m_bLegacyQuery; - uint8_t m_u8SentCount; - esp8266::polledTimeout::oneShotMs m_ResendTimeout; - bool m_bAwaitingAnswers; - stcAnswer* m_pAnswers; - - stcMDNSServiceQuery(void); - ~stcMDNSServiceQuery(void); - - bool clear(void); - - uint32_t answerCount(void) const; - const stcAnswer* answerAtIndex(uint32_t p_u32Index) const; - stcAnswer* answerAtIndex(uint32_t p_u32Index); - uint32_t indexOfAnswer(const stcAnswer* p_pAnswer) const; - - bool addAnswer(stcAnswer* p_pAnswer); - bool removeAnswer(stcAnswer* p_pAnswer); - - stcAnswer* findAnswerForServiceDomain(const stcMDNS_RRDomain& p_ServiceDomain); - stcAnswer* findAnswerForHostDomain(const stcMDNS_RRDomain& p_HostDomain); - }; - - /** - stcMDNSSendParameter - */ - struct stcMDNSSendParameter - { - protected: - /** - stcDomainCacheItem - */ - struct stcDomainCacheItem - { - stcDomainCacheItem* m_pNext; - const void* m_pHostnameOrService; // Opaque id for host or service domain (pointer) - bool m_bAdditionalData; // Opaque flag for special info (service domain included) - uint16_t m_u16Offset; // Offset in UDP output buffer - - stcDomainCacheItem(const void* p_pHostnameOrService, - bool p_bAdditionalData, - uint32_t p_u16Offset); - }; - - public: - uint16_t m_u16ID; // Query ID (used only in lagacy queries) - stcMDNS_RRQuestion* m_pQuestions; // A list of queries - uint8_t m_u8HostReplyMask; // Flags for reply components/answers - bool m_bLegacyQuery; // Flag: Legacy query - bool m_bResponse; // Flag: Response to a query - bool m_bAuthorative; // Flag: Authorative (owner) response - bool m_bCacheFlush; // Flag: Clients should flush their caches - bool m_bUnicast; // Flag: Unicast response - bool m_bUnannounce; // Flag: Unannounce service - uint16_t m_u16Offset; // Current offset in UDP write buffer (mainly for domain cache) - stcDomainCacheItem* m_pDomainCacheItems; // Cached host and service domains - - stcMDNSSendParameter(void); - ~stcMDNSSendParameter(void); - - bool clear(void); - - bool shiftOffset(uint16_t p_u16Shift); - - bool addDomainCacheItem(const void* p_pHostnameOrService, - bool p_bAdditionalData, - uint16_t p_u16Offset); - uint16_t findCachedDomainOffset(const void* p_pHostnameOrService, - bool p_bAdditionalData) const; - }; - - // Instance variables - stcMDNSService* m_pServices; - UdpContext* m_pUDPContext; - char* m_pcHostname; - stcMDNSServiceQuery* m_pServiceQueries; - WiFiEventHandler m_DisconnectedHandler; - WiFiEventHandler m_GotIPHandler; - MDNSDynamicServiceTxtCallbackFunc m_fnServiceTxtCallback; - bool m_bPassivModeEnabled; - stcProbeInformation m_HostProbeInformation; - CONST netif* m_netif; // network interface to run on - - /** CONTROL **/ - /* MAINTENANCE */ - bool _process(bool p_bUserContext); - bool _restart(void); - - /* RECEIVING */ - bool _parseMessage(void); - bool _parseQuery(const stcMDNS_MsgHeader& p_Header); - - bool _parseResponse(const stcMDNS_MsgHeader& p_Header); - bool _processAnswers(const stcMDNS_RRAnswer* p_pPTRAnswers); - bool _processPTRAnswer(const stcMDNS_RRAnswerPTR* p_pPTRAnswer, - bool& p_rbFoundNewKeyAnswer); - bool _processSRVAnswer(const stcMDNS_RRAnswerSRV* p_pSRVAnswer, - bool& p_rbFoundNewKeyAnswer); - bool _processTXTAnswer(const stcMDNS_RRAnswerTXT* p_pTXTAnswer); -#ifdef MDNS_IP4_SUPPORT - bool _processAAnswer(const stcMDNS_RRAnswerA* p_pAAnswer); -#endif -#ifdef MDNS_IP6_SUPPORT - bool _processAAAAAnswer(const stcMDNS_RRAnswerAAAA* p_pAAAAAnswer); -#endif - - /* PROBING */ - bool _updateProbeStatus(void); - bool _resetProbeStatus(bool p_bRestart = true); - bool _hasProbesWaitingForAnswers(void) const; - bool _sendHostProbe(void); - bool _sendServiceProbe(stcMDNSService& p_rService); - bool _cancelProbingForHost(void); - bool _cancelProbingForService(stcMDNSService& p_rService); - - /* ANNOUNCE */ - bool _announce(bool p_bAnnounce, - bool p_bIncludeServices); - bool _announceService(stcMDNSService& p_rService, - bool p_bAnnounce = true); - - /* SERVICE QUERY CACHE */ - bool _hasServiceQueriesWaitingForAnswers(void) const; - bool _checkServiceQueryCache(void); - - /** TRANSFER **/ - /* SENDING */ - bool _sendMDNSMessage(stcMDNSSendParameter& p_SendParameter); - bool _sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParameter& p_rSendParameter); - bool _prepareMDNSMessage(stcMDNSSendParameter& p_SendParameter, - IPAddress p_IPAddress); - bool _sendMDNSServiceQuery(const stcMDNSServiceQuery& p_ServiceQuery); - bool _sendMDNSQuery(const stcMDNS_RRDomain& p_QueryDomain, - uint16_t p_u16QueryType, - stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers = 0); - - const IPAddress _getResponseMulticastInterface() const - { - return IPAddress(m_netif->ip_addr); - } - - uint8_t _replyMaskForHost(const stcMDNS_RRHeader& p_RRHeader, - bool* p_pbFullNameMatch = 0) const; - uint8_t _replyMaskForService(const stcMDNS_RRHeader& p_RRHeader, - const stcMDNSService& p_Service, - bool* p_pbFullNameMatch = 0) const; - - /* RESOURCE RECORD */ - bool _readRRQuestion(stcMDNS_RRQuestion& p_rQuestion); - bool _readRRAnswer(stcMDNS_RRAnswer*& p_rpAnswer); -#ifdef MDNS_IP4_SUPPORT - bool _readRRAnswerA(stcMDNS_RRAnswerA& p_rRRAnswerA, - uint16_t p_u16RDLength); -#endif - bool _readRRAnswerPTR(stcMDNS_RRAnswerPTR& p_rRRAnswerPTR, - uint16_t p_u16RDLength); - bool _readRRAnswerTXT(stcMDNS_RRAnswerTXT& p_rRRAnswerTXT, - uint16_t p_u16RDLength); -#ifdef MDNS_IP6_SUPPORT - bool _readRRAnswerAAAA(stcMDNS_RRAnswerAAAA& p_rRRAnswerAAAA, - uint16_t p_u16RDLength); -#endif - bool _readRRAnswerSRV(stcMDNS_RRAnswerSRV& p_rRRAnswerSRV, - uint16_t p_u16RDLength); - bool _readRRAnswerGeneric(stcMDNS_RRAnswerGeneric& p_rRRAnswerGeneric, - uint16_t p_u16RDLength); - - bool _readRRHeader(stcMDNS_RRHeader& p_rHeader); - bool _readRRDomain(stcMDNS_RRDomain& p_rRRDomain); - bool _readRRDomain_Loop(stcMDNS_RRDomain& p_rRRDomain, - uint8_t p_u8Depth); - bool _readRRAttributes(stcMDNS_RRAttributes& p_rAttributes); - - /* DOMAIN NAMES */ - bool _buildDomainForHost(const char* p_pcHostname, - stcMDNS_RRDomain& p_rHostDomain) const; - bool _buildDomainForDNSSD(stcMDNS_RRDomain& p_rDNSSDDomain) const; - bool _buildDomainForService(const stcMDNSService& p_Service, - bool p_bIncludeName, - stcMDNS_RRDomain& p_rServiceDomain) const; - bool _buildDomainForService(const char* p_pcService, - const char* p_pcProtocol, - stcMDNS_RRDomain& p_rServiceDomain) const; -#ifdef MDNS_IP4_SUPPORT - bool _buildDomainForReverseIP4(IPAddress p_IP4Address, - stcMDNS_RRDomain& p_rReverseIP4Domain) const; -#endif -#ifdef MDNS_IP6_SUPPORT - bool _buildDomainForReverseIP6(IPAddress p_IP4Address, - stcMDNS_RRDomain& p_rReverseIP6Domain) const; -#endif - - /* UDP */ - bool _udpReadBuffer(unsigned char* p_pBuffer, - size_t p_stLength); - bool _udpRead8(uint8_t& p_ru8Value); - bool _udpRead16(uint16_t& p_ru16Value); - bool _udpRead32(uint32_t& p_ru32Value); - - bool _udpAppendBuffer(const unsigned char* p_pcBuffer, - size_t p_stLength); - bool _udpAppend8(uint8_t p_u8Value); - bool _udpAppend16(uint16_t p_u16Value); - bool _udpAppend32(uint32_t p_u32Value); - -#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER - bool _udpDump(bool p_bMovePointer = false); - bool _udpDump(unsigned p_uOffset, - unsigned p_uLength); -#endif - - /* READ/WRITE MDNS STRUCTS */ - bool _readMDNSMsgHeader(stcMDNS_MsgHeader& p_rMsgHeader); - - bool _write8(uint8_t p_u8Value, - stcMDNSSendParameter& p_rSendParameter); - bool _write16(uint16_t p_u16Value, - stcMDNSSendParameter& p_rSendParameter); - bool _write32(uint32_t p_u32Value, - stcMDNSSendParameter& p_rSendParameter); - - bool _writeMDNSMsgHeader(const stcMDNS_MsgHeader& p_MsgHeader, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSRRAttributes(const stcMDNS_RRAttributes& p_Attributes, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSRRDomain(const stcMDNS_RRDomain& p_Domain, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSHostDomain(const char* m_pcHostname, - bool p_bPrependRDLength, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSServiceDomain(const stcMDNSService& p_Service, - bool p_bIncludeName, - bool p_bPrependRDLength, - stcMDNSSendParameter& p_rSendParameter); - - bool _writeMDNSQuestion(stcMDNS_RRQuestion& p_Question, - stcMDNSSendParameter& p_rSendParameter); - -#ifdef MDNS_IP4_SUPPORT - bool _writeMDNSAnswer_A(IPAddress p_IPAddress, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSAnswer_PTR_IP4(IPAddress p_IPAddress, - stcMDNSSendParameter& p_rSendParameter); -#endif - bool _writeMDNSAnswer_PTR_TYPE(stcMDNSService& p_rService, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSAnswer_PTR_NAME(stcMDNSService& p_rService, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSAnswer_TXT(stcMDNSService& p_rService, - stcMDNSSendParameter& p_rSendParameter); -#ifdef MDNS_IP6_SUPPORT - bool _writeMDNSAnswer_AAAA(IPAddress p_IPAddress, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSAnswer_PTR_IP6(IPAddress p_IPAddress, - stcMDNSSendParameter& p_rSendParameter); -#endif - bool _writeMDNSAnswer_SRV(stcMDNSService& p_rService, - stcMDNSSendParameter& p_rSendParameter); - - /** HELPERS **/ - /* UDP CONTEXT */ - bool _callProcess(void); - bool _allocUDPContext(void); - bool _releaseUDPContext(void); - - /* SERVICE QUERY */ - stcMDNSServiceQuery* _allocServiceQuery(void); - bool _removeServiceQuery(stcMDNSServiceQuery* p_pServiceQuery); - bool _removeLegacyServiceQuery(void); - stcMDNSServiceQuery* _findServiceQuery(hMDNSServiceQuery p_hServiceQuery); - stcMDNSServiceQuery* _findLegacyServiceQuery(void); - bool _releaseServiceQueries(void); - stcMDNSServiceQuery* _findNextServiceQueryByServiceType(const stcMDNS_RRDomain& p_ServiceDomain, - const stcMDNSServiceQuery* p_pPrevServiceQuery); - - /* HOSTNAME */ - bool _setHostname(const char* p_pcHostname); - bool _releaseHostname(void); - - /* SERVICE */ - stcMDNSService* _allocService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port); - bool _releaseService(stcMDNSService* p_pService); - bool _releaseServices(void); - - stcMDNSService* _findService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol); - stcMDNSService* _findService(const hMDNSService p_hService); - - size_t _countServices(void) const; - - /* SERVICE TXT */ - stcMDNSServiceTxt* _allocServiceTxt(stcMDNSService* p_pService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp); - bool _releaseServiceTxt(stcMDNSService* p_pService, - stcMDNSServiceTxt* p_pTxt); - stcMDNSServiceTxt* _updateServiceTxt(stcMDNSService* p_pService, - stcMDNSServiceTxt* p_pTxt, - const char* p_pcValue, - bool p_bTemp); - - stcMDNSServiceTxt* _findServiceTxt(stcMDNSService* p_pService, - const char* p_pcKey); - stcMDNSServiceTxt* _findServiceTxt(stcMDNSService* p_pService, - const hMDNSTxt p_hTxt); - - stcMDNSServiceTxt* _addServiceTxt(stcMDNSService* p_pService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp); - - stcMDNSServiceTxt* _answerKeyValue(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - - bool _collectServiceTxts(stcMDNSService& p_rService); - bool _releaseTempServiceTxts(stcMDNSService& p_rService); - const stcMDNSServiceTxt* _serviceTxts(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol); - - /* MISC */ -#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER - bool _printRRDomain(const stcMDNS_RRDomain& p_rRRDomain) const; - bool _printRRAnswer(const MDNSResponder::stcMDNS_RRAnswer& p_RRAnswer) const; -#endif -}; - -}// namespace MDNSImplementation - -}// namespace esp8266 - -#endif // MDNS_H diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Control.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Control.cpp deleted file mode 100644 index 41e9524aba..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Control.cpp +++ /dev/null @@ -1,2134 +0,0 @@ -/* - LEAmDNS_Control.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#include <sys/time.h> -#include <IPAddress.h> -#include <AddrList.h> -#include <lwip/ip_addr.h> -#include <WString.h> -#include <cstdint> - -/* - ESP8266mDNS Control.cpp -*/ - -extern "C" { -#include "user_interface.h" -} - -#include "LEAmDNS_lwIPdefs.h" -#include "LEAmDNS_Priv.h" - -namespace esp8266 -{ -/* - LEAmDNS -*/ -namespace MDNSImplementation -{ - -/** - CONTROL -*/ - - -/** - MAINTENANCE -*/ - -/* - MDNSResponder::_process - - Run the MDNS process. - Is called, every time the UDPContext receives data AND - should be called in every 'loop' by calling 'MDNS::update()'. - -*/ -bool MDNSResponder::_process(bool p_bUserContext) -{ - - bool bResult = true; - - if (!p_bUserContext) - { - - if ((m_pUDPContext) && // UDPContext available AND - (m_pUDPContext->next())) // has content - { - - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _update: Calling _parseMessage\n"));); - bResult = _parseMessage(); - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parsePacket %s\n"), (bResult ? "succeeded" : "FAILED"));); - } - } - else - { - bResult = (m_netif != nullptr) && - (m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running - _updateProbeStatus() && // Probing - _checkServiceQueryCache(); // Service query cache check - } - return bResult; -} - -/* - MDNSResponder::_restart -*/ -bool MDNSResponder::_restart(void) -{ - - return ((m_netif != nullptr) && - (m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running - (_resetProbeStatus(true)) && // Stop and restart probing - (_allocUDPContext())); // Restart UDP -} - - -/** - RECEIVING -*/ - -/* - MDNSResponder::_parseMessage -*/ -bool MDNSResponder::_parseMessage(void) -{ - DEBUG_EX_INFO( - unsigned long ulStartTime = millis(); - unsigned uStartMemory = ESP.getFreeHeap(); - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage (Time: %lu ms, heap: %u bytes, from %s(%u), to %s(%u))\n"), ulStartTime, uStartMemory, - IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str(), m_pUDPContext->getRemotePort(), - IPAddress(m_pUDPContext->getDestAddress()).toString().c_str(), m_pUDPContext->getLocalPort()); - ); - //DEBUG_EX_INFO(_udpDump();); - - bool bResult = false; - - stcMDNS_MsgHeader header; - if (_readMDNSMsgHeader(header)) - { - if (0 == header.m_4bOpcode) // A standard query - { - if (header.m_1bQR) // Received a response -> answers to a query - { - //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: Reading answers: ID:%u, Q:%u, A:%u, NS:%u, AR:%u\n"), header.m_u16ID, header.m_u16QDCount, header.m_u16ANCount, header.m_u16NSCount, header.m_u16ARCount);); - bResult = _parseResponse(header); - } - else // Received a query (Questions) - { - //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: Reading query: ID:%u, Q:%u, A:%u, NS:%u, AR:%u\n"), header.m_u16ID, header.m_u16QDCount, header.m_u16ANCount, header.m_u16NSCount, header.m_u16ARCount);); - bResult = _parseQuery(header); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: Received UNEXPECTED opcode:%u. Ignoring message!\n"), header.m_4bOpcode);); - m_pUDPContext->flush(); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: FAILED to read header\n"));); - m_pUDPContext->flush(); - } - DEBUG_EX_INFO( - unsigned uFreeHeap = ESP.getFreeHeap(); - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: Done (%s after %lu ms, ate %i bytes, remaining %u)\n\n"), (bResult ? "Succeeded" : "FAILED"), (millis() - ulStartTime), (uStartMemory - uFreeHeap), uFreeHeap); - ); - return bResult; -} - -/* - MDNSResponder::_parseQuery - - Queries are of interest in two cases: - 1. allow for tiebreaking while probing in the case of a race condition between two instances probing for - the same name at the same time - 2. provide answers to questions for our host domain or any presented service - - When reading the questions, a set of (planned) responses is created, eg. a reverse PTR question for the host domain - gets an A (IP address) response, a PTR question for the _services._dns-sd domain gets a PTR (type) response for any - registered service, ... - - As any mDNS responder should be able to handle 'legacy' queries (from DNS clients), this case is handled here also. - Legacy queries have got only one (unicast) question and are directed to the local DNS port (not the multicast port). - - 1. -*/ -bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHeader) -{ - - bool bResult = true; - - stcMDNSSendParameter sendParameter; - uint8_t u8HostOrServiceReplies = 0; - for (uint16_t qd = 0; ((bResult) && (qd < p_MsgHeader.m_u16QDCount)); ++qd) - { - - stcMDNS_RRQuestion questionRR; - if ((bResult = _readRRQuestion(questionRR))) - { - // Define host replies, BUT only answer queries after probing is done - u8HostOrServiceReplies = - sendParameter.m_u8HostReplyMask |= (((m_bPassivModeEnabled) || - (ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus)) - ? _replyMaskForHost(questionRR.m_Header, 0) - : 0); - DEBUG_EX_INFO(if (u8HostOrServiceReplies) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Host reply needed 0x%X\n"), u8HostOrServiceReplies); - }); - - // Check tiebreak need for host domain - if (ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) - { - bool bFullNameMatch = false; - if ((_replyMaskForHost(questionRR.m_Header, &bFullNameMatch)) && - (bFullNameMatch)) - { - // We're in 'probing' state and someone is asking for our host domain: this might be - // a race-condition: Two host with the same domain names try simutanously to probe their domains - // See: RFC 6762, 8.2 (Tiebraking) - // However, we're using a max. reduced approach for tiebreaking here: The higher IP-address wins! - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Possible race-condition for host domain detected while probing.\n"));); - - m_HostProbeInformation.m_bTiebreakNeeded = true; - } - } - - // Define service replies - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - // Define service replies, BUT only answer queries after probing is done - uint8_t u8ReplyMaskForQuestion = (((m_bPassivModeEnabled) || - (ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus)) - ? _replyMaskForService(questionRR.m_Header, *pService, 0) - : 0); - u8HostOrServiceReplies |= (pService->m_u8ReplyMask |= u8ReplyMaskForQuestion); - DEBUG_EX_INFO(if (u8ReplyMaskForQuestion) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service reply needed for (%s.%s.%s): 0x%X (%s)\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol, u8ReplyMaskForQuestion, IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str()); - }); - - // Check tiebreak need for service domain - if (ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) - { - bool bFullNameMatch = false; - if ((_replyMaskForService(questionRR.m_Header, *pService, &bFullNameMatch)) && - (bFullNameMatch)) - { - // We're in 'probing' state and someone is asking for this service domain: this might be - // a race-condition: Two services with the same domain names try simutanously to probe their domains - // See: RFC 6762, 8.2 (Tiebraking) - // However, we're using a max. reduced approach for tiebreaking here: The 'higher' SRV host wins! - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Possible race-condition for service domain %s.%s.%s detected while probing.\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); - - pService->m_ProbeInformation.m_bTiebreakNeeded = true; - } - } - } - - // Handle unicast and legacy specialities - // If only one question asks for unicast reply, the whole reply packet is send unicast - if (((DNS_MQUERY_PORT != m_pUDPContext->getRemotePort()) || // Unicast (maybe legacy) query OR - (questionRR.m_bUnicast)) && // Expressivly unicast query - (!sendParameter.m_bUnicast)) - { - - sendParameter.m_bUnicast = true; - sendParameter.m_bCacheFlush = false; - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Unicast response for %s!\n"), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str());); - - if ((DNS_MQUERY_PORT != m_pUDPContext->getRemotePort()) && // Unicast (maybe legacy) query AND - (1 == p_MsgHeader.m_u16QDCount) && // Only one question AND - ((sendParameter.m_u8HostReplyMask) || // Host replies OR - (u8HostOrServiceReplies))) // Host or service replies available - { - // We're a match for this legacy query, BUT - // make sure, that the query comes from a local host - ip_info IPInfo_Local; - ip_info IPInfo_Remote; - if (((IPInfo_Remote.ip.addr = m_pUDPContext->getRemoteAddress())) && - (((wifi_get_ip_info(SOFTAP_IF, &IPInfo_Local)) && - (ip4_addr_netcmp(&IPInfo_Remote.ip, &IPInfo_Local.ip, &IPInfo_Local.netmask))) || // Remote IP in SOFTAP's subnet OR - ((wifi_get_ip_info(STATION_IF, &IPInfo_Local)) && - (ip4_addr_netcmp(&IPInfo_Remote.ip, &IPInfo_Local.ip, &IPInfo_Local.netmask))))) // Remote IP in STATION's subnet - { - - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Legacy query from local host %s, id %u!\n"), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str(), p_MsgHeader.m_u16ID);); - - sendParameter.m_u16ID = p_MsgHeader.m_u16ID; - sendParameter.m_bLegacyQuery = true; - sendParameter.m_pQuestions = new stcMDNS_RRQuestion; - if ((bResult = (0 != sendParameter.m_pQuestions))) - { - sendParameter.m_pQuestions->m_Header.m_Domain = questionRR.m_Header.m_Domain; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = questionRR.m_Header.m_Attributes.m_u16Type; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = questionRR.m_Header.m_Attributes.m_u16Class; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: FAILED to add legacy question!\n"));); - } - } - else - { - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Legacy query from NON-LOCAL host!\n"));); - bResult = false; - } - } - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: FAILED to read question!\n"));); - } - } // for questions - - //DEBUG_EX_INFO(if (u8HostOrServiceReplies) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Reply needed: %u (%s: %s->%s)\n"), u8HostOrServiceReplies, clsTimeSyncer::timestr(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str(), IPAddress(m_pUDPContext->getDestAddress()).toString().c_str()); } ); - - // Handle known answers - uint32_t u32Answers = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); - DEBUG_EX_INFO(if ((u8HostOrServiceReplies) && (u32Answers)) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Known answers(%u):\n"), u32Answers); - }); - - for (uint32_t an = 0; ((bResult) && (an < u32Answers)); ++an) - { - stcMDNS_RRAnswer* pKnownRRAnswer = 0; - if (((bResult = _readRRAnswer(pKnownRRAnswer))) && - (pKnownRRAnswer)) - { - - if ((DNS_RRTYPE_ANY != pKnownRRAnswer->m_Header.m_Attributes.m_u16Type) && // No ANY type answer - (DNS_RRCLASS_ANY != pKnownRRAnswer->m_Header.m_Attributes.m_u16Class)) // No ANY class answer - { - - // Find match between planned answer (sendParameter.m_u8HostReplyMask) and this 'known answer' - uint8_t u8HostMatchMask = (sendParameter.m_u8HostReplyMask & _replyMaskForHost(pKnownRRAnswer->m_Header)); - if ((u8HostMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND - ((MDNS_HOST_TTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new host TTL (120s) - { - - // Compare contents - if (AnswerType_PTR == pKnownRRAnswer->answerType()) - { - stcMDNS_RRDomain hostDomain; - if ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (((stcMDNS_RRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain == hostDomain)) - { - // Host domain match -#ifdef MDNS_IP4_SUPPORT - if (u8HostMatchMask & ContentFlag_PTR_IP4) - { - // IP4 PTR was asked for, but is already known -> skipping - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP4 PTR already known... skipping!\n"));); - sendParameter.m_u8HostReplyMask &= ~ContentFlag_PTR_IP4; - } -#endif -#ifdef MDNS_IP6_SUPPORT - if (u8HostMatchMask & ContentFlag_PTR_IP6) - { - // IP6 PTR was asked for, but is already known -> skipping - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP6 PTR already known... skipping!\n"));); - sendParameter.m_u8HostReplyMask &= ~ContentFlag_PTR_IP6; - } -#endif - } - } - else if (u8HostMatchMask & ContentFlag_A) - { - // IP4 address was asked for -#ifdef MDNS_IP4_SUPPORT - if ((AnswerType_A == pKnownRRAnswer->answerType()) && - (((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == _getResponseMulticastInterface())) - { - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP4 address already known... skipping!\n"));); - sendParameter.m_u8HostReplyMask &= ~ContentFlag_A; - } // else: RData NOT IP4 length !! -#endif - } - else if (u8HostMatchMask & ContentFlag_AAAA) - { - // IP6 address was asked for -#ifdef MDNS_IP6_SUPPORT - if ((AnswerType_AAAA == pAnswerRR->answerType()) && - (((stcMDNS_RRAnswerAAAA*)pAnswerRR)->m_IPAddress == _getResponseMulticastInterface())) - { - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP6 address already known... skipping!\n"));); - sendParameter.m_u8HostReplyMask &= ~ContentFlag_AAAA; - } // else: RData NOT IP6 length !! -#endif - } - } // Host match /*and TTL*/ - - // - // Check host tiebreak possibility - if (m_HostProbeInformation.m_bTiebreakNeeded) - { - stcMDNS_RRDomain hostDomain; - if ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (pKnownRRAnswer->m_Header.m_Domain == hostDomain)) - { - // Host domain match -#ifdef MDNS_IP4_SUPPORT - if (AnswerType_A == pKnownRRAnswer->answerType()) - { - IPAddress localIPAddress(_getResponseMulticastInterface()); - if (((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) - { - // SAME IP address -> We've received an old message from ourselfs (same IP) - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (IP4) WON (was an old message)!\n"));); - m_HostProbeInformation.m_bTiebreakNeeded = false; - } - else - { - if ((uint32_t)(((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress) > (uint32_t)localIPAddress) // The OTHER IP is 'higher' -> LOST - { - // LOST tiebreak - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (IP4) LOST (lower)!\n"));); - _cancelProbingForHost(); - m_HostProbeInformation.m_bTiebreakNeeded = false; - } - else // WON tiebreak - { - //TiebreakState = TiebreakState_Won; // We received an 'old' message from ourselfs -> Just ignore - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (IP4) WON (higher IP)!\n"));); - m_HostProbeInformation.m_bTiebreakNeeded = false; - } - } - } -#endif -#ifdef MDNS_IP6_SUPPORT - if (AnswerType_AAAA == pAnswerRR->answerType()) - { - // TODO - } -#endif - } - } // Host tiebreak possibility - - // Check service answers - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - - uint8_t u8ServiceMatchMask = (pService->m_u8ReplyMask & _replyMaskForService(pKnownRRAnswer->m_Header, *pService)); - - if ((u8ServiceMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND - ((MDNS_SERVICE_TTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new service TTL (4500s) - { - - if (AnswerType_PTR == pKnownRRAnswer->answerType()) - { - stcMDNS_RRDomain serviceDomain; - if ((u8ServiceMatchMask & ContentFlag_PTR_TYPE) && - (_buildDomainForService(*pService, false, serviceDomain)) && - (serviceDomain == ((stcMDNS_RRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service type PTR already known... skipping!\n"));); - pService->m_u8ReplyMask &= ~ContentFlag_PTR_TYPE; - } - if ((u8ServiceMatchMask & ContentFlag_PTR_NAME) && - (_buildDomainForService(*pService, true, serviceDomain)) && - (serviceDomain == ((stcMDNS_RRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service name PTR already known... skipping!\n"));); - pService->m_u8ReplyMask &= ~ContentFlag_PTR_NAME; - } - } - else if (u8ServiceMatchMask & ContentFlag_SRV) - { - DEBUG_EX_ERR(if (AnswerType_SRV != pKnownRRAnswer->answerType()) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: ERROR! INVALID answer type (SRV)!\n"));); - stcMDNS_RRDomain hostDomain; - if ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (hostDomain == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain)) // Host domain match - { - - if ((MDNS_SRV_PRIORITY == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_u16Priority) && - (MDNS_SRV_WEIGHT == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_u16Weight) && - (pService->m_u16Port == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_u16Port)) - { - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service SRV answer already known... skipping!\n"));); - pService->m_u8ReplyMask &= ~ContentFlag_SRV; - } // else: Small differences -> send update message - } - } - else if (u8ServiceMatchMask & ContentFlag_TXT) - { - DEBUG_EX_ERR(if (AnswerType_TXT != pKnownRRAnswer->answerType()) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: ERROR! INVALID answer type (TXT)!\n"));); - _collectServiceTxts(*pService); - if (pService->m_Txts == ((stcMDNS_RRAnswerTXT*)pKnownRRAnswer)->m_Txts) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service TXT answer already known... skipping!\n"));); - pService->m_u8ReplyMask &= ~ContentFlag_TXT; - } - _releaseTempServiceTxts(*pService); - } - } // Service match and enough TTL - - // - // Check service tiebreak possibility - if (pService->m_ProbeInformation.m_bTiebreakNeeded) - { - stcMDNS_RRDomain serviceDomain; - if ((_buildDomainForService(*pService, true, serviceDomain)) && - (pKnownRRAnswer->m_Header.m_Domain == serviceDomain)) - { - // Service domain match - if (AnswerType_SRV == pKnownRRAnswer->answerType()) - { - stcMDNS_RRDomain hostDomain; - if ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (hostDomain == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain)) // Host domain match - { - - // We've received an old message from ourselfs (same SRV) - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (SRV) won (was an old message)!\n"));); - pService->m_ProbeInformation.m_bTiebreakNeeded = false; - } - else - { - if (((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain > hostDomain) // The OTHER domain is 'higher' -> LOST - { - // LOST tiebreak - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (SRV) LOST (lower)!\n"));); - _cancelProbingForService(*pService); - pService->m_ProbeInformation.m_bTiebreakNeeded = false; - } - else // WON tiebreak - { - //TiebreakState = TiebreakState_Won; // We received an 'old' message from ourselfs -> Just ignore - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (SRV) won (higher)!\n"));); - pService->m_ProbeInformation.m_bTiebreakNeeded = false; - } - } - } - } - } // service tiebreak possibility - } // for services - } // ANY answers - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: FAILED to read known answer!\n"));); - } - - if (pKnownRRAnswer) - { - delete pKnownRRAnswer; - pKnownRRAnswer = 0; - } - } // for answers - - if (bResult) - { - // Check, if a reply is needed - uint8_t u8ReplyNeeded = sendParameter.m_u8HostReplyMask; - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - u8ReplyNeeded |= pService->m_u8ReplyMask; - } - - if (u8ReplyNeeded) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Sending answer(0x%X)...\n"), u8ReplyNeeded);); - - sendParameter.m_bResponse = true; - sendParameter.m_bAuthorative = true; - - bResult = _sendMDNSMessage(sendParameter); - } - DEBUG_EX_INFO( - else - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: No reply needed\n")); - } - ); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Something FAILED!\n"));); - m_pUDPContext->flush(); - } - - // - // Check and reset tiebreak-states - if (m_HostProbeInformation.m_bTiebreakNeeded) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: UNSOLVED tiebreak-need for host domain!\n"));); - m_HostProbeInformation.m_bTiebreakNeeded = false; - } - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - if (pService->m_ProbeInformation.m_bTiebreakNeeded) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: UNSOLVED tiebreak-need for service domain (%s.%s.%s)\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); - pService->m_ProbeInformation.m_bTiebreakNeeded = false; - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_parseResponse - - Responses are of interest in two cases: - 1. find domain name conflicts while probing - 2. get answers to service queries - - In both cases any included questions are ignored - - 1. If any answer has a domain name similar to one of the domain names we're planning to use (and are probing for), - then we've got a 'probing conflict'. The conflict has to be solved on our side of the conflict (eg. by - setting a new hostname and restart probing). The callback 'm_fnProbeResultCallback' is called with - 'p_bProbeResult=false' in this case. - - 2. Service queries like '_http._tcp.local' will (if available) produce PTR, SRV, TXT and A/AAAA answers. - All stored answers are pivoted by the service instance name (from the PTR record). Other answer parts, - like host domain or IP address are than attached to this element. - Any answer part carries a TTL, this is also stored (incl. the reception time); if the TTL is '0' the - answer (part) is withdrawn by the sender and should be removed from any cache. RFC 6762, 10.1 proposes to - set the caches TTL-value to 1 second in such a case and to delete the item only, if no update has - has taken place in this second. - Answer parts may arrive in 'unsorted' order, so they are grouped into three levels: - Level 1: PRT - names the service instance (and is used as pivot), voids all other parts if is withdrawn or outdates - Level 2: SRV - links the instance name to a host domain and port, voids A/AAAA parts if is withdrawn or outdates - TXT - links the instance name to services TXTs - Level 3: A/AAAA - links the host domain to an IP address -*/ -bool MDNSResponder::_parseResponse(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHeader) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse\n"));); - //DEBUG_EX_INFO(_udpDump();); - - bool bResult = false; - - // A response should be the result of a query or a probe - if ((_hasServiceQueriesWaitingForAnswers()) || // Waiting for query answers OR - (_hasProbesWaitingForAnswers())) // Probe responses - { - - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: Received a response\n")); - //_udpDump(); - ); - - bResult = true; - // - // Ignore questions here - stcMDNS_RRQuestion dummyRRQ; - for (uint16_t qd = 0; ((bResult) && (qd < p_MsgHeader.m_u16QDCount)); ++qd) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: Received a response containing a question... ignoring!\n"));); - bResult = _readRRQuestion(dummyRRQ); - } // for queries - - // - // Read and collect answers - stcMDNS_RRAnswer* pCollectedRRAnswers = 0; - uint32_t u32NumberOfAnswerRRs = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); - for (uint32_t an = 0; ((bResult) && (an < u32NumberOfAnswerRRs)); ++an) - { - stcMDNS_RRAnswer* pRRAnswer = 0; - if (((bResult = _readRRAnswer(pRRAnswer))) && - (pRRAnswer)) - { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: ADDING answer!\n"));); - pRRAnswer->m_pNext = pCollectedRRAnswers; - pCollectedRRAnswers = pRRAnswer; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: FAILED to read answer!\n"));); - if (pRRAnswer) - { - delete pRRAnswer; - pRRAnswer = 0; - } - bResult = false; - } - } // for answers - - // - // Process answers - if (bResult) - { - bResult = ((!pCollectedRRAnswers) || - (_processAnswers(pCollectedRRAnswers))); - } - else // Some failure while reading answers - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: FAILED to read answers!\n"));); - m_pUDPContext->flush(); - } - - // Delete collected answers - while (pCollectedRRAnswers) - { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: DELETING answer!\n"));); - stcMDNS_RRAnswer* pNextAnswer = pCollectedRRAnswers->m_pNext; - delete pCollectedRRAnswers; - pCollectedRRAnswers = pNextAnswer; - } - } - else // Received an unexpected response -> ignore - { - /* DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: Received an unexpected response... ignoring!\nDUMP:\n")); - bool bDumpResult = true; - for (uint16_t qd=0; ((bDumpResult) && (qd<p_MsgHeader.m_u16QDCount)); ++qd) { - stcMDNS_RRQuestion questionRR; - bDumpResult = _readRRQuestion(questionRR); - esp_yield(); - } // for questions - // Handle known answers - uint32_t u32Answers = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); - for (uint32_t an=0; ((bDumpResult) && (an<u32Answers)); ++an) { - stcMDNS_RRAnswer* pRRAnswer = 0; - bDumpResult = _readRRAnswer(pRRAnswer); - if (pRRAnswer) { - delete pRRAnswer; - pRRAnswer = 0; - } - esp_yield(); - } - );*/ - m_pUDPContext->flush(); - bResult = true; - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_processAnswers - Host: - A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 - AAAA (01Cx): eg. esp8266.local AAAA OP TTL 1234:5678::90 - PTR (0x0C, IP4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local - PTR (0x0C, IP6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local - Service: - PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local - PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local - SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local - TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 - -*/ -bool MDNSResponder::_processAnswers(const MDNSResponder::stcMDNS_RRAnswer* p_pAnswers) -{ - - bool bResult = false; - - if (p_pAnswers) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAnswers: Processing answers...\n"));); - bResult = true; - - // Answers may arrive in an unexpected order. So we loop our answers as long, as we - // can connect new information to service queries - bool bFoundNewKeyAnswer; - do - { - bFoundNewKeyAnswer = false; - - const stcMDNS_RRAnswer* pRRAnswer = p_pAnswers; - while ((pRRAnswer) && - (bResult)) - { - // 1. level answer (PTR) - if (AnswerType_PTR == pRRAnswer->answerType()) - { - // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local - bResult = _processPTRAnswer((stcMDNS_RRAnswerPTR*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new SRV or TXT answers to be linked to queries - } - // 2. level answers - // SRV -> host domain and port - else if (AnswerType_SRV == pRRAnswer->answerType()) - { - // eg. MyESP_http._tcp.local SRV xxxx xx yy zz 5000 esp8266.local - bResult = _processSRVAnswer((stcMDNS_RRAnswerSRV*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new A/AAAA answers to be linked to queries - } - // TXT -> Txts - else if (AnswerType_TXT == pRRAnswer->answerType()) - { - // eg. MyESP_http._tcp.local TXT xxxx xx c#=1 - bResult = _processTXTAnswer((stcMDNS_RRAnswerTXT*)pRRAnswer); - } - // 3. level answers -#ifdef MDNS_IP4_SUPPORT - // A -> IP4Address - else if (AnswerType_A == pRRAnswer->answerType()) - { - // eg. esp8266.local A xxxx xx 192.168.2.120 - bResult = _processAAnswer((stcMDNS_RRAnswerA*)pRRAnswer); - } -#endif -#ifdef MDNS_IP6_SUPPORT - // AAAA -> IP6Address - else if (AnswerType_AAAA == pRRAnswer->answerType()) - { - // eg. esp8266.local AAAA xxxx xx 09cf::0c - bResult = _processAAAAAnswer((stcMDNS_RRAnswerAAAA*)pRRAnswer); - } -#endif - - // Finally check for probing conflicts - // Host domain - if ((ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) && - ((AnswerType_A == pRRAnswer->answerType()) || - (AnswerType_AAAA == pRRAnswer->answerType()))) - { - - stcMDNS_RRDomain hostDomain; - if ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (pRRAnswer->m_Header.m_Domain == hostDomain)) - { - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAnswers: Probing CONFLICT found with: %s.local\n"), m_pcHostname);); - _cancelProbingForHost(); - } - } - // Service domains - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - if ((ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) && - ((AnswerType_TXT == pRRAnswer->answerType()) || - (AnswerType_SRV == pRRAnswer->answerType()))) - { - - stcMDNS_RRDomain serviceDomain; - if ((_buildDomainForService(*pService, true, serviceDomain)) && - (pRRAnswer->m_Header.m_Domain == serviceDomain)) - { - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAnswers: Probing CONFLICT found with: %s.%s.%s\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); - _cancelProbingForService(*pService); - } - } - } - - pRRAnswer = pRRAnswer->m_pNext; // Next collected answer - } // while (answers) - } while ((bFoundNewKeyAnswer) && - (bResult)); - } // else: No answers provided - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAnswers: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_processPTRAnswer -*/ -bool MDNSResponder::_processPTRAnswer(const MDNSResponder::stcMDNS_RRAnswerPTR* p_pPTRAnswer, - bool& p_rbFoundNewKeyAnswer) -{ - - bool bResult = false; - - if ((bResult = (0 != p_pPTRAnswer))) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: Processing PTR answers...\n"));); - // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local - // Check pending service queries for eg. '_http._tcp' - - stcMDNSServiceQuery* pServiceQuery = _findNextServiceQueryByServiceType(p_pPTRAnswer->m_Header.m_Domain, 0); - while (pServiceQuery) - { - if (pServiceQuery->m_bAwaitingAnswers) - { - // Find answer for service domain (eg. MyESP._http._tcp.local) - stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForServiceDomain(p_pPTRAnswer->m_PTRDomain); - if (pSQAnswer) // existing answer - { - if (p_pPTRAnswer->m_u32TTL) // Received update message - { - pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); // Update TTL tag - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: Updated TTL(%d) for "), (int)p_pPTRAnswer->m_u32TTL); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR("\n")); - ); - } - else // received goodbye-message - { - pSQAnswer->m_TTLServiceDomain.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: 'Goodbye' received for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR("\n")); - ); - } - } - else if ((p_pPTRAnswer->m_u32TTL) && // Not just a goodbye-message - ((pSQAnswer = new stcMDNSServiceQuery::stcAnswer))) // Not yet included -> add answer - { - pSQAnswer->m_ServiceDomain = p_pPTRAnswer->m_PTRDomain; - pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_ServiceDomain; - pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); - pSQAnswer->releaseServiceDomain(); - - bResult = pServiceQuery->addAnswer(pSQAnswer); - p_rbFoundNewKeyAnswer = true; - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_ServiceDomain), true); - } - } - } - pServiceQuery = _findNextServiceQueryByServiceType(p_pPTRAnswer->m_Header.m_Domain, pServiceQuery); - } - } // else: No p_pPTRAnswer - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_processSRVAnswer -*/ -bool MDNSResponder::_processSRVAnswer(const MDNSResponder::stcMDNS_RRAnswerSRV* p_pSRVAnswer, - bool& p_rbFoundNewKeyAnswer) -{ - - bool bResult = false; - - if ((bResult = (0 != p_pSRVAnswer))) - { - // eg. MyESP._http._tcp.local SRV xxxx xx yy zz 5000 esp8266.local - - stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; - while (pServiceQuery) - { - stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForServiceDomain(p_pSRVAnswer->m_Header.m_Domain); - if (pSQAnswer) // Answer for this service domain (eg. MyESP._http._tcp.local) available - { - if (p_pSRVAnswer->m_u32TTL) // First or update message (TTL != 0) - { - pSQAnswer->m_TTLHostDomainAndPort.set(p_pSRVAnswer->m_u32TTL); // Update TTL tag - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: Updated TTL(%d) for "), (int)p_pSRVAnswer->m_u32TTL); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); - ); - // Host domain & Port - if ((pSQAnswer->m_HostDomain != p_pSRVAnswer->m_SRVDomain) || - (pSQAnswer->m_u16Port != p_pSRVAnswer->m_u16Port)) - { - - pSQAnswer->m_HostDomain = p_pSRVAnswer->m_SRVDomain; - pSQAnswer->releaseHostDomain(); - pSQAnswer->m_u16Port = p_pSRVAnswer->m_u16Port; - pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_HostDomainAndPort; - - p_rbFoundNewKeyAnswer = true; - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_HostDomainAndPort), true); - } - } - } - else // Goodby message - { - pSQAnswer->m_TTLHostDomainAndPort.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: 'Goodbye' received for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); - ); - } - } - pServiceQuery = pServiceQuery->m_pNext; - } // while(service query) - } // else: No p_pSRVAnswer - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_processTXTAnswer -*/ -bool MDNSResponder::_processTXTAnswer(const MDNSResponder::stcMDNS_RRAnswerTXT* p_pTXTAnswer) -{ - - bool bResult = false; - - if ((bResult = (0 != p_pTXTAnswer))) - { - // eg. MyESP._http._tcp.local TXT xxxx xx c#=1 - - stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; - while (pServiceQuery) - { - stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForServiceDomain(p_pTXTAnswer->m_Header.m_Domain); - if (pSQAnswer) // Answer for this service domain (eg. MyESP._http._tcp.local) available - { - if (p_pTXTAnswer->m_u32TTL) // First or update message - { - pSQAnswer->m_TTLTxts.set(p_pTXTAnswer->m_u32TTL); // Update TTL tag - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: Updated TTL(%d) for "), (int)p_pTXTAnswer->m_u32TTL); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); - ); - if (!pSQAnswer->m_Txts.compare(p_pTXTAnswer->m_Txts)) - { - pSQAnswer->m_Txts = p_pTXTAnswer->m_Txts; - pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_Txts; - pSQAnswer->releaseTxts(); - - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_Txts), true); - } - } - } - else // Goodby message - { - pSQAnswer->m_TTLTxts.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: 'Goodbye' received for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); - ); - } - } - pServiceQuery = pServiceQuery->m_pNext; - } // while(service query) - } // else: No p_pTXTAnswer - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: FAILED!\n")); - }); - return bResult; -} - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::_processAAnswer -*/ -bool MDNSResponder::_processAAnswer(const MDNSResponder::stcMDNS_RRAnswerA* p_pAAnswer) -{ - - bool bResult = false; - - if ((bResult = (0 != p_pAAnswer))) - { - // eg. esp8266.local A xxxx xx 192.168.2.120 - - stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; - while (pServiceQuery) - { - stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForHostDomain(p_pAAnswer->m_Header.m_Domain); - if (pSQAnswer) // Answer for this host domain (eg. esp8266.local) available - { - stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address = pSQAnswer->findIP4Address(p_pAAnswer->m_IPAddress); - if (pIP4Address) - { - // Already known IP4 address - if (p_pAAnswer->m_u32TTL) // Valid TTL -> Update answers TTL - { - pIP4Address->m_TTL.set(p_pAAnswer->m_u32TTL); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL(%d) for "), (int)p_pAAnswer->m_u32TTL); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP4Address (%s)\n"), pIP4Address->m_IPAddress.toString().c_str()); - ); - } - else // 'Goodbye' message for known IP4 address - { - pIP4Address->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: 'Goodbye' received for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP4 address (%s)\n"), pIP4Address->m_IPAddress.toString().c_str()); - ); - } - } - else - { - // Until now unknown IP4 address -> Add (if the message isn't just a 'Goodbye' note) - if (p_pAAnswer->m_u32TTL) // NOT just a 'Goodbye' message - { - pIP4Address = new stcMDNSServiceQuery::stcAnswer::stcIP4Address(p_pAAnswer->m_IPAddress, p_pAAnswer->m_u32TTL); - if ((pIP4Address) && - (pSQAnswer->addIP4Address(pIP4Address))) - { - - pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_IP4Address; - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_IP4Address), true); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: FAILED to add IP4 address (%s)!\n"), p_pAAnswer->m_IPAddress.toString().c_str());); - } - } - } - } - pServiceQuery = pServiceQuery->m_pNext; - } // while(service query) - } // else: No p_pAAnswer - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: FAILED!\n")); - }); - return bResult; -} -#endif - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::_processAAAAAnswer -*/ -bool MDNSResponder::_processAAAAAnswer(const MDNSResponder::stcMDNS_RRAnswerAAAA* p_pAAAAAnswer) -{ - - bool bResult = false; - - if ((bResult = (0 != p_pAAAAAnswer))) - { - // eg. esp8266.local AAAA xxxx xx 0bf3::0c - - stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; - while (pServiceQuery) - { - stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForHostDomain(p_pAAAAAnswer->m_Header.m_Domain); - if (pSQAnswer) // Answer for this host domain (eg. esp8266.local) available - { - stcIP6Address* pIP6Address = pSQAnswer->findIP6Address(p_pAAAAAnswer->m_IPAddress); - if (pIP6Address) - { - // Already known IP6 address - if (p_pAAAAAnswer->m_u32TTL) // Valid TTL -> Update answers TTL - { - pIP6Address->m_TTL.set(p_pAAAAAnswer->m_u32TTL); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL(%lu) for "), p_pAAAAAnswer->m_u32TTL); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP6 address (%s)\n"), pIP6Address->m_IPAddress.toString().c_str()); - ); - } - else // 'Goodbye' message for known IP6 address - { - pIP6Address->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: 'Goodbye' received for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP6 address (%s)\n"), pIP6Address->m_IPAddress.toString().c_str()); - ); - } - } - else - { - // Until now unknown IP6 address -> Add (if the message isn't just a 'Goodbye' note) - if (p_pAAAAAnswer->m_u32TTL) // NOT just a 'Goodbye' message - { - pIP6Address = new stcIP6Address(p_pAAAAAnswer->m_IPAddress, p_pAAAAAnswer->m_u32TTL); - if ((pIP6Address) && - (pSQAnswer->addIP6Address(pIP6Address))) - { - - pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_IP6Address; - - if (pServiceQuery->m_fnCallback) - { - pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), ServiceQueryAnswerType_IP6Address, true, pServiceQuery->m_pUserdata); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: FAILED to add IP6 address (%s)!\n"), p_pAAAAAnswer->m_IPAddress.toString().c_str());); - } - } - } - } - pServiceQuery = pServiceQuery->m_pNext; - } // while(service query) - } // else: No p_pAAAAAnswer - - return bResult; -} -#endif - - -/* - PROBING -*/ - -/* - MDNSResponder::_updateProbeStatus - - Manages the (outgoing) probing process. - - If probing has not been started yet (ProbingStatus_NotStarted), the initial delay (see RFC 6762) is determined and - the process is started - - After timeout (of initial or subsequential delay) a probe message is send out for three times. If the message has - already been sent out three times, the probing has been successful and is finished. - - Conflict management is handled in '_parseResponse ff.' - Tiebraking is handled in 'parseQuery ff.' -*/ -bool MDNSResponder::_updateProbeStatus(void) -{ - - bool bResult = true; - - // - // Probe host domain - if ((ProbingStatus_ReadyToStart == m_HostProbeInformation.m_ProbingStatus) && // Ready to get started AND - //TODO: Fix the following to allow Ethernet shield or other interfaces - (_getResponseMulticastInterface() != IPAddress())) // Has IP address - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Starting host probing...\n"));); - - // First probe delay SHOULD be random 0-250 ms - m_HostProbeInformation.m_Timeout.reset(rand() % MDNS_PROBE_DELAY); - m_HostProbeInformation.m_ProbingStatus = ProbingStatus_InProgress; - } - else if ((ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing AND - (m_HostProbeInformation.m_Timeout.expired())) // Time for next probe - { - - if (MDNS_PROBE_COUNT > m_HostProbeInformation.m_u8SentCount) // Send next probe - { - if ((bResult = _sendHostProbe())) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Did sent host probe\n\n"));); - m_HostProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); - ++m_HostProbeInformation.m_u8SentCount; - } - } - else // Probing finished - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done host probing.\n"));); - m_HostProbeInformation.m_ProbingStatus = ProbingStatus_Done; - m_HostProbeInformation.m_Timeout.resetToNeverExpires(); - if (m_HostProbeInformation.m_fnHostProbeResultCallback) - { - m_HostProbeInformation.m_fnHostProbeResultCallback(m_pcHostname, true); - } - - // Prepare to announce host - m_HostProbeInformation.m_u8SentCount = 0; - m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Prepared host announcing.\n\n"));); - } - } // else: Probing already finished OR waiting for next time slot - else if ((ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus) && - (m_HostProbeInformation.m_Timeout.expired())) - { - - if ((bResult = _announce(true, false))) // Don't announce services here - { - ++m_HostProbeInformation.m_u8SentCount; - - if (MDNS_ANNOUNCE_COUNT > m_HostProbeInformation.m_u8SentCount) - { - m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing host (%d).\n\n"), m_HostProbeInformation.m_u8SentCount);); - } - else - { - m_HostProbeInformation.m_Timeout.resetToNeverExpires(); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done host announcing.\n\n"));); - } - } - } - - // - // Probe services - for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) - { - if (ProbingStatus_ReadyToStart == pService->m_ProbeInformation.m_ProbingStatus) // Ready to get started - { - - pService->m_ProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); // More or equal than first probe for host domain - pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_InProgress; - } - else if ((ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing AND - (pService->m_ProbeInformation.m_Timeout.expired())) // Time for next probe - { - - if (MDNS_PROBE_COUNT > pService->m_ProbeInformation.m_u8SentCount) // Send next probe - { - if ((bResult = _sendServiceProbe(*pService))) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Did sent service probe (%u)\n\n"), (pService->m_ProbeInformation.m_u8SentCount + 1));); - pService->m_ProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); - ++pService->m_ProbeInformation.m_u8SentCount; - } - } - else // Probing finished - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done service probing %s.%s.%s\n\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); - pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_Done; - pService->m_ProbeInformation.m_Timeout.resetToNeverExpires(); - if (pService->m_ProbeInformation.m_fnServiceProbeResultCallback) - { - pService->m_ProbeInformation.m_fnServiceProbeResultCallback(pService->m_pcName, pService, true); - } - // Prepare to announce service - pService->m_ProbeInformation.m_u8SentCount = 0; - pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Prepared service announcing.\n\n"));); - } - } // else: Probing already finished OR waiting for next time slot - else if ((ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus) && - (pService->m_ProbeInformation.m_Timeout.expired())) - { - - if ((bResult = _announceService(*pService))) // Announce service - { - ++pService->m_ProbeInformation.m_u8SentCount; - - if (MDNS_ANNOUNCE_COUNT > pService->m_ProbeInformation.m_u8SentCount) - { - pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing service %s.%s.%s (%d)\n\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_ProbeInformation.m_u8SentCount);); - } - else - { - pService->m_ProbeInformation.m_Timeout.resetToNeverExpires(); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done service announcing for %s.%s.%s\n\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); - } - } - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: FAILED!\n\n")); - }); - return bResult; -} - -/* - MDNSResponder::_resetProbeStatus - - Resets the probe status. - If 'p_bRestart' is set, the status is set to ProbingStatus_NotStarted. Consequently, - when running 'updateProbeStatus' (which is done in every '_update' loop), the probing - process is restarted. -*/ -bool MDNSResponder::_resetProbeStatus(bool p_bRestart /*= true*/) -{ - - m_HostProbeInformation.clear(false); - m_HostProbeInformation.m_ProbingStatus = (p_bRestart ? ProbingStatus_ReadyToStart : ProbingStatus_Done); - - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - pService->m_ProbeInformation.clear(false); - pService->m_ProbeInformation.m_ProbingStatus = (p_bRestart ? ProbingStatus_ReadyToStart : ProbingStatus_Done); - } - return true; -} - -/* - MDNSResponder::_hasProbesWaitingForAnswers -*/ -bool MDNSResponder::_hasProbesWaitingForAnswers(void) const -{ - - bool bResult = ((ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing - (0 < m_HostProbeInformation.m_u8SentCount)); // And really probing - - for (stcMDNSService* pService = m_pServices; ((!bResult) && (pService)); pService = pService->m_pNext) - { - bResult = ((ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing - (0 < pService->m_ProbeInformation.m_u8SentCount)); // And really probing - } - return bResult; -} - -/* - MDNSResponder::_sendHostProbe - - Asks (probes) in the local network for the planned host domain - - (eg. esp8266.local) - - To allow 'tiebreaking' (see '_parseQuery'), the answers for these questions are delivered in - the 'knwon answers' section of the query. - Host domain: - - A/AAAA (eg. esp8266.esp -> 192.168.2.120) -*/ -bool MDNSResponder::_sendHostProbe(void) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendHostProbe (%s, %lu)\n"), m_pcHostname, millis());); - - bool bResult = true; - - // Requests for host domain - stcMDNSSendParameter sendParameter; - sendParameter.m_bCacheFlush = false; // RFC 6762 10.2 - - sendParameter.m_pQuestions = new stcMDNS_RRQuestion; - if (((bResult = (0 != sendParameter.m_pQuestions))) && - ((bResult = _buildDomainForHost(m_pcHostname, sendParameter.m_pQuestions->m_Header.m_Domain)))) - { - - //sendParameter.m_pQuestions->m_bUnicast = true; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet - - // Add known answers -#ifdef MDNS_IP4_SUPPORT - sendParameter.m_u8HostReplyMask |= ContentFlag_A; // Add A answer -#endif -#ifdef MDNS_IP6_SUPPORT - sendParameter.m_u8HostReplyMask |= ContentFlag_AAAA; // Add AAAA answer -#endif - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendHostProbe: FAILED to create host question!\n"));); - if (sendParameter.m_pQuestions) - { - delete sendParameter.m_pQuestions; - sendParameter.m_pQuestions = 0; - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendHostProbe: FAILED!\n")); - }); - return ((bResult) && - (_sendMDNSMessage(sendParameter))); -} - -/* - MDNSResponder::_sendServiceProbe - - Asks (probes) in the local network for the planned service instance domain - - (eg. MyESP._http._tcp.local). - - To allow 'tiebreaking' (see '_parseQuery'), the answers for these questions are delivered in - the 'knwon answers' section of the query. - Service domain: - - SRV (eg. MyESP._http._tcp.local -> 5000 esp8266.local) - - PTR NAME (eg. _http._tcp.local -> MyESP._http._tcp.local) (TODO: Check if needed, maybe TXT is better) -*/ -bool MDNSResponder::_sendServiceProbe(stcMDNSService& p_rService) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendServiceProbe (%s.%s.%s, %lu)\n"), (p_rService.m_pcName ? : m_pcHostname), p_rService.m_pcService, p_rService.m_pcProtocol, millis());); - - bool bResult = true; - - // Requests for service instance domain - stcMDNSSendParameter sendParameter; - sendParameter.m_bCacheFlush = false; // RFC 6762 10.2 - - sendParameter.m_pQuestions = new stcMDNS_RRQuestion; - if (((bResult = (0 != sendParameter.m_pQuestions))) && - ((bResult = _buildDomainForService(p_rService, true, sendParameter.m_pQuestions->m_Header.m_Domain)))) - { - - sendParameter.m_pQuestions->m_bUnicast = true; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet - - // Add known answers - p_rService.m_u8ReplyMask = (ContentFlag_SRV | ContentFlag_PTR_NAME); // Add SRV and PTR NAME answers - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendServiceProbe: FAILED to create service question!\n"));); - if (sendParameter.m_pQuestions) - { - delete sendParameter.m_pQuestions; - sendParameter.m_pQuestions = 0; - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendServiceProbe: FAILED!\n")); - }); - return ((bResult) && - (_sendMDNSMessage(sendParameter))); -} - -/* - MDNSResponder::_cancelProbingForHost -*/ -bool MDNSResponder::_cancelProbingForHost(void) -{ - - bool bResult = false; - - m_HostProbeInformation.clear(false); - // Send host notification - if (m_HostProbeInformation.m_fnHostProbeResultCallback) - { - m_HostProbeInformation.m_fnHostProbeResultCallback(m_pcHostname, false); - - bResult = true; - } - - for (stcMDNSService* pService = m_pServices; ((!bResult) && (pService)); pService = pService->m_pNext) - { - bResult = _cancelProbingForService(*pService); - } - return bResult; -} - -/* - MDNSResponder::_cancelProbingForService -*/ -bool MDNSResponder::_cancelProbingForService(stcMDNSService& p_rService) -{ - - bool bResult = false; - - p_rService.m_ProbeInformation.clear(false); - // Send notification - if (p_rService.m_ProbeInformation.m_fnServiceProbeResultCallback) - { - p_rService.m_ProbeInformation.m_fnServiceProbeResultCallback(p_rService.m_pcName, &p_rService, false); - bResult = true; - } - return bResult; -} - - - -/** - ANNOUNCING -*/ - -/* - MDNSResponder::_announce - - Announces the host domain: - - A/AAAA (eg. esp8266.local -> 192.168.2.120) - - PTR (eg. 192.168.2.120.in-addr.arpa -> esp8266.local) - - and all presented services: - - PTR_TYPE (_services._dns-sd._udp.local -> _http._tcp.local) - - PTR_NAME (eg. _http._tcp.local -> MyESP8266._http._tcp.local) - - SRV (eg. MyESP8266._http._tcp.local -> 5000 esp8266.local) - - TXT (eg. MyESP8266._http._tcp.local -> c#=1) - - Goodbye (Un-Announcing) for the host domain and all services is also handled here. - Goodbye messages are created by setting the TTL for the answer to 0, this happens - inside the '_writeXXXAnswer' procs via 'sendParameter.m_bUnannounce = true' -*/ -bool MDNSResponder::_announce(bool p_bAnnounce, - bool p_bIncludeServices) -{ - - bool bResult = false; - - stcMDNSSendParameter sendParameter; - if (ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus) - { - - bResult = true; - - sendParameter.m_bResponse = true; // Announces are 'Unsolicited authorative responses' - sendParameter.m_bAuthorative = true; - sendParameter.m_bUnannounce = !p_bAnnounce; // When unannouncing, the TTL is set to '0' while creating the answers - - // Announce host - sendParameter.m_u8HostReplyMask = 0; -#ifdef MDNS_IP4_SUPPORT - sendParameter.m_u8HostReplyMask |= ContentFlag_A; // A answer - sendParameter.m_u8HostReplyMask |= ContentFlag_PTR_IP4; // PTR_IP4 answer -#endif -#ifdef MDNS_IP6_SUPPORT - sendParameter.m_u8HostReplyMask |= ContentFlag_AAAA; // AAAA answer - sendParameter.m_u8HostReplyMask |= ContentFlag_PTR_IP6; // PTR_IP6 answer -#endif - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: Announcing host %s (content 0x%X)\n"), m_pcHostname, sendParameter.m_u8HostReplyMask);); - - if (p_bIncludeServices) - { - // Announce services (service type, name, SRV (location) and TXTs) - for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) - { - if (ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus) - { - pService->m_u8ReplyMask = (ContentFlag_PTR_TYPE | ContentFlag_PTR_NAME | ContentFlag_SRV | ContentFlag_TXT); - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: Announcing service %s.%s.%s (content %u)\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_u8ReplyMask);); - } - } - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: FAILED!\n")); - }); - return ((bResult) && - (_sendMDNSMessage(sendParameter))); -} - -/* - MDNSResponder::_announceService -*/ -bool MDNSResponder::_announceService(stcMDNSService& p_rService, - bool p_bAnnounce /*= true*/) -{ - - bool bResult = false; - - stcMDNSSendParameter sendParameter; - if (ProbingStatus_Done == p_rService.m_ProbeInformation.m_ProbingStatus) - { - - sendParameter.m_bResponse = true; // Announces are 'Unsolicited authorative responses' - sendParameter.m_bAuthorative = true; - sendParameter.m_bUnannounce = !p_bAnnounce; // When unannouncing, the TTL is set to '0' while creating the answers - - // DON'T announce host - sendParameter.m_u8HostReplyMask = 0; - - // Announce services (service type, name, SRV (location) and TXTs) - p_rService.m_u8ReplyMask = (ContentFlag_PTR_TYPE | ContentFlag_PTR_NAME | ContentFlag_SRV | ContentFlag_TXT); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announceService: Announcing service %s.%s.%s (content 0x%X)\n"), (p_rService.m_pcName ? : m_pcHostname), p_rService.m_pcService, p_rService.m_pcProtocol, p_rService.m_u8ReplyMask);); - - bResult = true; - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announceService: FAILED!\n")); - }); - return ((bResult) && - (_sendMDNSMessage(sendParameter))); -} - - -/** - SERVICE QUERY CACHE -*/ - -/* - MDNSResponder::_hasServiceQueriesWaitingForAnswers -*/ -bool MDNSResponder::_hasServiceQueriesWaitingForAnswers(void) const -{ - - bool bOpenQueries = false; - - for (stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; pServiceQuery; pServiceQuery = pServiceQuery->m_pNext) - { - if (pServiceQuery->m_bAwaitingAnswers) - { - bOpenQueries = true; - break; - } - } - return bOpenQueries; -} - -/* - MDNSResponder::_checkServiceQueryCache - - For any 'living' service query (m_bAwaitingAnswers == true) all available answers (their components) - are checked for topicality based on the stored reception time and the answers TTL. - When the components TTL is outlasted by more than 80%, a new question is generated, to get updated information. - When no update arrived (in time), the component is removed from the answer (cache). - -*/ -bool MDNSResponder::_checkServiceQueryCache(void) -{ - - bool bResult = true; - - DEBUG_EX_INFO( - bool printedInfo = false; - ); - for (stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; ((bResult) && (pServiceQuery)); pServiceQuery = pServiceQuery->m_pNext) - { - - // - // Resend dynamic service queries, if not already done often enough - if ((!pServiceQuery->m_bLegacyQuery) && - (MDNS_DYNAMIC_QUERY_RESEND_COUNT > pServiceQuery->m_u8SentCount) && - (pServiceQuery->m_ResendTimeout.expired())) - { - - if ((bResult = _sendMDNSServiceQuery(*pServiceQuery))) - { - ++pServiceQuery->m_u8SentCount; - pServiceQuery->m_ResendTimeout.reset((MDNS_DYNAMIC_QUERY_RESEND_COUNT > pServiceQuery->m_u8SentCount) - ? (MDNS_DYNAMIC_QUERY_RESEND_DELAY * (pServiceQuery->m_u8SentCount - 1)) - : esp8266::polledTimeout::oneShotMs::neverExpires); - } - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: %s to resend service query!"), (bResult ? "Succeeded" : "FAILED")); - printedInfo = true; - ); - } - - // - // Schedule updates for cached answers - if (pServiceQuery->m_bAwaitingAnswers) - { - stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->m_pAnswers; - while ((bResult) && - (pSQAnswer)) - { - stcMDNSServiceQuery::stcAnswer* pNextSQAnswer = pSQAnswer->m_pNext; - - // 1. level answer - if ((bResult) && - (pSQAnswer->m_TTLServiceDomain.flagged())) - { - - if (!pSQAnswer->m_TTLServiceDomain.finalTimeoutLevel()) - { - - bResult = ((_sendMDNSServiceQuery(*pServiceQuery)) && - (pSQAnswer->m_TTLServiceDomain.restart())); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: PTR update scheduled for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" %s\n"), (bResult ? "OK" : "FAILURE")); - printedInfo = true; - ); - } - else - { - // Timed out! -> Delete - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_ServiceDomain), false); - } - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove PTR answer for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR("\n")); - printedInfo = true; - ); - - bResult = pServiceQuery->removeAnswer(pSQAnswer); - pSQAnswer = 0; - continue; // Don't use this answer anymore - } - } // ServiceDomain flagged - - // 2. level answers - // HostDomain & Port (from SRV) - if ((bResult) && - (pSQAnswer->m_TTLHostDomainAndPort.flagged())) - { - - if (!pSQAnswer->m_TTLHostDomainAndPort.finalTimeoutLevel()) - { - - bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_SRV)) && - (pSQAnswer->m_TTLHostDomainAndPort.restart())); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: SRV update scheduled for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" host domain and port %s\n"), (bResult ? "OK" : "FAILURE")); - printedInfo = true; - ); - } - else - { - // Timed out! -> Delete - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove SRV answer for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); - printedInfo = true; - ); - // Delete - pSQAnswer->m_HostDomain.clear(); - pSQAnswer->releaseHostDomain(); - pSQAnswer->m_u16Port = 0; - pSQAnswer->m_TTLHostDomainAndPort.set(0); - uint32_t u32ContentFlags = ServiceQueryAnswerType_HostDomainAndPort; - // As the host domain is the base for the IP4- and IP6Address, remove these too -#ifdef MDNS_IP4_SUPPORT - pSQAnswer->releaseIP4Addresses(); - u32ContentFlags |= ServiceQueryAnswerType_IP4Address; -#endif -#ifdef MDNS_IP6_SUPPORT - pSQAnswer->releaseIP6Addresses(); - u32ContentFlags |= ServiceQueryAnswerType_IP6Address; -#endif - - // Remove content flags for deleted answer parts - pSQAnswer->m_u32ContentFlags &= ~u32ContentFlags; - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(u32ContentFlags), false); - } - } - } // HostDomainAndPort flagged - - // Txts (from TXT) - if ((bResult) && - (pSQAnswer->m_TTLTxts.flagged())) - { - - if (!pSQAnswer->m_TTLTxts.finalTimeoutLevel()) - { - - bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_TXT)) && - (pSQAnswer->m_TTLTxts.restart())); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: TXT update scheduled for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" TXTs %s\n"), (bResult ? "OK" : "FAILURE")); - printedInfo = true; - ); - } - else - { - // Timed out! -> Delete - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove TXT answer for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); - printedInfo = true; - ); - // Delete - pSQAnswer->m_Txts.clear(); - pSQAnswer->m_TTLTxts.set(0); - - // Remove content flags for deleted answer parts - pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_Txts; - - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_Txts), false); - } - } - } // TXTs flagged - - // 3. level answers -#ifdef MDNS_IP4_SUPPORT - // IP4Address (from A) - stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address = pSQAnswer->m_pIP4Addresses; - bool bAUpdateQuerySent = false; - while ((pIP4Address) && - (bResult)) - { - - stcMDNSServiceQuery::stcAnswer::stcIP4Address* pNextIP4Address = pIP4Address->m_pNext; // Get 'next' early, as 'current' may be deleted at the end... - - if (pIP4Address->m_TTL.flagged()) - { - - if (!pIP4Address->m_TTL.finalTimeoutLevel()) // Needs update - { - - if ((bAUpdateQuerySent) || - ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_A)))) - { - - pIP4Address->m_TTL.restart(); - bAUpdateQuerySent = true; - - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: IP4 update scheduled for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP4 address (%s)\n"), (pIP4Address->m_IPAddress.toString().c_str())); - printedInfo = true; - ); - } - } - else - { - // Timed out! -> Delete - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove IP4 answer for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP4 address\n")); - printedInfo = true; - ); - pSQAnswer->removeIP4Address(pIP4Address); - if (!pSQAnswer->m_pIP4Addresses) // NO IP4 address left -> remove content flag - { - pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_IP4Address; - } - // Notify client - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_IP4Address), false); - } - } - } // IP4 flagged - - pIP4Address = pNextIP4Address; // Next - } // while -#endif -#ifdef MDNS_IP6_SUPPORT - // IP6Address (from AAAA) - stcMDNSServiceQuery::stcAnswer::stcIP6Address* pIP6Address = pSQAnswer->m_pIP6Addresses; - bool bAAAAUpdateQuerySent = false; - while ((pIP6Address) && - (bResult)) - { - - stcMDNSServiceQuery::stcAnswer::stcIP6Address* pNextIP6Address = pIP6Address->m_pNext; // Get 'next' early, as 'current' may be deleted at the end... - - if (pIP6Address->m_TTL.flagged()) - { - - if (!pIP6Address->m_TTL.finalTimeoutLevel()) // Needs update - { - - if ((bAAAAUpdateQuerySent) || - ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) - { - - pIP6Address->m_TTL.restart(); - bAAAAUpdateQuerySent = true; - - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: IP6 update scheduled for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP6 address (%s)\n"), (pIP6Address->m_IPAddress.toString().c_str())); - printedInfo = true; - ); - } - } - else - { - // Timed out! -> Delete - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove answer for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP6Address\n")); - printedInfo = true; - ); - pSQAnswer->removeIP6Address(pIP6Address); - if (!pSQAnswer->m_pIP6Addresses) // NO IP6 address left -> remove content flag - { - pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_IP6Address; - } - // Notify client - if (pServiceQuery->m_fnCallback) - { - pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), ServiceQueryAnswerType_IP6Address, false, pServiceQuery->m_pUserdata); - } - } - } // IP6 flagged - - pIP6Address = pNextIP6Address; // Next - } // while -#endif - pSQAnswer = pNextSQAnswer; - } - } - } - DEBUG_EX_INFO( - if (printedInfo) -{ - DEBUG_OUTPUT.printf_P(PSTR("\n")); - } - ); - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: FAILED!\n")); - }); - return bResult; -} - - -/* - MDNSResponder::_replyMaskForHost - - Determines the relavant host answers for the given question. - - A question for the hostname (eg. esp8266.local) will result in an A/AAAA (eg. 192.168.2.129) reply. - - A question for the reverse IP address (eg. 192-168.2.120.inarpa.arpa) will result in an PTR_IP4 (eg. esp8266.local) reply. - - In addition, a full name match (question domain == host domain) is marked. -*/ -uint8_t MDNSResponder::_replyMaskForHost(const MDNSResponder::stcMDNS_RRHeader& p_RRHeader, - bool* p_pbFullNameMatch /*= 0*/) const -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForHost\n"));); - - uint8_t u8ReplyMask = 0; - (p_pbFullNameMatch ? *p_pbFullNameMatch = false : 0); - - if ((DNS_RRCLASS_IN == p_RRHeader.m_Attributes.m_u16Class) || - (DNS_RRCLASS_ANY == p_RRHeader.m_Attributes.m_u16Class)) - { - - if ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) - { - // PTR request -#ifdef MDNS_IP4_SUPPORT - stcMDNS_RRDomain reverseIP4Domain; - if ((_buildDomainForReverseIP4(_getResponseMulticastInterface(), reverseIP4Domain)) && - (p_RRHeader.m_Domain == reverseIP4Domain)) - { - // Reverse domain match - u8ReplyMask |= ContentFlag_PTR_IP4; - } -#endif -#ifdef MDNS_IP6_SUPPORT - // TODO -#endif - } // Address qeuest - - stcMDNS_RRDomain hostDomain; - if ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (p_RRHeader.m_Domain == hostDomain)) // Host domain match - { - - (p_pbFullNameMatch ? (*p_pbFullNameMatch = true) : (0)); - -#ifdef MDNS_IP4_SUPPORT - if ((DNS_RRTYPE_A == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) - { - // IP4 address request - u8ReplyMask |= ContentFlag_A; - } -#endif -#ifdef MDNS_IP6_SUPPORT - if ((DNS_RRTYPE_AAAA == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) - { - // IP6 address request - u8ReplyMask |= ContentFlag_AAAA; - } -#endif - } - } - else - { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForHost: INVALID RR-class (0x%04X)!\n"), p_RRHeader.m_Attributes.m_u16Class);); - } - DEBUG_EX_INFO(if (u8ReplyMask) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForHost: 0x%X\n"), u8ReplyMask); - }); - return u8ReplyMask; -} - -/* - MDNSResponder::_replyMaskForService - - Determines the relevant service answers for the given question - - A PTR dns-sd service enum question (_services.dns-sd._udp.local) will result into an PTR_TYPE (eg. _http._tcp.local) answer - - A PTR service type question (eg. _http._tcp.local) will result into an PTR_NAME (eg. MyESP._http._tcp.local) answer - - A PTR service name question (eg. MyESP._http._tcp.local) will result into an PTR_NAME (eg. MyESP._http._tcp.local) answer - - A SRV service name question (eg. MyESP._http._tcp.local) will result into an SRV (eg. 5000 MyESP.local) answer - - A TXT service name question (eg. MyESP._http._tcp.local) will result into an TXT (eg. c#=1) answer - - In addition, a full name match (question domain == service instance domain) is marked. -*/ -uint8_t MDNSResponder::_replyMaskForService(const MDNSResponder::stcMDNS_RRHeader& p_RRHeader, - const MDNSResponder::stcMDNSService& p_Service, - bool* p_pbFullNameMatch /*= 0*/) const -{ - - uint8_t u8ReplyMask = 0; - (p_pbFullNameMatch ? *p_pbFullNameMatch = false : 0); - - if ((DNS_RRCLASS_IN == p_RRHeader.m_Attributes.m_u16Class) || - (DNS_RRCLASS_ANY == p_RRHeader.m_Attributes.m_u16Class)) - { - - stcMDNS_RRDomain DNSSDDomain; - if ((_buildDomainForDNSSD(DNSSDDomain)) && // _services._dns-sd._udp.local - (p_RRHeader.m_Domain == DNSSDDomain) && - ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type))) - { - // Common service info requested - u8ReplyMask |= ContentFlag_PTR_TYPE; - } - - stcMDNS_RRDomain serviceDomain; - if ((_buildDomainForService(p_Service, false, serviceDomain)) && // eg. _http._tcp.local - (p_RRHeader.m_Domain == serviceDomain) && - ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type))) - { - // Special service info requested - u8ReplyMask |= ContentFlag_PTR_NAME; - } - - if ((_buildDomainForService(p_Service, true, serviceDomain)) && // eg. MyESP._http._tcp.local - (p_RRHeader.m_Domain == serviceDomain)) - { - - (p_pbFullNameMatch ? (*p_pbFullNameMatch = true) : (0)); - - if ((DNS_RRTYPE_SRV == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) - { - // Instance info SRV requested - u8ReplyMask |= ContentFlag_SRV; - } - if ((DNS_RRTYPE_TXT == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) - { - // Instance info TXT requested - u8ReplyMask |= ContentFlag_TXT; - } - } - } - else - { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForService: INVALID RR-class (0x%04X)!\n"), p_RRHeader.m_Attributes.m_u16Class);); - } - DEBUG_EX_INFO(if (u8ReplyMask) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForService(%s.%s.%s): 0x%X\n"), p_Service.m_pcName, p_Service.m_pcService, p_Service.m_pcProtocol, u8ReplyMask); - }); - return u8ReplyMask; -} - -} // namespace MDNSImplementation - -} // namespace esp8266 diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Helpers.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Helpers.cpp deleted file mode 100644 index d23941ce53..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Helpers.cpp +++ /dev/null @@ -1,850 +0,0 @@ -/* - LEAmDNS_Helpers.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#include "lwip/igmp.h" - -#include "LEAmDNS_lwIPdefs.h" -#include "LEAmDNS_Priv.h" - - -namespace -{ - -/* - strrstr (static) - - Backwards search for p_pcPattern in p_pcString - Based on: https://stackoverflow.com/a/1634398/2778898 - -*/ -const char* strrstr(const char*__restrict p_pcString, const char*__restrict p_pcPattern) -{ - - const char* pcResult = 0; - - size_t stStringLength = (p_pcString ? strlen(p_pcString) : 0); - size_t stPatternLength = (p_pcPattern ? strlen(p_pcPattern) : 0); - - if ((stStringLength) && - (stPatternLength) && - (stPatternLength <= stStringLength)) - { - // Pattern is shorter or has the same length tham the string - - for (const char* s = (p_pcString + stStringLength - stPatternLength); s >= p_pcString; --s) - { - if (0 == strncmp(s, p_pcPattern, stPatternLength)) - { - pcResult = s; - break; - } - } - } - return pcResult; -} - - -} // anonymous - - - - - -namespace esp8266 -{ - -/* - LEAmDNS -*/ -namespace MDNSImplementation -{ - -/** - HELPERS -*/ - -/* - MDNSResponder::indexDomain (static) - - Updates the given domain 'p_rpcHostname' by appending a delimiter and an index number. - - If the given domain already hasa numeric index (after the given delimiter), this index - incremented. If not, the delimiter and index '2' is added. - - If 'p_rpcHostname' is empty (==0), the given default name 'p_pcDefaultHostname' is used, - if no default is given, 'esp8266' is used. - -*/ -/*static*/ bool MDNSResponder::indexDomain(char*& p_rpcDomain, - const char* p_pcDivider /*= "-"*/, - const char* p_pcDefaultDomain /*= 0*/) -{ - - bool bResult = false; - - // Ensure a divider exists; use '-' as default - const char* pcDivider = (p_pcDivider ? : "-"); - - if (p_rpcDomain) - { - const char* pFoundDivider = strrstr(p_rpcDomain, pcDivider); - if (pFoundDivider) // maybe already extended - { - char* pEnd = 0; - unsigned long ulIndex = strtoul((pFoundDivider + strlen(pcDivider)), &pEnd, 10); - if ((ulIndex) && - ((pEnd - p_rpcDomain) == (ptrdiff_t)strlen(p_rpcDomain)) && - (!*pEnd)) // Valid (old) index found - { - - char acIndexBuffer[16]; - sprintf(acIndexBuffer, "%lu", (++ulIndex)); - size_t stLength = ((pFoundDivider - p_rpcDomain + strlen(pcDivider)) + strlen(acIndexBuffer) + 1); - char* pNewHostname = new char[stLength]; - if (pNewHostname) - { - memcpy(pNewHostname, p_rpcDomain, (pFoundDivider - p_rpcDomain + strlen(pcDivider))); - pNewHostname[pFoundDivider - p_rpcDomain + strlen(pcDivider)] = 0; - strcat(pNewHostname, acIndexBuffer); - - delete[] p_rpcDomain; - p_rpcDomain = pNewHostname; - - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.println(F("[MDNSResponder] indexDomain: FAILED to alloc new hostname!"));); - } - } - else - { - pFoundDivider = 0; // Flag the need to (base) extend the hostname - } - } - - if (!pFoundDivider) // not yet extended (or failed to increment extension) -> start indexing - { - size_t stLength = strlen(p_rpcDomain) + (strlen(pcDivider) + 1 + 1); // Name + Divider + '2' + '\0' - char* pNewHostname = new char[stLength]; - if (pNewHostname) - { - sprintf(pNewHostname, "%s%s2", p_rpcDomain, pcDivider); - - delete[] p_rpcDomain; - p_rpcDomain = pNewHostname; - - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.println(F("[MDNSResponder] indexDomain: FAILED to alloc new hostname!"));); - } - } - } - else - { - // No given host domain, use base or default - const char* cpcDefaultName = (p_pcDefaultDomain ? : "esp8266"); - - size_t stLength = strlen(cpcDefaultName) + 1; // '\0' - p_rpcDomain = new char[stLength]; - if (p_rpcDomain) - { - strncpy(p_rpcDomain, cpcDefaultName, stLength); - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.println(F("[MDNSResponder] indexDomain: FAILED to alloc new hostname!"));); - } - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] indexDomain: %s\n"), p_rpcDomain);); - return bResult; -} - - -/* - UDP CONTEXT -*/ - -bool MDNSResponder::_callProcess(void) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf("[MDNSResponder] _callProcess (%lu, triggered by: %s)\n", millis(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str());); - - return _process(false); -} - -/* - MDNSResponder::_allocUDPContext - - (Re-)Creates the one-and-only UDP context for the MDNS responder. - The context is added to the 'multicast'-group and listens to the MDNS port (5353). - The travel-distance for multicast messages is set to 1 (local, via MDNS_MULTICAST_TTL). - Messages are received via the MDNSResponder '_update' function. CAUTION: This function - is called from the WiFi stack side of the ESP stack system. - -*/ -bool MDNSResponder::_allocUDPContext(void) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.println("[MDNSResponder] _allocUDPContext");); - - bool bResult = false; - - _releaseUDPContext(); - -#ifdef MDNS_IP4_SUPPORT - ip_addr_t multicast_addr = DNS_MQUERY_IPV4_GROUP_INIT; -#endif -#ifdef MDNS_IP6_SUPPORT - //TODO: set multicast address (lwip_joingroup() is IPv4 only at the time of writing) - multicast_addr.addr = DNS_MQUERY_IPV6_GROUP_INIT; -#endif - if (ERR_OK == igmp_joingroup(ip_2_ip4(&m_netif->ip_addr), ip_2_ip4(&multicast_addr))) - { - m_pUDPContext = new UdpContext; - m_pUDPContext->ref(); - - if (m_pUDPContext->listen(IP4_ADDR_ANY, DNS_MQUERY_PORT)) - { - m_pUDPContext->setMulticastTTL(MDNS_MULTICAST_TTL); - m_pUDPContext->onRx(std::bind(&MDNSResponder::_callProcess, this)); - - bResult = m_pUDPContext->connect(&multicast_addr, DNS_MQUERY_PORT); - } - } - return bResult; -} - -/* - MDNSResponder::_releaseUDPContext -*/ -bool MDNSResponder::_releaseUDPContext(void) -{ - - if (m_pUDPContext) - { - m_pUDPContext->unref(); - m_pUDPContext = 0; - } - return true; -} - - -/* - SERVICE QUERY -*/ - -/* - MDNSResponder::_allocServiceQuery -*/ -MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_allocServiceQuery(void) -{ - - stcMDNSServiceQuery* pServiceQuery = new stcMDNSServiceQuery; - if (pServiceQuery) - { - // Link to query list - pServiceQuery->m_pNext = m_pServiceQueries; - m_pServiceQueries = pServiceQuery; - } - return m_pServiceQueries; -} - -/* - MDNSResponder::_removeServiceQuery -*/ -bool MDNSResponder::_removeServiceQuery(MDNSResponder::stcMDNSServiceQuery* p_pServiceQuery) -{ - - bool bResult = false; - - if (p_pServiceQuery) - { - stcMDNSServiceQuery* pPred = m_pServiceQueries; - while ((pPred) && - (pPred->m_pNext != p_pServiceQuery)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pServiceQuery->m_pNext; - delete p_pServiceQuery; - bResult = true; - } - else // No predecesor - { - if (m_pServiceQueries == p_pServiceQuery) - { - m_pServiceQueries = p_pServiceQuery->m_pNext; - delete p_pServiceQuery; - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.println("[MDNSResponder] _releaseServiceQuery: INVALID service query!");); - } - } - } - return bResult; -} - -/* - MDNSResponder::_removeLegacyServiceQuery -*/ -bool MDNSResponder::_removeLegacyServiceQuery(void) -{ - - stcMDNSServiceQuery* pLegacyServiceQuery = _findLegacyServiceQuery(); - return (pLegacyServiceQuery ? _removeServiceQuery(pLegacyServiceQuery) : true); -} - -/* - MDNSResponder::_findServiceQuery - - 'Convert' hMDNSServiceQuery to stcMDNSServiceQuery* (ensure existance) - -*/ -MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_findServiceQuery(MDNSResponder::hMDNSServiceQuery p_hServiceQuery) -{ - - stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; - while (pServiceQuery) - { - if ((hMDNSServiceQuery)pServiceQuery == p_hServiceQuery) - { - break; - } - pServiceQuery = pServiceQuery->m_pNext; - } - return pServiceQuery; -} - -/* - MDNSResponder::_findLegacyServiceQuery -*/ -MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_findLegacyServiceQuery(void) -{ - - stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; - while (pServiceQuery) - { - if (pServiceQuery->m_bLegacyQuery) - { - break; - } - pServiceQuery = pServiceQuery->m_pNext; - } - return pServiceQuery; -} - -/* - MDNSResponder::_releaseServiceQueries -*/ -bool MDNSResponder::_releaseServiceQueries(void) -{ - while (m_pServiceQueries) - { - stcMDNSServiceQuery* pNext = m_pServiceQueries->m_pNext; - delete m_pServiceQueries; - m_pServiceQueries = pNext; - } - return true; -} - -/* - MDNSResponder::_findNextServiceQueryByServiceType -*/ -MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_findNextServiceQueryByServiceType(const stcMDNS_RRDomain& p_ServiceTypeDomain, - const stcMDNSServiceQuery* p_pPrevServiceQuery) -{ - stcMDNSServiceQuery* pMatchingServiceQuery = 0; - - stcMDNSServiceQuery* pServiceQuery = (p_pPrevServiceQuery ? p_pPrevServiceQuery->m_pNext : m_pServiceQueries); - while (pServiceQuery) - { - if (p_ServiceTypeDomain == pServiceQuery->m_ServiceTypeDomain) - { - pMatchingServiceQuery = pServiceQuery; - break; - } - pServiceQuery = pServiceQuery->m_pNext; - } - return pMatchingServiceQuery; -} - - -/* - HOSTNAME -*/ - -/* - MDNSResponder::_setHostname -*/ -bool MDNSResponder::_setHostname(const char* p_pcHostname) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _allocHostname (%s)\n"), p_pcHostname);); - - bool bResult = false; - - _releaseHostname(); - - size_t stLength = 0; - if ((p_pcHostname) && - (MDNS_DOMAIN_LABEL_MAXLENGTH >= (stLength = strlen(p_pcHostname)))) // char max size for a single label - { - // Copy in hostname characters as lowercase - if ((bResult = (0 != (m_pcHostname = new char[stLength + 1])))) - { -#ifdef MDNS_FORCE_LOWERCASE_HOSTNAME - size_t i = 0; - for (; i < stLength; ++i) - { - m_pcHostname[i] = (isupper(p_pcHostname[i]) ? tolower(p_pcHostname[i]) : p_pcHostname[i]); - } - m_pcHostname[i] = 0; -#else - strncpy(m_pcHostname, p_pcHostname, (stLength + 1)); -#endif - } - } - return bResult; -} - -/* - MDNSResponder::_releaseHostname -*/ -bool MDNSResponder::_releaseHostname(void) -{ - - if (m_pcHostname) - { - delete[] m_pcHostname; - m_pcHostname = 0; - } - return true; -} - - -/* - SERVICE -*/ - -/* - MDNSResponder::_allocService -*/ -MDNSResponder::stcMDNSService* MDNSResponder::_allocService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port) -{ - - stcMDNSService* pService = 0; - if (((!p_pcName) || - (MDNS_DOMAIN_LABEL_MAXLENGTH >= strlen(p_pcName))) && - (p_pcService) && - (MDNS_SERVICE_NAME_LENGTH >= strlen(p_pcService)) && - (p_pcProtocol) && - (MDNS_SERVICE_PROTOCOL_LENGTH >= strlen(p_pcProtocol)) && - (p_u16Port) && - (0 != (pService = new stcMDNSService)) && - (pService->setName(p_pcName ? : m_pcHostname)) && - (pService->setService(p_pcService)) && - (pService->setProtocol(p_pcProtocol))) - { - - pService->m_bAutoName = (0 == p_pcName); - pService->m_u16Port = p_u16Port; - - // Add to list (or start list) - pService->m_pNext = m_pServices; - m_pServices = pService; - } - return pService; -} - -/* - MDNSResponder::_releaseService -*/ -bool MDNSResponder::_releaseService(MDNSResponder::stcMDNSService* p_pService) -{ - - bool bResult = false; - - if (p_pService) - { - stcMDNSService* pPred = m_pServices; - while ((pPred) && - (pPred->m_pNext != p_pService)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pService->m_pNext; - delete p_pService; - bResult = true; - } - else // No predecesor - { - if (m_pServices == p_pService) - { - m_pServices = p_pService->m_pNext; - delete p_pService; - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.println("[MDNSResponder] _releaseService: INVALID service!");); - } - } - } - return bResult; -} - -/* - MDNSResponder::_releaseServices -*/ -bool MDNSResponder::_releaseServices(void) -{ - - stcMDNSService* pService = m_pServices; - while (pService) - { - _releaseService(pService); - pService = m_pServices; - } - return true; -} - -/* - MDNSResponder::_findService -*/ -MDNSResponder::stcMDNSService* MDNSResponder::_findService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol) -{ - - stcMDNSService* pService = m_pServices; - while (pService) - { - if ((0 == strcmp(pService->m_pcName, p_pcName)) && - (0 == strcmp(pService->m_pcService, p_pcService)) && - (0 == strcmp(pService->m_pcProtocol, p_pcProtocol))) - { - - break; - } - pService = pService->m_pNext; - } - return pService; -} - -/* - MDNSResponder::_findService -*/ -MDNSResponder::stcMDNSService* MDNSResponder::_findService(const MDNSResponder::hMDNSService p_hService) -{ - - stcMDNSService* pService = m_pServices; - while (pService) - { - if (p_hService == (hMDNSService)pService) - { - break; - } - pService = pService->m_pNext; - } - return pService; -} - - -/* - SERVICE TXT -*/ - -/* - MDNSResponder::_allocServiceTxt -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_allocServiceTxt(MDNSResponder::stcMDNSService* p_pService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp) -{ - - stcMDNSServiceTxt* pTxt = 0; - - if ((p_pService) && - (p_pcKey) && - (MDNS_SERVICE_TXT_MAXLENGTH > (p_pService->m_Txts.length() + - 1 + // Length byte - (p_pcKey ? strlen(p_pcKey) : 0) + - 1 + // '=' - (p_pcValue ? strlen(p_pcValue) : 0)))) - { - - pTxt = new stcMDNSServiceTxt; - if (pTxt) - { - size_t stLength = (p_pcKey ? strlen(p_pcKey) : 0); - pTxt->m_pcKey = new char[stLength + 1]; - if (pTxt->m_pcKey) - { - strncpy(pTxt->m_pcKey, p_pcKey, stLength); pTxt->m_pcKey[stLength] = 0; - } - - if (p_pcValue) - { - stLength = (p_pcValue ? strlen(p_pcValue) : 0); - pTxt->m_pcValue = new char[stLength + 1]; - if (pTxt->m_pcValue) - { - strncpy(pTxt->m_pcValue, p_pcValue, stLength); pTxt->m_pcValue[stLength] = 0; - } - } - pTxt->m_bTemp = p_bTemp; - - // Add to list (or start list) - p_pService->m_Txts.add(pTxt); - } - } - return pTxt; -} - -/* - MDNSResponder::_releaseServiceTxt -*/ -bool MDNSResponder::_releaseServiceTxt(MDNSResponder::stcMDNSService* p_pService, - MDNSResponder::stcMDNSServiceTxt* p_pTxt) -{ - - return ((p_pService) && - (p_pTxt) && - (p_pService->m_Txts.remove(p_pTxt))); -} - -/* - MDNSResponder::_updateServiceTxt -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_updateServiceTxt(MDNSResponder::stcMDNSService* p_pService, - MDNSResponder::stcMDNSServiceTxt* p_pTxt, - const char* p_pcValue, - bool p_bTemp) -{ - - if ((p_pService) && - (p_pTxt) && - (MDNS_SERVICE_TXT_MAXLENGTH > (p_pService->m_Txts.length() - - (p_pTxt->m_pcValue ? strlen(p_pTxt->m_pcValue) : 0) + - (p_pcValue ? strlen(p_pcValue) : 0)))) - { - p_pTxt->update(p_pcValue); - p_pTxt->m_bTemp = p_bTemp; - } - return p_pTxt; -} - -/* - MDNSResponder::_findServiceTxt -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_findServiceTxt(MDNSResponder::stcMDNSService* p_pService, - const char* p_pcKey) -{ - - return (p_pService ? p_pService->m_Txts.find(p_pcKey) : 0); -} - -/* - MDNSResponder::_findServiceTxt -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_findServiceTxt(MDNSResponder::stcMDNSService* p_pService, - const hMDNSTxt p_hTxt) -{ - - return (((p_pService) && (p_hTxt)) ? p_pService->m_Txts.find((stcMDNSServiceTxt*)p_hTxt) : 0); -} - -/* - MDNSResponder::_addServiceTxt -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_addServiceTxt(MDNSResponder::stcMDNSService* p_pService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp) -{ - stcMDNSServiceTxt* pResult = 0; - - if ((p_pService) && - (p_pcKey) && - (strlen(p_pcKey))) - { - - stcMDNSServiceTxt* pTxt = p_pService->m_Txts.find(p_pcKey); - if (pTxt) - { - pResult = _updateServiceTxt(p_pService, pTxt, p_pcValue, p_bTemp); - } - else - { - pResult = _allocServiceTxt(p_pService, p_pcKey, p_pcValue, p_bTemp); - } - } - return pResult; -} - -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_answerKeyValue(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcTxts (if not already done) - return (pSQAnswer) ? pSQAnswer->m_Txts.m_pTxts : 0; -} - -/* - MDNSResponder::_collectServiceTxts -*/ -bool MDNSResponder::_collectServiceTxts(MDNSResponder::stcMDNSService& p_rService) -{ - - // Call Dynamic service callbacks - if (m_fnServiceTxtCallback) - { - m_fnServiceTxtCallback((hMDNSService)&p_rService); - } - if (p_rService.m_fnTxtCallback) - { - p_rService.m_fnTxtCallback((hMDNSService)&p_rService); - } - return true; -} - -/* - MDNSResponder::_releaseTempServiceTxts -*/ -bool MDNSResponder::_releaseTempServiceTxts(MDNSResponder::stcMDNSService& p_rService) -{ - - return (p_rService.m_Txts.removeTempTxts()); -} - - -/* - MISC -*/ - -#ifdef DEBUG_ESP_MDNS_RESPONDER -/* - MDNSResponder::_printRRDomain -*/ -bool MDNSResponder::_printRRDomain(const MDNSResponder::stcMDNS_RRDomain& p_RRDomain) const -{ - - //DEBUG_OUTPUT.printf_P(PSTR("Domain: ")); - - const char* pCursor = p_RRDomain.m_acName; - uint8_t u8Length = *pCursor++; - if (u8Length) - { - while (u8Length) - { - for (uint8_t u = 0; u < u8Length; ++u) - { - DEBUG_OUTPUT.printf_P(PSTR("%c"), *(pCursor++)); - } - u8Length = *pCursor++; - if (u8Length) - { - DEBUG_OUTPUT.printf_P(PSTR(".")); - } - } - } - else // empty domain - { - DEBUG_OUTPUT.printf_P(PSTR("-empty-")); - } - //DEBUG_OUTPUT.printf_P(PSTR("\n")); - - return true; -} - -/* - MDNSResponder::_printRRAnswer -*/ -bool MDNSResponder::_printRRAnswer(const MDNSResponder::stcMDNS_RRAnswer& p_RRAnswer) const -{ - - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] RRAnswer: ")); - _printRRDomain(p_RRAnswer.m_Header.m_Domain); - DEBUG_OUTPUT.printf_P(PSTR(" Type:0x%04X Class:0x%04X TTL:%u, "), p_RRAnswer.m_Header.m_Attributes.m_u16Type, p_RRAnswer.m_Header.m_Attributes.m_u16Class, p_RRAnswer.m_u32TTL); - switch (p_RRAnswer.m_Header.m_Attributes.m_u16Type & (~0x8000)) // Topmost bit might carry 'cache flush' flag - { -#ifdef MDNS_IP4_SUPPORT - case DNS_RRTYPE_A: - DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((const stcMDNS_RRAnswerA*)&p_RRAnswer)->m_IPAddress.toString().c_str()); - break; -#endif - case DNS_RRTYPE_PTR: - DEBUG_OUTPUT.printf_P(PSTR("PTR ")); - _printRRDomain(((const stcMDNS_RRAnswerPTR*)&p_RRAnswer)->m_PTRDomain); - break; - case DNS_RRTYPE_TXT: - { - size_t stTxtLength = ((const stcMDNS_RRAnswerTXT*)&p_RRAnswer)->m_Txts.c_strLength(); - char* pTxts = new char[stTxtLength]; - if (pTxts) - { - ((/*const c_str()!!*/stcMDNS_RRAnswerTXT*)&p_RRAnswer)->m_Txts.c_str(pTxts); - DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts); - delete[] pTxts; - } - break; - } -#ifdef MDNS_IP6_SUPPORT - case DNS_RRTYPE_AAAA: - DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((stcMDNS_RRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); - break; -#endif - case DNS_RRTYPE_SRV: - DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((const stcMDNS_RRAnswerSRV*)&p_RRAnswer)->m_u16Port); - _printRRDomain(((const stcMDNS_RRAnswerSRV*)&p_RRAnswer)->m_SRVDomain); - break; - default: - DEBUG_OUTPUT.printf_P(PSTR("generic ")); - break; - } - DEBUG_OUTPUT.printf_P(PSTR("\n")); - - return true; -} -#endif - -} // namespace MDNSImplementation - -} // namespace esp8266 - - - - diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Priv.h b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Priv.h deleted file mode 100644 index cc56b133a9..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Priv.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - LEAmDNS_Priv.h - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#ifndef MDNS_PRIV_H -#define MDNS_PRIV_H - -namespace esp8266 -{ - -/* - LEAmDNS -*/ - -namespace MDNSImplementation -{ - -// Enable class debug functions -#define ESP_8266_MDNS_INCLUDE -//#define DEBUG_ESP_MDNS_RESPONDER - -#if !defined(DEBUG_ESP_MDNS_RESPONDER) && defined(DEBUG_ESP_MDNS) -#define DEBUG_ESP_MDNS_RESPONDER -#endif - -#ifndef LWIP_OPEN_SRC -#define LWIP_OPEN_SRC -#endif - -// -// If ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE is defined, the mDNS responder ignores a successful probing -// This allows to drive the responder in a environment, where 'update()' isn't called in the loop -//#define ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE - -// Enable/disable debug trace macros -#ifdef DEBUG_ESP_MDNS_RESPONDER -#define DEBUG_ESP_MDNS_INFO -#define DEBUG_ESP_MDNS_ERR -#define DEBUG_ESP_MDNS_TX -#define DEBUG_ESP_MDNS_RX -#endif - -#ifdef DEBUG_ESP_MDNS_RESPONDER -#ifdef DEBUG_ESP_MDNS_INFO -#define DEBUG_EX_INFO(A) A -#else -#define DEBUG_EX_INFO(A) do { (void)0; } while (0) -#endif -#ifdef DEBUG_ESP_MDNS_ERR -#define DEBUG_EX_ERR(A) A -#else -#define DEBUG_EX_ERR(A) do { (void)0; } while (0) -#endif -#ifdef DEBUG_ESP_MDNS_TX -#define DEBUG_EX_TX(A) A -#else -#define DEBUG_EX_TX(A) do { (void)0; } while (0) -#endif -#ifdef DEBUG_ESP_MDNS_RX -#define DEBUG_EX_RX(A) A -#else -#define DEBUG_EX_RX(A) do { (void)0; } while (0) -#endif - -#ifdef DEBUG_ESP_PORT -#define DEBUG_OUTPUT DEBUG_ESP_PORT -#else -#define DEBUG_OUTPUT Serial -#endif -#else -#define DEBUG_EX_INFO(A) do { (void)0; } while (0) -#define DEBUG_EX_ERR(A) do { (void)0; } while (0) -#define DEBUG_EX_TX(A) do { (void)0; } while (0) -#define DEBUG_EX_RX(A) do { (void)0; } while (0) -#endif - - -/* Replaced by 'lwip/prot/dns.h' definitions - #ifdef MDNS_IP4_SUPPORT - #define MDNS_MULTICAST_ADDR_IP4 (IPAddress(224, 0, 0, 251)) // ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT - #endif - #ifdef MDNS_IP6_SUPPORT - #define MDNS_MULTICAST_ADDR_IP6 (IPAddress("FF02::FB")) // ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT - #endif*/ -//#define MDNS_MULTICAST_PORT 5353 - -/* - This is NOT the TTL (Time-To-Live) for MDNS records, but the - subnet level distance MDNS records should travel. - 1 sets the subnet distance to 'local', which is default for MDNS. - (Btw.: 255 would set it to 'as far as possible' -> internet) - - However, RFC 3171 seems to force 255 instead -*/ -#define MDNS_MULTICAST_TTL 255/*1*/ - -/* - This is the MDNS record TTL - Host level records are set to 2min (120s) - service level records are set to 75min (4500s) -*/ -#define MDNS_HOST_TTL 120 -#define MDNS_SERVICE_TTL 4500 - -/* - Compressed labels are flaged by the two topmost bits of the length byte being set -*/ -#define MDNS_DOMAIN_COMPRESS_MARK 0xC0 -/* - Avoid endless recursion because of malformed compressed labels -*/ -#define MDNS_DOMAIN_MAX_REDIRCTION 6 - -/* - Default service priority and weight in SRV answers -*/ -#define MDNS_SRV_PRIORITY 0 -#define MDNS_SRV_WEIGHT 0 - -/* - Delay between and number of probes for host and service domains - Delay between and number of announces for host and service domains - Delay between and number of service queries; the delay is multiplied by the resent number in '_checkServiceQueryCache' -*/ -#define MDNS_PROBE_DELAY 250 -#define MDNS_PROBE_COUNT 3 -#define MDNS_ANNOUNCE_DELAY 1000 -#define MDNS_ANNOUNCE_COUNT 8 -#define MDNS_DYNAMIC_QUERY_RESEND_COUNT 5 -#define MDNS_DYNAMIC_QUERY_RESEND_DELAY 5000 - - -/* - Force host domain to use only lowercase letters -*/ -//#define MDNS_FORCE_LOWERCASE_HOSTNAME - -/* - Enable/disable the usage of the F() macro in debug trace printf calls. - There needs to be an PGM comptible printf function to use this. - - USE_PGM_PRINTF and F -*/ -#define USE_PGM_PRINTF - -#ifdef USE_PGM_PRINTF -#else -#ifdef F -#undef F -#endif -#define F(A) A -#endif - -} // namespace MDNSImplementation - -} // namespace esp8266 - -// Include the main header, so the submodlues only need to include this header -#include "LEAmDNS.h" - - -#endif // MDNS_PRIV_H diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Structs.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Structs.cpp deleted file mode 100644 index ce475de3ba..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Structs.cpp +++ /dev/null @@ -1,2476 +0,0 @@ -/* - LEAmDNS_Structs.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#include "LEAmDNS_Priv.h" -#include "LEAmDNS_lwIPdefs.h" - -namespace esp8266 -{ - -/* - LEAmDNS -*/ -namespace MDNSImplementation -{ - -/** - STRUCTS -*/ - -/** - MDNSResponder::stcMDNSServiceTxt - - One MDNS TXT item. - m_pcValue may be '\0'. - Objects can be chained together (list, m_pNext). - A 'm_bTemp' flag differentiates between static and dynamic items. - Output as byte array 'c#=1' is supported. -*/ - -/* - MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt constructor -*/ -MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt(const char* p_pcKey /*= 0*/, - const char* p_pcValue /*= 0*/, - bool p_bTemp /*= false*/) - : m_pNext(0), - m_pcKey(0), - m_pcValue(0), - m_bTemp(p_bTemp) -{ - - setKey(p_pcKey); - setValue(p_pcValue); -} - -/* - MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt copy-constructor -*/ -MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt(const MDNSResponder::stcMDNSServiceTxt& p_Other) - : m_pNext(0), - m_pcKey(0), - m_pcValue(0), - m_bTemp(false) -{ - - operator=(p_Other); -} - -/* - MDNSResponder::stcMDNSServiceTxt::~stcMDNSServiceTxt destructor -*/ -MDNSResponder::stcMDNSServiceTxt::~stcMDNSServiceTxt(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSServiceTxt::operator= -*/ -MDNSResponder::stcMDNSServiceTxt& MDNSResponder::stcMDNSServiceTxt::operator=(const MDNSResponder::stcMDNSServiceTxt& p_Other) -{ - - if (&p_Other != this) - { - clear(); - set(p_Other.m_pcKey, p_Other.m_pcValue, p_Other.m_bTemp); - } - return *this; -} - -/* - MDNSResponder::stcMDNSServiceTxt::clear -*/ -bool MDNSResponder::stcMDNSServiceTxt::clear(void) -{ - - releaseKey(); - releaseValue(); - return true; -} - -/* - MDNSResponder::stcMDNSServiceTxt::allocKey -*/ -char* MDNSResponder::stcMDNSServiceTxt::allocKey(size_t p_stLength) -{ - - releaseKey(); - if (p_stLength) - { - m_pcKey = new char[p_stLength + 1]; - } - return m_pcKey; -} - -/* - MDNSResponder::stcMDNSServiceTxt::setKey -*/ -bool MDNSResponder::stcMDNSServiceTxt::setKey(const char* p_pcKey, - size_t p_stLength) -{ - - bool bResult = false; - - releaseKey(); - if (p_stLength) - { - if (allocKey(p_stLength)) - { - strncpy(m_pcKey, p_pcKey, p_stLength); - m_pcKey[p_stLength] = 0; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxt::setKey -*/ -bool MDNSResponder::stcMDNSServiceTxt::setKey(const char* p_pcKey) -{ - - return setKey(p_pcKey, (p_pcKey ? strlen(p_pcKey) : 0)); -} - -/* - MDNSResponder::stcMDNSServiceTxt::releaseKey -*/ -bool MDNSResponder::stcMDNSServiceTxt::releaseKey(void) -{ - - if (m_pcKey) - { - delete[] m_pcKey; - m_pcKey = 0; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceTxt::allocValue -*/ -char* MDNSResponder::stcMDNSServiceTxt::allocValue(size_t p_stLength) -{ - - releaseValue(); - if (p_stLength) - { - m_pcValue = new char[p_stLength + 1]; - } - return m_pcValue; -} - -/* - MDNSResponder::stcMDNSServiceTxt::setValue -*/ -bool MDNSResponder::stcMDNSServiceTxt::setValue(const char* p_pcValue, - size_t p_stLength) -{ - - bool bResult = false; - - releaseValue(); - if (p_stLength) - { - if (allocValue(p_stLength)) - { - strncpy(m_pcValue, p_pcValue, p_stLength); - m_pcValue[p_stLength] = 0; - bResult = true; - } - } - else // No value -> also OK - { - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxt::setValue -*/ -bool MDNSResponder::stcMDNSServiceTxt::setValue(const char* p_pcValue) -{ - - return setValue(p_pcValue, (p_pcValue ? strlen(p_pcValue) : 0)); -} - -/* - MDNSResponder::stcMDNSServiceTxt::releaseValue -*/ -bool MDNSResponder::stcMDNSServiceTxt::releaseValue(void) -{ - - if (m_pcValue) - { - delete[] m_pcValue; - m_pcValue = 0; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceTxt::set -*/ -bool MDNSResponder::stcMDNSServiceTxt::set(const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp /*= false*/) -{ - - m_bTemp = p_bTemp; - return ((setKey(p_pcKey)) && - (setValue(p_pcValue))); -} - -/* - MDNSResponder::stcMDNSServiceTxt::update -*/ -bool MDNSResponder::stcMDNSServiceTxt::update(const char* p_pcValue) -{ - - return setValue(p_pcValue); -} - -/* - MDNSResponder::stcMDNSServiceTxt::length - - length of eg. 'c#=1' without any closing '\0' -*/ -size_t MDNSResponder::stcMDNSServiceTxt::length(void) const -{ - - size_t stLength = 0; - if (m_pcKey) - { - stLength += strlen(m_pcKey); // Key - stLength += 1; // '=' - stLength += (m_pcValue ? strlen(m_pcValue) : 0); // Value - } - return stLength; -} - - -/** - MDNSResponder::stcMDNSServiceTxts - - A list of zero or more MDNS TXT items. - Dynamic TXT items can be removed by 'removeTempTxts'. - A TXT item can be looke up by its 'key' member. - Export as ';'-separated byte array is supported. - Export as 'length byte coded' byte array is supported. - Comparision ((all A TXT items in B and equal) AND (all B TXT items in A and equal)) is supported. - -*/ - -/* - MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts contructor -*/ -MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts(void) - : m_pTxts(0) -{ - -} - -/* - MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts copy-constructor -*/ -MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts(const stcMDNSServiceTxts& p_Other) - : m_pTxts(0) -{ - - operator=(p_Other); -} - -/* - MDNSResponder::stcMDNSServiceTxts::~stcMDNSServiceTxts destructor -*/ -MDNSResponder::stcMDNSServiceTxts::~stcMDNSServiceTxts(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSServiceTxts::operator= -*/ -MDNSResponder::stcMDNSServiceTxts& MDNSResponder::stcMDNSServiceTxts::operator=(const stcMDNSServiceTxts& p_Other) -{ - - if (this != &p_Other) - { - clear(); - - for (stcMDNSServiceTxt* pOtherTxt = p_Other.m_pTxts; pOtherTxt; pOtherTxt = pOtherTxt->m_pNext) - { - add(new stcMDNSServiceTxt(*pOtherTxt)); - } - } - return *this; -} - -/* - MDNSResponder::stcMDNSServiceTxts::clear -*/ -bool MDNSResponder::stcMDNSServiceTxts::clear(void) -{ - - while (m_pTxts) - { - stcMDNSServiceTxt* pNext = m_pTxts->m_pNext; - delete m_pTxts; - m_pTxts = pNext; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceTxts::add -*/ -bool MDNSResponder::stcMDNSServiceTxts::add(MDNSResponder::stcMDNSServiceTxt* p_pTxt) -{ - - bool bResult = false; - - if (p_pTxt) - { - p_pTxt->m_pNext = m_pTxts; - m_pTxts = p_pTxt; - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::remove -*/ -bool MDNSResponder::stcMDNSServiceTxts::remove(stcMDNSServiceTxt* p_pTxt) -{ - - bool bResult = false; - - if (p_pTxt) - { - stcMDNSServiceTxt* pPred = m_pTxts; - while ((pPred) && - (pPred->m_pNext != p_pTxt)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pTxt->m_pNext; - delete p_pTxt; - bResult = true; - } - else if (m_pTxts == p_pTxt) // No predecesor, but first item - { - m_pTxts = p_pTxt->m_pNext; - delete p_pTxt; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::removeTempTxts -*/ -bool MDNSResponder::stcMDNSServiceTxts::removeTempTxts(void) -{ - - bool bResult = true; - - stcMDNSServiceTxt* pTxt = m_pTxts; - while ((bResult) && - (pTxt)) - { - stcMDNSServiceTxt* pNext = pTxt->m_pNext; - if (pTxt->m_bTemp) - { - bResult = remove(pTxt); - } - pTxt = pNext; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::find -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::stcMDNSServiceTxts::find(const char* p_pcKey) -{ - - stcMDNSServiceTxt* pResult = 0; - - for (stcMDNSServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) - { - if ((p_pcKey) && - (0 == strcmp(pTxt->m_pcKey, p_pcKey))) - { - pResult = pTxt; - break; - } - } - return pResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::find -*/ -const MDNSResponder::stcMDNSServiceTxt* MDNSResponder::stcMDNSServiceTxts::find(const char* p_pcKey) const -{ - - const stcMDNSServiceTxt* pResult = 0; - - for (const stcMDNSServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) - { - if ((p_pcKey) && - (0 == strcmp(pTxt->m_pcKey, p_pcKey))) - { - - pResult = pTxt; - break; - } - } - return pResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::find -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::stcMDNSServiceTxts::find(const stcMDNSServiceTxt* p_pTxt) -{ - - stcMDNSServiceTxt* pResult = 0; - - for (stcMDNSServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) - { - if (p_pTxt == pTxt) - { - pResult = pTxt; - break; - } - } - return pResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::length -*/ -uint16_t MDNSResponder::stcMDNSServiceTxts::length(void) const -{ - - uint16_t u16Length = 0; - - stcMDNSServiceTxt* pTxt = m_pTxts; - while (pTxt) - { - u16Length += 1; // Length byte - u16Length += pTxt->length(); // Text - pTxt = pTxt->m_pNext; - } - return u16Length; -} - -/* - MDNSResponder::stcMDNSServiceTxts::c_strLength - - (incl. closing '\0'). Length bytes place is used for delimiting ';' and closing '\0' -*/ -size_t MDNSResponder::stcMDNSServiceTxts::c_strLength(void) const -{ - - return length(); -} - -/* - MDNSResponder::stcMDNSServiceTxts::c_str -*/ -bool MDNSResponder::stcMDNSServiceTxts::c_str(char* p_pcBuffer) -{ - - bool bResult = false; - - if (p_pcBuffer) - { - bResult = true; - - *p_pcBuffer = 0; - for (stcMDNSServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) - { - size_t stLength; - if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) - { - if (pTxt != m_pTxts) - { - *p_pcBuffer++ = ';'; - } - strncpy(p_pcBuffer, pTxt->m_pcKey, stLength); p_pcBuffer[stLength] = 0; - p_pcBuffer += stLength; - *p_pcBuffer++ = '='; - if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) - { - strncpy(p_pcBuffer, pTxt->m_pcValue, stLength); p_pcBuffer[stLength] = 0; - p_pcBuffer += stLength; - } - } - } - *p_pcBuffer++ = 0; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::bufferLength - - (incl. closing '\0'). -*/ -size_t MDNSResponder::stcMDNSServiceTxts::bufferLength(void) const -{ - - return (length() + 1); -} - -/* - MDNSResponder::stcMDNSServiceTxts::toBuffer -*/ -bool MDNSResponder::stcMDNSServiceTxts::buffer(char* p_pcBuffer) -{ - - bool bResult = false; - - if (p_pcBuffer) - { - bResult = true; - - *p_pcBuffer = 0; - for (stcMDNSServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) - { - *(unsigned char*)p_pcBuffer++ = pTxt->length(); - size_t stLength; - if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) - { - memcpy(p_pcBuffer, pTxt->m_pcKey, stLength); - p_pcBuffer += stLength; - *p_pcBuffer++ = '='; - if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) - { - memcpy(p_pcBuffer, pTxt->m_pcValue, stLength); - p_pcBuffer += stLength; - } - } - } - *p_pcBuffer++ = 0; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::compare -*/ -bool MDNSResponder::stcMDNSServiceTxts::compare(const MDNSResponder::stcMDNSServiceTxts& p_Other) const -{ - - bool bResult = false; - - if ((bResult = (length() == p_Other.length()))) - { - // Compare A->B - for (const stcMDNSServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) - { - const stcMDNSServiceTxt* pOtherTxt = p_Other.find(pTxt->m_pcKey); - bResult = ((pOtherTxt) && - (pTxt->m_pcValue) && - (pOtherTxt->m_pcValue) && - (strlen(pTxt->m_pcValue) == strlen(pOtherTxt->m_pcValue)) && - (0 == strcmp(pTxt->m_pcValue, pOtherTxt->m_pcValue))); - } - // Compare B->A - for (const stcMDNSServiceTxt* pOtherTxt = p_Other.m_pTxts; ((bResult) && (pOtherTxt)); pOtherTxt = pOtherTxt->m_pNext) - { - const stcMDNSServiceTxt* pTxt = find(pOtherTxt->m_pcKey); - bResult = ((pTxt) && - (pOtherTxt->m_pcValue) && - (pTxt->m_pcValue) && - (strlen(pOtherTxt->m_pcValue) == strlen(pTxt->m_pcValue)) && - (0 == strcmp(pOtherTxt->m_pcValue, pTxt->m_pcValue))); - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::operator== -*/ -bool MDNSResponder::stcMDNSServiceTxts::operator==(const stcMDNSServiceTxts& p_Other) const -{ - - return compare(p_Other); -} - -/* - MDNSResponder::stcMDNSServiceTxts::operator!= -*/ -bool MDNSResponder::stcMDNSServiceTxts::operator!=(const stcMDNSServiceTxts& p_Other) const -{ - - return !compare(p_Other); -} - - -/** - MDNSResponder::stcMDNS_MsgHeader - - A MDNS message haeder. - -*/ - -/* - MDNSResponder::stcMDNS_MsgHeader::stcMDNS_MsgHeader -*/ -MDNSResponder::stcMDNS_MsgHeader::stcMDNS_MsgHeader(uint16_t p_u16ID /*= 0*/, - bool p_bQR /*= false*/, - unsigned char p_ucOpcode /*= 0*/, - bool p_bAA /*= false*/, - bool p_bTC /*= false*/, - bool p_bRD /*= false*/, - bool p_bRA /*= false*/, - unsigned char p_ucRCode /*= 0*/, - uint16_t p_u16QDCount /*= 0*/, - uint16_t p_u16ANCount /*= 0*/, - uint16_t p_u16NSCount /*= 0*/, - uint16_t p_u16ARCount /*= 0*/) - : m_u16ID(p_u16ID), - m_1bQR(p_bQR), m_4bOpcode(p_ucOpcode), m_1bAA(p_bAA), m_1bTC(p_bTC), m_1bRD(p_bRD), - m_1bRA(p_bRA), m_3bZ(0), m_4bRCode(p_ucRCode), - m_u16QDCount(p_u16QDCount), - m_u16ANCount(p_u16ANCount), - m_u16NSCount(p_u16NSCount), - m_u16ARCount(p_u16ARCount) -{ - -} - - -/** - MDNSResponder::stcMDNS_RRDomain - - A MDNS domain object. - The labels of the domain are stored (DNS-like encoded) in 'm_acName': - [length byte]varlength label[length byte]varlength label[0] - 'm_u16NameLength' stores the used length of 'm_acName'. - Dynamic label addition is supported. - Comparison is supported. - Export as byte array 'esp8266.local' is supported. - -*/ - -/* - MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain constructor -*/ -MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain(void) - : m_u16NameLength(0) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain copy-constructor -*/ -MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain(const stcMDNS_RRDomain& p_Other) - : m_u16NameLength(0) -{ - - operator=(p_Other); -} - -/* - MDNSResponder::stcMDNS_RRDomain::operator = -*/ -MDNSResponder::stcMDNS_RRDomain& MDNSResponder::stcMDNS_RRDomain::operator=(const stcMDNS_RRDomain& p_Other) -{ - - if (&p_Other != this) - { - memcpy(m_acName, p_Other.m_acName, sizeof(m_acName)); - m_u16NameLength = p_Other.m_u16NameLength; - } - return *this; -} - -/* - MDNSResponder::stcMDNS_RRDomain::clear -*/ -bool MDNSResponder::stcMDNS_RRDomain::clear(void) -{ - - memset(m_acName, 0, sizeof(m_acName)); - m_u16NameLength = 0; - return true; -} - -/* - MDNSResponder::stcMDNS_RRDomain::addLabel -*/ -bool MDNSResponder::stcMDNS_RRDomain::addLabel(const char* p_pcLabel, - bool p_bPrependUnderline /*= false*/) -{ - - bool bResult = false; - - size_t stLength = (p_pcLabel - ? (strlen(p_pcLabel) + (p_bPrependUnderline ? 1 : 0)) - : 0); - if ((MDNS_DOMAIN_LABEL_MAXLENGTH >= stLength) && - (MDNS_DOMAIN_MAXLENGTH >= (m_u16NameLength + (1 + stLength)))) - { - // Length byte - m_acName[m_u16NameLength] = (unsigned char)stLength; // Might be 0! - ++m_u16NameLength; - // Label - if (stLength) - { - if (p_bPrependUnderline) - { - m_acName[m_u16NameLength++] = '_'; - --stLength; - } - strncpy(&(m_acName[m_u16NameLength]), p_pcLabel, stLength); m_acName[m_u16NameLength + stLength] = 0; - m_u16NameLength += stLength; - } - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNS_RRDomain::compare -*/ -bool MDNSResponder::stcMDNS_RRDomain::compare(const stcMDNS_RRDomain& p_Other) const -{ - - bool bResult = false; - - if (m_u16NameLength == p_Other.m_u16NameLength) - { - const char* pT = m_acName; - const char* pO = p_Other.m_acName; - while ((pT) && - (pO) && - (*((unsigned char*)pT) == *((unsigned char*)pO)) && // Same length AND - (0 == strncasecmp((pT + 1), (pO + 1), *((unsigned char*)pT)))) // Same content - { - if (*((unsigned char*)pT)) // Not 0 - { - pT += (1 + * ((unsigned char*)pT)); // Shift by length byte and lenght - pO += (1 + * ((unsigned char*)pO)); - } - else // Is 0 -> Successfully reached the end - { - bResult = true; - break; - } - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNS_RRDomain::operator == -*/ -bool MDNSResponder::stcMDNS_RRDomain::operator==(const stcMDNS_RRDomain& p_Other) const -{ - - return compare(p_Other); -} - -/* - MDNSResponder::stcMDNS_RRDomain::operator != -*/ -bool MDNSResponder::stcMDNS_RRDomain::operator!=(const stcMDNS_RRDomain& p_Other) const -{ - - return !compare(p_Other); -} - -/* - MDNSResponder::stcMDNS_RRDomain::operator > -*/ -bool MDNSResponder::stcMDNS_RRDomain::operator>(const stcMDNS_RRDomain& p_Other) const -{ - - // TODO: Check, if this is a good idea... - return !compare(p_Other); -} - -/* - MDNSResponder::stcMDNS_RRDomain::c_strLength -*/ -size_t MDNSResponder::stcMDNS_RRDomain::c_strLength(void) const -{ - - size_t stLength = 0; - - unsigned char* pucLabelLength = (unsigned char*)m_acName; - while (*pucLabelLength) - { - stLength += (*pucLabelLength + 1 /* +1 for '.' or '\0'*/); - pucLabelLength += (*pucLabelLength + 1); - } - return stLength; -} - -/* - MDNSResponder::stcMDNS_RRDomain::c_str -*/ -bool MDNSResponder::stcMDNS_RRDomain::c_str(char* p_pcBuffer) -{ - - bool bResult = false; - - if (p_pcBuffer) - { - *p_pcBuffer = 0; - unsigned char* pucLabelLength = (unsigned char*)m_acName; - while (*pucLabelLength) - { - memcpy(p_pcBuffer, (const char*)(pucLabelLength + 1), *pucLabelLength); - p_pcBuffer += *pucLabelLength; - pucLabelLength += (*pucLabelLength + 1); - *p_pcBuffer++ = (*pucLabelLength ? '.' : '\0'); - } - bResult = true; - } - return bResult; -} - - -/** - MDNSResponder::stcMDNS_RRAttributes - - A MDNS attributes object. - -*/ - -/* - MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes constructor -*/ -MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes(uint16_t p_u16Type /*= 0*/, - uint16_t p_u16Class /*= 1 DNS_RRCLASS_IN Internet*/) - : m_u16Type(p_u16Type), - m_u16Class(p_u16Class) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes copy-constructor -*/ -MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes(const MDNSResponder::stcMDNS_RRAttributes& p_Other) -{ - - operator=(p_Other); -} - -/* - MDNSResponder::stcMDNS_RRAttributes::operator = -*/ -MDNSResponder::stcMDNS_RRAttributes& MDNSResponder::stcMDNS_RRAttributes::operator=(const MDNSResponder::stcMDNS_RRAttributes& p_Other) -{ - - if (&p_Other != this) - { - m_u16Type = p_Other.m_u16Type; - m_u16Class = p_Other.m_u16Class; - } - return *this; -} - - -/** - MDNSResponder::stcMDNS_RRHeader - - A MDNS record header (domain and attributes) object. - -*/ - -/* - MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader constructor -*/ -MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader(void) -{ - -} - -/* - MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader copy-constructor -*/ -MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader(const stcMDNS_RRHeader& p_Other) -{ - - operator=(p_Other); -} - -/* - MDNSResponder::stcMDNS_RRHeader::operator = -*/ -MDNSResponder::stcMDNS_RRHeader& MDNSResponder::stcMDNS_RRHeader::operator=(const MDNSResponder::stcMDNS_RRHeader& p_Other) -{ - - if (&p_Other != this) - { - m_Domain = p_Other.m_Domain; - m_Attributes = p_Other.m_Attributes; - } - return *this; -} - -/* - MDNSResponder::stcMDNS_RRHeader::clear -*/ -bool MDNSResponder::stcMDNS_RRHeader::clear(void) -{ - - m_Domain.clear(); - return true; -} - - -/** - MDNSResponder::stcMDNS_RRQuestion - - A MDNS question record object (header + question flags) - -*/ - -/* - MDNSResponder::stcMDNS_RRQuestion::stcMDNS_RRQuestion constructor -*/ -MDNSResponder::stcMDNS_RRQuestion::stcMDNS_RRQuestion(void) - : m_pNext(0), - m_bUnicast(false) -{ - -} - - -/** - MDNSResponder::stcMDNS_RRAnswer - - A MDNS answer record object (header + answer content). - This is a 'virtual' base class for all other MDNS answer classes. - -*/ - -/* - MDNSResponder::stcMDNS_RRAnswer::stcMDNS_RRAnswer constructor -*/ -MDNSResponder::stcMDNS_RRAnswer::stcMDNS_RRAnswer(enuAnswerType p_AnswerType, - const MDNSResponder::stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : m_pNext(0), - m_AnswerType(p_AnswerType), - m_Header(p_Header), - m_u32TTL(p_u32TTL) -{ - - // Extract 'cache flush'-bit - m_bCacheFlush = (m_Header.m_Attributes.m_u16Class & 0x8000); - m_Header.m_Attributes.m_u16Class &= (~0x8000); -} - -/* - MDNSResponder::stcMDNS_RRAnswer::~stcMDNS_RRAnswer destructor -*/ -MDNSResponder::stcMDNS_RRAnswer::~stcMDNS_RRAnswer(void) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswer::answerType -*/ -MDNSResponder::enuAnswerType MDNSResponder::stcMDNS_RRAnswer::answerType(void) const -{ - - return m_AnswerType; -} - -/* - MDNSResponder::stcMDNS_RRAnswer::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswer::clear(void) -{ - - m_pNext = 0; - m_Header.clear(); - return true; -} - - -/** - MDNSResponder::stcMDNS_RRAnswerA - - A MDNS A answer object. - Extends the base class by an IP4 address member. - -*/ - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::stcMDNS_RRAnswerA::stcMDNS_RRAnswerA constructor -*/ -MDNSResponder::stcMDNS_RRAnswerA::stcMDNS_RRAnswerA(const MDNSResponder::stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : stcMDNS_RRAnswer(AnswerType_A, p_Header, p_u32TTL), - m_IPAddress(0, 0, 0, 0) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswerA::stcMDNS_RRAnswerA destructor -*/ -MDNSResponder::stcMDNS_RRAnswerA::~stcMDNS_RRAnswerA(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRAnswerA::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswerA::clear(void) -{ - - m_IPAddress = IPAddress(0, 0, 0, 0); - return true; -} -#endif - - -/** - MDNSResponder::stcMDNS_RRAnswerPTR - - A MDNS PTR answer object. - Extends the base class by a MDNS domain member. - -*/ - -/* - MDNSResponder::stcMDNS_RRAnswerPTR::stcMDNS_RRAnswerPTR constructor -*/ -MDNSResponder::stcMDNS_RRAnswerPTR::stcMDNS_RRAnswerPTR(const MDNSResponder::stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : stcMDNS_RRAnswer(AnswerType_PTR, p_Header, p_u32TTL) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswerPTR::~stcMDNS_RRAnswerPTR destructor -*/ -MDNSResponder::stcMDNS_RRAnswerPTR::~stcMDNS_RRAnswerPTR(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRAnswerPTR::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswerPTR::clear(void) -{ - - m_PTRDomain.clear(); - return true; -} - - -/** - MDNSResponder::stcMDNS_RRAnswerTXT - - A MDNS TXT answer object. - Extends the base class by a MDNS TXT items list member. - -*/ - -/* - MDNSResponder::stcMDNS_RRAnswerTXT::stcMDNS_RRAnswerTXT constructor -*/ -MDNSResponder::stcMDNS_RRAnswerTXT::stcMDNS_RRAnswerTXT(const MDNSResponder::stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : stcMDNS_RRAnswer(AnswerType_TXT, p_Header, p_u32TTL) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswerTXT::~stcMDNS_RRAnswerTXT destructor -*/ -MDNSResponder::stcMDNS_RRAnswerTXT::~stcMDNS_RRAnswerTXT(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRAnswerTXT::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswerTXT::clear(void) -{ - - m_Txts.clear(); - return true; -} - - -/** - MDNSResponder::stcMDNS_RRAnswerAAAA - - A MDNS AAAA answer object. - (Should) extend the base class by an IP6 address member. - -*/ - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::stcMDNS_RRAnswerAAAA::stcMDNS_RRAnswerAAAA constructor -*/ -MDNSResponder::stcMDNS_RRAnswerAAAA::stcMDNS_RRAnswerAAAA(const MDNSResponder::stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : stcMDNS_RRAnswer(AnswerType_AAAA, p_Header, p_u32TTL) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswerAAAA::~stcMDNS_RRAnswerAAAA destructor -*/ -MDNSResponder::stcMDNS_RRAnswerAAAA::~stcMDNS_RRAnswerAAAA(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRAnswerAAAA::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswerAAAA::clear(void) -{ - - return true; -} -#endif - - -/** - MDNSResponder::stcMDNS_RRAnswerSRV - - A MDNS SRV answer object. - Extends the base class by a port member. - -*/ - -/* - MDNSResponder::stcMDNS_RRAnswerSRV::stcMDNS_RRAnswerSRV constructor -*/ -MDNSResponder::stcMDNS_RRAnswerSRV::stcMDNS_RRAnswerSRV(const MDNSResponder::stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : stcMDNS_RRAnswer(AnswerType_SRV, p_Header, p_u32TTL), - m_u16Priority(0), - m_u16Weight(0), - m_u16Port(0) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswerSRV::~stcMDNS_RRAnswerSRV destructor -*/ -MDNSResponder::stcMDNS_RRAnswerSRV::~stcMDNS_RRAnswerSRV(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRAnswerSRV::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswerSRV::clear(void) -{ - - m_u16Priority = 0; - m_u16Weight = 0; - m_u16Port = 0; - m_SRVDomain.clear(); - return true; -} - - -/** - MDNSResponder::stcMDNS_RRAnswerGeneric - - An unknown (generic) MDNS answer object. - Extends the base class by a RDATA buffer member. - -*/ - -/* - MDNSResponder::stcMDNS_RRAnswerGeneric::stcMDNS_RRAnswerGeneric constructor -*/ -MDNSResponder::stcMDNS_RRAnswerGeneric::stcMDNS_RRAnswerGeneric(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : stcMDNS_RRAnswer(AnswerType_Generic, p_Header, p_u32TTL), - m_u16RDLength(0), - m_pu8RDData(0) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswerGeneric::~stcMDNS_RRAnswerGeneric destructor -*/ -MDNSResponder::stcMDNS_RRAnswerGeneric::~stcMDNS_RRAnswerGeneric(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRAnswerGeneric::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswerGeneric::clear(void) -{ - - if (m_pu8RDData) - { - delete[] m_pu8RDData; - m_pu8RDData = 0; - } - m_u16RDLength = 0; - - return true; -} - - -/** - MDNSResponder::stcProbeInformation - - Probing status information for a host or service domain - -*/ - -/* - MDNSResponder::stcProbeInformation::stcProbeInformation constructor -*/ -MDNSResponder::stcProbeInformation::stcProbeInformation(void) - : m_ProbingStatus(ProbingStatus_WaitingForData), - m_u8SentCount(0), - m_Timeout(esp8266::polledTimeout::oneShotMs::neverExpires), - m_bConflict(false), - m_bTiebreakNeeded(false), - m_fnHostProbeResultCallback(0), - m_fnServiceProbeResultCallback(0) -{ -} - -/* - MDNSResponder::stcProbeInformation::clear -*/ -bool MDNSResponder::stcProbeInformation::clear(bool p_bClearUserdata /*= false*/) -{ - - m_ProbingStatus = ProbingStatus_WaitingForData; - m_u8SentCount = 0; - m_Timeout.resetToNeverExpires(); - m_bConflict = false; - m_bTiebreakNeeded = false; - if (p_bClearUserdata) - { - m_fnHostProbeResultCallback = 0; - m_fnServiceProbeResultCallback = 0; - } - return true; -} - -/** - MDNSResponder::stcMDNSService - - A MDNS service object (to be announced by the MDNS responder) - The service instance may be '\0'; in this case the hostname is used - and the flag m_bAutoName is set. If the hostname changes, all 'auto- - named' services are renamed also. - m_u8Replymask is used while preparing a response to a MDNS query. It is - resetted in '_sendMDNSMessage' afterwards. -*/ - -/* - MDNSResponder::stcMDNSService::stcMDNSService constructor -*/ -MDNSResponder::stcMDNSService::stcMDNSService(const char* p_pcName /*= 0*/, - const char* p_pcService /*= 0*/, - const char* p_pcProtocol /*= 0*/) - : m_pNext(0), - m_pcName(0), - m_bAutoName(false), - m_pcService(0), - m_pcProtocol(0), - m_u16Port(0), - m_u8ReplyMask(0), - m_fnTxtCallback(0) -{ - - setName(p_pcName); - setService(p_pcService); - setProtocol(p_pcProtocol); -} - -/* - MDNSResponder::stcMDNSService::~stcMDNSService destructor -*/ -MDNSResponder::stcMDNSService::~stcMDNSService(void) -{ - - releaseName(); - releaseService(); - releaseProtocol(); -} - -/* - MDNSResponder::stcMDNSService::setName -*/ -bool MDNSResponder::stcMDNSService::setName(const char* p_pcName) -{ - - bool bResult = false; - - releaseName(); - size_t stLength = (p_pcName ? strlen(p_pcName) : 0); - if (stLength) - { - if ((bResult = (0 != (m_pcName = new char[stLength + 1])))) - { - strncpy(m_pcName, p_pcName, stLength); - m_pcName[stLength] = 0; - } - } - else - { - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSService::releaseName -*/ -bool MDNSResponder::stcMDNSService::releaseName(void) -{ - - if (m_pcName) - { - delete[] m_pcName; - m_pcName = 0; - } - return true; -} - -/* - MDNSResponder::stcMDNSService::setService -*/ -bool MDNSResponder::stcMDNSService::setService(const char* p_pcService) -{ - - bool bResult = false; - - releaseService(); - size_t stLength = (p_pcService ? strlen(p_pcService) : 0); - if (stLength) - { - if ((bResult = (0 != (m_pcService = new char[stLength + 1])))) - { - strncpy(m_pcService, p_pcService, stLength); - m_pcService[stLength] = 0; - } - } - else - { - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSService::releaseService -*/ -bool MDNSResponder::stcMDNSService::releaseService(void) -{ - - if (m_pcService) - { - delete[] m_pcService; - m_pcService = 0; - } - return true; -} - -/* - MDNSResponder::stcMDNSService::setProtocol -*/ -bool MDNSResponder::stcMDNSService::setProtocol(const char* p_pcProtocol) -{ - - bool bResult = false; - - releaseProtocol(); - size_t stLength = (p_pcProtocol ? strlen(p_pcProtocol) : 0); - if (stLength) - { - if ((bResult = (0 != (m_pcProtocol = new char[stLength + 1])))) - { - strncpy(m_pcProtocol, p_pcProtocol, stLength); - m_pcProtocol[stLength] = 0; - } - } - else - { - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSService::releaseProtocol -*/ -bool MDNSResponder::stcMDNSService::releaseProtocol(void) -{ - - if (m_pcProtocol) - { - delete[] m_pcProtocol; - m_pcProtocol = 0; - } - return true; -} - - -/** - MDNSResponder::stcMDNSServiceQuery - - A MDNS service query object. - Service queries may be static or dynamic. - As the static service query is processed in the blocking function 'queryService', - only one static service service may exist. The processing of the answers is done - on the WiFi-stack side of the ESP stack structure (via 'UDPContext.onRx(_update)'). - -*/ - -/** - MDNSResponder::stcMDNSServiceQuery::stcAnswer - - One answer for a service query. - Every answer must contain - - a service instance entry (pivot), - and may contain - - a host domain, - - a port - - an IP4 address - (- an IP6 address) - - a MDNS TXTs - The existance of a component is flaged in 'm_u32ContentFlags'. - For every answer component a TTL value is maintained. - Answer objects can be connected to a linked list. - - For the host domain, service domain and TXTs components, a char array - representation can be retrieved (which is created on demand). - -*/ - -/** - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL - - The TTL (Time-To-Live) for an specific answer content. - The 80% and outdated states are calculated based on the current time (millis) - and the 'set' time (also millis). - If the answer is scheduled for an update, the corresponding flag should be set. - - / - - / * - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL constructor - / - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL(uint32_t p_u32TTL / *= 0* /) - : m_bUpdateScheduled(false) { - - set(p_u32TTL * 1000); - } - - / * - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set - / - bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set(uint32_t p_u32TTL) { - - m_TTLTimeFlag.restart(p_u32TTL * 1000); - m_bUpdateScheduled = false; - - return true; - } - - / * - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::has80Percent - / - bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::has80Percent(void) const { - - return ((m_TTLTimeFlag.getTimeout()) && - (!m_bUpdateScheduled) && - (m_TTLTimeFlag.hypotheticalTimeout((m_TTLTimeFlag.getTimeout() * 800) / 1000))); - } - - / * - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::isOutdated - / - bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::isOutdated(void) const { - - return ((m_TTLTimeFlag.getTimeout()) && - (m_TTLTimeFlag.flagged())); - }*/ - - -/** - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL - - The TTL (Time-To-Live) for an specific answer content. - The 80% and outdated states are calculated based on the current time (millis) - and the 'set' time (also millis). - If the answer is scheduled for an update, the corresponding flag should be set. - -*/ - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL constructor -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL(void) - : m_u32TTL(0), - m_TTLTimeout(esp8266::polledTimeout::oneShotMs::neverExpires), - m_timeoutLevel(TIMEOUTLEVEL_UNSET) -{ - -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set(uint32_t p_u32TTL) -{ - - m_u32TTL = p_u32TTL; - if (m_u32TTL) - { - m_timeoutLevel = TIMEOUTLEVEL_BASE; // Set to 80% - m_TTLTimeout.reset(timeout()); - } - else - { - m_timeoutLevel = TIMEOUTLEVEL_UNSET; // undef - m_TTLTimeout.resetToNeverExpires(); - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged(void) -{ - - return ((m_u32TTL) && - (TIMEOUTLEVEL_UNSET != m_timeoutLevel) && - (m_TTLTimeout.expired())); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::restart -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::restart(void) -{ - - bool bResult = true; - - if ((TIMEOUTLEVEL_BASE <= m_timeoutLevel) && // >= 80% AND - (TIMEOUTLEVEL_FINAL > m_timeoutLevel)) // < 100% - { - - m_timeoutLevel += TIMEOUTLEVEL_INTERVAL; // increment by 5% - m_TTLTimeout.reset(timeout()); - } - else - { - bResult = false; - m_TTLTimeout.resetToNeverExpires(); - m_timeoutLevel = TIMEOUTLEVEL_UNSET; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::prepareDeletion -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::prepareDeletion(void) -{ - - m_timeoutLevel = TIMEOUTLEVEL_FINAL; - m_TTLTimeout.reset(1 * 1000); // See RFC 6762, 10.1 - - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::finalTimeoutLevel -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::finalTimeoutLevel(void) const -{ - - return (TIMEOUTLEVEL_FINAL == m_timeoutLevel); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::timeout -*/ -unsigned long MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::timeout(void) const -{ - - uint32_t u32Timeout = esp8266::polledTimeout::oneShotMs::neverExpires; - - if (TIMEOUTLEVEL_BASE == m_timeoutLevel) // 80% - { - u32Timeout = (m_u32TTL * 800); // to milliseconds - } - else if ((TIMEOUTLEVEL_BASE < m_timeoutLevel) && // >80% AND - (TIMEOUTLEVEL_FINAL >= m_timeoutLevel)) // <= 100% - { - - u32Timeout = (m_u32TTL * 50); - } // else: invalid - return u32Timeout; -} - - -#ifdef MDNS_IP4_SUPPORT -/** - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address - -*/ - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address::stcIP4Address constructor -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address::stcIP4Address(IPAddress p_IPAddress, - uint32_t p_u32TTL /*= 0*/) - : m_pNext(0), - m_IPAddress(p_IPAddress) -{ - - m_TTL.set(p_u32TTL); -} -#endif - - -/** - MDNSResponder::stcMDNSServiceQuery::stcAnswer -*/ - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcAnswer constructor -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcAnswer(void) - : m_pNext(0), - m_pcServiceDomain(0), - m_pcHostDomain(0), - m_u16Port(0), - m_pcTxts(0), -#ifdef MDNS_IP4_SUPPORT - m_pIP4Addresses(0), -#endif -#ifdef MDNS_IP6_SUPPORT - m_pIP6Addresses(0), -#endif - m_u32ContentFlags(0) -{ -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::~stcAnswer destructor -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::~stcAnswer(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::clear -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::clear(void) -{ - - return ((releaseTxts()) && -#ifdef MDNS_IP4_SUPPORT - (releaseIP4Addresses()) && -#endif -#ifdef MDNS_IP6_SUPPORT - (releaseIP6Addresses()) -#endif - (releaseHostDomain()) && - (releaseServiceDomain())); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocServiceDomain - - Alloc memory for the char array representation of the service domain. - -*/ -char* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocServiceDomain(size_t p_stLength) -{ - - releaseServiceDomain(); - if (p_stLength) - { - m_pcServiceDomain = new char[p_stLength]; - } - return m_pcServiceDomain; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseServiceDomain -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseServiceDomain(void) -{ - - if (m_pcServiceDomain) - { - delete[] m_pcServiceDomain; - m_pcServiceDomain = 0; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocHostDomain - - Alloc memory for the char array representation of the host domain. - -*/ -char* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocHostDomain(size_t p_stLength) -{ - - releaseHostDomain(); - if (p_stLength) - { - m_pcHostDomain = new char[p_stLength]; - } - return m_pcHostDomain; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseHostDomain -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseHostDomain(void) -{ - - if (m_pcHostDomain) - { - delete[] m_pcHostDomain; - m_pcHostDomain = 0; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocTxts - - Alloc memory for the char array representation of the TXT items. - -*/ -char* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocTxts(size_t p_stLength) -{ - - releaseTxts(); - if (p_stLength) - { - m_pcTxts = new char[p_stLength]; - } - return m_pcTxts; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseTxts -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseTxts(void) -{ - - if (m_pcTxts) - { - delete[] m_pcTxts; - m_pcTxts = 0; - } - return true; -} - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP4Addresses -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP4Addresses(void) -{ - - while (m_pIP4Addresses) - { - stcIP4Address* pNext = m_pIP4Addresses->m_pNext; - delete m_pIP4Addresses; - m_pIP4Addresses = pNext; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP4Address -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP4Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* p_pIP4Address) -{ - - bool bResult = false; - - if (p_pIP4Address) - { - p_pIP4Address->m_pNext = m_pIP4Addresses; - m_pIP4Addresses = p_pIP4Address; - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP4Address -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP4Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* p_pIP4Address) -{ - - bool bResult = false; - - if (p_pIP4Address) - { - stcIP4Address* pPred = m_pIP4Addresses; - while ((pPred) && - (pPred->m_pNext != p_pIP4Address)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pIP4Address->m_pNext; - delete p_pIP4Address; - bResult = true; - } - else if (m_pIP4Addresses == p_pIP4Address) // No predecesor, but first item - { - m_pIP4Addresses = p_pIP4Address->m_pNext; - delete p_pIP4Address; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address (const) -*/ -const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address(const IPAddress& p_IPAddress) const -{ - - return (stcIP4Address*)(((const stcAnswer*)this)->findIP4Address(p_IPAddress)); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address(const IPAddress& p_IPAddress) -{ - - stcIP4Address* pIP4Address = m_pIP4Addresses; - while (pIP4Address) - { - if (pIP4Address->m_IPAddress == p_IPAddress) - { - break; - } - pIP4Address = pIP4Address->m_pNext; - } - return pIP4Address; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressCount -*/ -uint32_t MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressCount(void) const -{ - - uint32_t u32Count = 0; - - stcIP4Address* pIP4Address = m_pIP4Addresses; - while (pIP4Address) - { - ++u32Count; - pIP4Address = pIP4Address->m_pNext; - } - return u32Count; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex(uint32_t p_u32Index) -{ - - return (stcIP4Address*)(((const stcAnswer*)this)->IP4AddressAtIndex(p_u32Index)); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex (const) -*/ -const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex(uint32_t p_u32Index) const -{ - - const stcIP4Address* pIP4Address = 0; - - if (((uint32_t)(-1) != p_u32Index) && - (m_pIP4Addresses)) - { - - uint32_t u32Index; - for (pIP4Address = m_pIP4Addresses, u32Index = 0; ((pIP4Address) && (u32Index < p_u32Index)); pIP4Address = pIP4Address->m_pNext, ++u32Index); - } - return pIP4Address; -} -#endif - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP6Addresses -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP6Addresses(void) -{ - - while (m_pIP6Addresses) - { - stcIP6Address* pNext = m_pIP6Addresses->m_pNext; - delete m_pIP6Addresses; - m_pIP6Addresses = pNext; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP6Address -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP6Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* p_pIP6Address) -{ - - bool bResult = false; - - if (p_pIP6Address) - { - p_pIP6Address->m_pNext = m_pIP6Addresses; - m_pIP6Addresses = p_pIP6Address; - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP6Address -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP6Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* p_pIP6Address) -{ - - bool bResult = false; - - if (p_pIP6Address) - { - stcIP6Address* pPred = m_pIP6Addresses; - while ((pPred) && - (pPred->m_pNext != p_pIP6Address)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pIP6Address->m_pNext; - delete p_pIP6Address; - bResult = true; - } - else if (m_pIP6Addresses == p_pIP6Address) // No predecesor, but first item - { - m_pIP6Addresses = p_pIP6Address->m_pNext; - delete p_pIP6Address; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address(const IP6Address& p_IPAddress) -{ - - return (stcIP6Address*)(((const stcAnswer*)this)->findIP6Address(p_IPAddress)); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address (const) -*/ -const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address(const IPAddress& p_IPAddress) const -{ - - const stcIP6Address* pIP6Address = m_pIP6Addresses; - while (pIP6Address) - { - if (p_IP6Address->m_IPAddress == p_IPAddress) - { - break; - } - pIP6Address = pIP6Address->m_pNext; - } - return pIP6Address; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressCount -*/ -uint32_t MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressCount(void) const -{ - - uint32_t u32Count = 0; - - stcIP6Address* pIP6Address = m_pIP6Addresses; - while (pIP6Address) - { - ++u32Count; - pIP6Address = pIP6Address->m_pNext; - } - return u32Count; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex (const) -*/ -const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex(uint32_t p_u32Index) const -{ - - return (stcIP6Address*)(((const stcAnswer*)this)->IP6AddressAtIndex(p_u32Index)); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex(uint32_t p_u32Index) -{ - - stcIP6Address* pIP6Address = 0; - - if (((uint32_t)(-1) != p_u32Index) && - (m_pIP6Addresses)) - { - - uint32_t u32Index; - for (pIP6Address = m_pIP6Addresses, u32Index = 0; ((pIP6Address) && (u32Index < p_u32Index)); pIP6Address = pIP6Address->m_pNext, ++u32Index); - } - return pIP6Address; -} -#endif - - -/** - MDNSResponder::stcMDNSServiceQuery - - A service query object. - A static query is flaged via 'm_bLegacyQuery'; while the function 'queryService' - is waiting for answers, the internal flag 'm_bAwaitingAnswers' is set. When the - timeout is reached, the flag is removed. These two flags are only used for static - service queries. - All answers to the service query are stored in 'm_pAnswers' list. - Individual answers may be addressed by index (in the list of answers). - Every time a answer component is added (or changes) in a dynamic service query, - the callback 'm_fnCallback' is called. - The answer list may be searched by service and host domain. - - Service query object may be connected to a linked list. -*/ - -/* - MDNSResponder::stcMDNSServiceQuery::stcMDNSServiceQuery constructor -*/ -MDNSResponder::stcMDNSServiceQuery::stcMDNSServiceQuery(void) - : m_pNext(0), - m_fnCallback(0), - m_bLegacyQuery(false), - m_u8SentCount(0), - m_ResendTimeout(esp8266::polledTimeout::oneShotMs::neverExpires), - m_bAwaitingAnswers(true), - m_pAnswers(0) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSServiceQuery::~stcMDNSServiceQuery destructor -*/ -MDNSResponder::stcMDNSServiceQuery::~stcMDNSServiceQuery(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSServiceQuery::clear -*/ -bool MDNSResponder::stcMDNSServiceQuery::clear(void) -{ - - m_fnCallback = 0; - m_bLegacyQuery = false; - m_u8SentCount = 0; - m_ResendTimeout.resetToNeverExpires(); - m_bAwaitingAnswers = true; - while (m_pAnswers) - { - stcAnswer* pNext = m_pAnswers->m_pNext; - delete m_pAnswers; - m_pAnswers = pNext; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::answerCount -*/ -uint32_t MDNSResponder::stcMDNSServiceQuery::answerCount(void) const -{ - - uint32_t u32Count = 0; - - stcAnswer* pAnswer = m_pAnswers; - while (pAnswer) - { - ++u32Count; - pAnswer = pAnswer->m_pNext; - } - return u32Count; -} - -/* - MDNSResponder::stcMDNSServiceQuery::answerAtIndex -*/ -const MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::answerAtIndex(uint32_t p_u32Index) const -{ - - const stcAnswer* pAnswer = 0; - - if (((uint32_t)(-1) != p_u32Index) && - (m_pAnswers)) - { - - uint32_t u32Index; - for (pAnswer = m_pAnswers, u32Index = 0; ((pAnswer) && (u32Index < p_u32Index)); pAnswer = pAnswer->m_pNext, ++u32Index); - } - return pAnswer; -} - -/* - MDNSResponder::stcMDNSServiceQuery::answerAtIndex -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::answerAtIndex(uint32_t p_u32Index) -{ - - return (stcAnswer*)(((const stcMDNSServiceQuery*)this)->answerAtIndex(p_u32Index)); -} - -/* - MDNSResponder::stcMDNSServiceQuery::indexOfAnswer -*/ -uint32_t MDNSResponder::stcMDNSServiceQuery::indexOfAnswer(const MDNSResponder::stcMDNSServiceQuery::stcAnswer* p_pAnswer) const -{ - - uint32_t u32Index = 0; - - for (const stcAnswer* pAnswer = m_pAnswers; pAnswer; pAnswer = pAnswer->m_pNext, ++u32Index) - { - if (pAnswer == p_pAnswer) - { - return u32Index; - } - } - return ((uint32_t)(-1)); -} - -/* - MDNSResponder::stcMDNSServiceQuery::addAnswer -*/ -bool MDNSResponder::stcMDNSServiceQuery::addAnswer(MDNSResponder::stcMDNSServiceQuery::stcAnswer* p_pAnswer) -{ - - bool bResult = false; - - if (p_pAnswer) - { - p_pAnswer->m_pNext = m_pAnswers; - m_pAnswers = p_pAnswer; - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::removeAnswer -*/ -bool MDNSResponder::stcMDNSServiceQuery::removeAnswer(MDNSResponder::stcMDNSServiceQuery::stcAnswer* p_pAnswer) -{ - - bool bResult = false; - - if (p_pAnswer) - { - stcAnswer* pPred = m_pAnswers; - while ((pPred) && - (pPred->m_pNext != p_pAnswer)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pAnswer->m_pNext; - delete p_pAnswer; - bResult = true; - } - else if (m_pAnswers == p_pAnswer) // No predecesor, but first item - { - m_pAnswers = p_pAnswer->m_pNext; - delete p_pAnswer; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::findAnswerForServiceDomain -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::findAnswerForServiceDomain(const MDNSResponder::stcMDNS_RRDomain& p_ServiceDomain) -{ - - stcAnswer* pAnswer = m_pAnswers; - while (pAnswer) - { - if (pAnswer->m_ServiceDomain == p_ServiceDomain) - { - break; - } - pAnswer = pAnswer->m_pNext; - } - return pAnswer; -} - -/* - MDNSResponder::stcMDNSServiceQuery::findAnswerForHostDomain -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::findAnswerForHostDomain(const MDNSResponder::stcMDNS_RRDomain& p_HostDomain) -{ - - stcAnswer* pAnswer = m_pAnswers; - while (pAnswer) - { - if (pAnswer->m_HostDomain == p_HostDomain) - { - break; - } - pAnswer = pAnswer->m_pNext; - } - return pAnswer; -} - - -/** - MDNSResponder::stcMDNSSendParameter - - A 'collection' of properties and flags for one MDNS query or response. - Mainly managed by the 'Control' functions. - The current offset in the UPD output buffer is tracked to be able to do - a simple host or service domain compression. - -*/ - -/** - MDNSResponder::stcMDNSSendParameter::stcDomainCacheItem - - A cached host or service domain, incl. the offset in the UDP output buffer. - -*/ - -/* - MDNSResponder::stcMDNSSendParameter::stcDomainCacheItem::stcDomainCacheItem constructor -*/ -MDNSResponder::stcMDNSSendParameter::stcDomainCacheItem::stcDomainCacheItem(const void* p_pHostnameOrService, - bool p_bAdditionalData, - uint32_t p_u16Offset) - : m_pNext(0), - m_pHostnameOrService(p_pHostnameOrService), - m_bAdditionalData(p_bAdditionalData), - m_u16Offset(p_u16Offset) -{ - -} - -/** - MDNSResponder::stcMDNSSendParameter -*/ - -/* - MDNSResponder::stcMDNSSendParameter::stcMDNSSendParameter constructor -*/ -MDNSResponder::stcMDNSSendParameter::stcMDNSSendParameter(void) - : m_pQuestions(0), - m_pDomainCacheItems(0) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSSendParameter::~stcMDNSSendParameter destructor -*/ -MDNSResponder::stcMDNSSendParameter::~stcMDNSSendParameter(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSSendParameter::clear -*/ -bool MDNSResponder::stcMDNSSendParameter::clear(void) -{ - - m_u16ID = 0; - m_u8HostReplyMask = 0; - m_u16Offset = 0; - - m_bLegacyQuery = false; - m_bResponse = false; - m_bAuthorative = false; - m_bUnicast = false; - m_bUnannounce = false; - - m_bCacheFlush = true; - - while (m_pQuestions) - { - stcMDNS_RRQuestion* pNext = m_pQuestions->m_pNext; - delete m_pQuestions; - m_pQuestions = pNext; - } - while (m_pDomainCacheItems) - { - stcDomainCacheItem* pNext = m_pDomainCacheItems->m_pNext; - delete m_pDomainCacheItems; - m_pDomainCacheItems = pNext; - } - return true; -} - -/* - MDNSResponder::stcMDNSSendParameter::shiftOffset -*/ -bool MDNSResponder::stcMDNSSendParameter::shiftOffset(uint16_t p_u16Shift) -{ - - m_u16Offset += p_u16Shift; - return true; -} - -/* - MDNSResponder::stcMDNSSendParameter::addDomainCacheItem -*/ -bool MDNSResponder::stcMDNSSendParameter::addDomainCacheItem(const void* p_pHostnameOrService, - bool p_bAdditionalData, - uint16_t p_u16Offset) -{ - - bool bResult = false; - - stcDomainCacheItem* pNewItem = 0; - if ((p_pHostnameOrService) && - (p_u16Offset) && - ((pNewItem = new stcDomainCacheItem(p_pHostnameOrService, p_bAdditionalData, p_u16Offset)))) - { - - pNewItem->m_pNext = m_pDomainCacheItems; - bResult = ((m_pDomainCacheItems = pNewItem)); - } - return bResult; -} - -/* - MDNSResponder::stcMDNSSendParameter::findCachedDomainOffset -*/ -uint16_t MDNSResponder::stcMDNSSendParameter::findCachedDomainOffset(const void* p_pHostnameOrService, - bool p_bAdditionalData) const -{ - - const stcDomainCacheItem* pCacheItem = m_pDomainCacheItems; - - for (; pCacheItem; pCacheItem = pCacheItem->m_pNext) - { - if ((pCacheItem->m_pHostnameOrService == p_pHostnameOrService) && - (pCacheItem->m_bAdditionalData == p_bAdditionalData)) // Found cache item - { - break; - } - } - return (pCacheItem ? pCacheItem->m_u16Offset : 0); -} - -} // namespace MDNSImplementation - -} // namespace esp8266 - - - diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Transfer.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Transfer.cpp deleted file mode 100644 index 7400abec42..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Transfer.cpp +++ /dev/null @@ -1,1779 +0,0 @@ -/* - LEAmDNS_Transfer.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -extern "C" { -#include "user_interface.h" -} - -#include "LEAmDNS_lwIPdefs.h" -#include "LEAmDNS_Priv.h" - - -namespace esp8266 -{ - -/* - LEAmDNS -*/ -namespace MDNSImplementation -{ - -/** - CONST STRINGS -*/ -static const char* scpcLocal = "local"; -static const char* scpcServices = "services"; -static const char* scpcDNSSD = "dns-sd"; -static const char* scpcUDP = "udp"; -//static const char* scpcTCP = "tcp"; - -#ifdef MDNS_IP4_SUPPORT -static const char* scpcReverseIP4Domain = "in-addr"; -#endif -#ifdef MDNS_IP6_SUPPORT -static const char* scpcReverseIP6Domain = "ip6"; -#endif -static const char* scpcReverseTopDomain = "arpa"; - -/** - TRANSFER -*/ - - -/** - SENDING -*/ - -/* - MDNSResponder::_sendMDNSMessage - - Unicast responses are prepared and sent directly to the querier. - Multicast responses or queries are transferred to _sendMDNSMessage_Multicast - - Any reply flags in installed services are removed at the end! - -*/ -bool MDNSResponder::_sendMDNSMessage(MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - bool bResult = true; - - if (p_rSendParameter.m_bResponse && - p_rSendParameter.m_bUnicast) // Unicast response -> Send to querier - { - DEBUG_EX_ERR(if (!m_pUDPContext->getRemoteAddress()) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage: MISSING remote address for response!\n")); - }); - IPAddress ipRemote; - ipRemote = m_pUDPContext->getRemoteAddress(); - bResult = ((_prepareMDNSMessage(p_rSendParameter, _getResponseMulticastInterface())) && - (m_pUDPContext->send(ipRemote, m_pUDPContext->getRemotePort()))); - } - else // Multicast response - { - bResult = _sendMDNSMessage_Multicast(p_rSendParameter); - } - - // Finally clear service reply masks - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - pService->m_u8ReplyMask = 0; - } - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_sendMDNSMessage_Multicast - - Fills the UDP output buffer (via _prepareMDNSMessage) and sends the buffer - via the selected WiFi interface (Station or AP) -*/ -bool MDNSResponder::_sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - bool bResult = false; - - IPAddress fromIPAddress; - fromIPAddress = _getResponseMulticastInterface(); - m_pUDPContext->setMulticastInterface(fromIPAddress); - -#ifdef MDNS_IP4_SUPPORT - IPAddress toMulticastAddress(DNS_MQUERY_IPV4_GROUP_INIT); -#endif -#ifdef MDNS_IP6_SUPPORT - //TODO: set multicast address - IPAddress toMulticastAddress(DNS_MQUERY_IPV6_GROUP_INIT); -#endif - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage_Multicast: Will send to '%s'.\n"), toMulticastAddress.toString().c_str());); - bResult = ((_prepareMDNSMessage(p_rSendParameter, fromIPAddress)) && - (m_pUDPContext->send(toMulticastAddress, DNS_MQUERY_PORT))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage_Multicast: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_prepareMDNSMessage - - The MDNS message is composed in a two-step process. - In the first loop 'only' the header informations (mainly number of answers) are collected, - while in the seconds loop, the header and all queries and answers are written to the UDP - output buffer. - -*/ -bool MDNSResponder::_prepareMDNSMessage(MDNSResponder::stcMDNSSendParameter& p_rSendParameter, - IPAddress p_IPAddress) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage\n"));); - bool bResult = true; - - // Prepare header; count answers - stcMDNS_MsgHeader msgHeader(p_rSendParameter.m_u16ID, p_rSendParameter.m_bResponse, 0, p_rSendParameter.m_bAuthorative); - // If this is a response, the answers are anwers, - // else this is a query or probe and the answers go into auth section - uint16_t& ru16Answers = (p_rSendParameter.m_bResponse - ? msgHeader.m_u16ANCount - : msgHeader.m_u16NSCount); - - /** - enuSequence - */ - enum enuSequence - { - Sequence_Count = 0, - Sequence_Send = 1 - }; - - // Two step sequence: 'Count' and 'Send' - for (uint32_t sequence = Sequence_Count; ((bResult) && (sequence <= Sequence_Send)); ++sequence) - { - DEBUG_EX_INFO( - if (Sequence_Send == sequence) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), - (unsigned)msgHeader.m_u16ID, - (unsigned)msgHeader.m_1bQR, (unsigned)msgHeader.m_4bOpcode, (unsigned)msgHeader.m_1bAA, (unsigned)msgHeader.m_1bTC, (unsigned)msgHeader.m_1bRD, - (unsigned)msgHeader.m_1bRA, (unsigned)msgHeader.m_4bRCode, - (unsigned)msgHeader.m_u16QDCount, - (unsigned)msgHeader.m_u16ANCount, - (unsigned)msgHeader.m_u16NSCount, - (unsigned)msgHeader.m_u16ARCount); - } - ); - // Count/send - // Header - bResult = ((Sequence_Count == sequence) - ? true - : _writeMDNSMsgHeader(msgHeader, p_rSendParameter)); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSMsgHeader FAILED!\n"));); - // Questions - for (stcMDNS_RRQuestion* pQuestion = p_rSendParameter.m_pQuestions; ((bResult) && (pQuestion)); pQuestion = pQuestion->m_pNext) - { - ((Sequence_Count == sequence) - ? ++msgHeader.m_u16QDCount - : (bResult = _writeMDNSQuestion(*pQuestion, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSQuestion FAILED!\n"));); - } - - // Answers and authorative answers -#ifdef MDNS_IP4_SUPPORT - if ((bResult) && - (p_rSendParameter.m_u8HostReplyMask & ContentFlag_A)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_A(p_IPAddress, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_A(A) FAILED!\n"));); - } - if ((bResult) && - (p_rSendParameter.m_u8HostReplyMask & ContentFlag_PTR_IP4)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_PTR_IP4(p_IPAddress, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_PTR_IP4 FAILED!\n"));); - } -#endif -#ifdef MDNS_IP6_SUPPORT - if ((bResult) && - (p_rSendParameter.m_u8HostReplyMask & ContentFlag_AAAA)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_AAAA(p_IPAddress, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_AAAA(A) FAILED!\n"));); - } - if ((bResult) && - (p_rSendParameter.m_u8HostReplyMask & ContentFlag_PTR_IP6)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_PTR_IP6(p_IPAddress, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_PTR_IP6 FAILED!\n"));); - } -#endif - - for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) - { - if ((bResult) && - (pService->m_u8ReplyMask & ContentFlag_PTR_TYPE)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_PTR_TYPE(*pService, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_PTR_TYPE FAILED!\n"));); - } - if ((bResult) && - (pService->m_u8ReplyMask & ContentFlag_PTR_NAME)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_PTR_NAME(*pService, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_PTR_NAME FAILED!\n"));); - } - if ((bResult) && - (pService->m_u8ReplyMask & ContentFlag_SRV)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_SRV(*pService, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_SRV(A) FAILED!\n"));); - } - if ((bResult) && - (pService->m_u8ReplyMask & ContentFlag_TXT)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_TXT(*pService, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_TXT(A) FAILED!\n"));); - } - } // for services - - // Additional answers -#ifdef MDNS_IP4_SUPPORT - bool bNeedsAdditionalAnswerA = false; -#endif -#ifdef MDNS_IP6_SUPPORT - bool bNeedsAdditionalAnswerAAAA = false; -#endif - for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) - { - if ((bResult) && - (pService->m_u8ReplyMask & ContentFlag_PTR_NAME) && // If PTR_NAME is requested, AND - (!(pService->m_u8ReplyMask & ContentFlag_SRV))) // NOT SRV -> add SRV as additional answer - { - ((Sequence_Count == sequence) - ? ++msgHeader.m_u16ARCount - : (bResult = _writeMDNSAnswer_SRV(*pService, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_SRV(B) FAILED!\n"));); - } - if ((bResult) && - (pService->m_u8ReplyMask & ContentFlag_PTR_NAME) && // If PTR_NAME is requested, AND - (!(pService->m_u8ReplyMask & ContentFlag_TXT))) // NOT TXT -> add TXT as additional answer - { - ((Sequence_Count == sequence) - ? ++msgHeader.m_u16ARCount - : (bResult = _writeMDNSAnswer_TXT(*pService, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_TXT(B) FAILED!\n"));); - } - if ((pService->m_u8ReplyMask & (ContentFlag_PTR_NAME | ContentFlag_SRV)) || // If service instance name or SRV OR - (p_rSendParameter.m_u8HostReplyMask & (ContentFlag_A | ContentFlag_AAAA))) // any host IP address is requested - { -#ifdef MDNS_IP4_SUPPORT - if ((bResult) && - (!(p_rSendParameter.m_u8HostReplyMask & ContentFlag_A))) // Add IP4 address - { - bNeedsAdditionalAnswerA = true; - } -#endif -#ifdef MDNS_IP6_SUPPORT - if ((bResult) && - (!(p_rSendParameter.m_u8HostReplyMask & ContentFlag_AAAA))) // Add IP6 address - { - bNeedsAdditionalAnswerAAAA = true; - } -#endif - } - } // for services - - // Answer A needed? -#ifdef MDNS_IP4_SUPPORT - if ((bResult) && - (bNeedsAdditionalAnswerA)) - { - ((Sequence_Count == sequence) - ? ++msgHeader.m_u16ARCount - : (bResult = _writeMDNSAnswer_A(p_IPAddress, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_A(B) FAILED!\n"));); - } -#endif -#ifdef MDNS_IP6_SUPPORT - // Answer AAAA needed? - if ((bResult) && - (bNeedsAdditionalAnswerAAAA)) - { - ((Sequence_Count == sequence) - ? ++msgHeader.m_u16ARCount - : (bResult = _writeMDNSAnswer_AAAA(p_IPAddress, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_AAAA(B) FAILED!\n"));); - } -#endif - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: Loop %i FAILED!\n"), sequence);); - } // for sequence - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_sendMDNSServiceQuery - - Creates and sends a PTR query for the given service domain. - -*/ -bool MDNSResponder::_sendMDNSServiceQuery(const MDNSResponder::stcMDNSServiceQuery& p_ServiceQuery) -{ - - return _sendMDNSQuery(p_ServiceQuery.m_ServiceTypeDomain, DNS_RRTYPE_PTR); -} - -/* - MDNSResponder::_sendMDNSQuery - - Creates and sends a query for the given domain and query type. - -*/ -bool MDNSResponder::_sendMDNSQuery(const MDNSResponder::stcMDNS_RRDomain& p_QueryDomain, - uint16_t p_u16QueryType, - stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers /*= 0*/) -{ - - bool bResult = false; - - stcMDNSSendParameter sendParameter; - if (0 != ((sendParameter.m_pQuestions = new stcMDNS_RRQuestion))) - { - sendParameter.m_pQuestions->m_Header.m_Domain = p_QueryDomain; - - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = p_u16QueryType; - // It seems, that some mDNS implementations don't support 'unicast response' questions... - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (/*0x8000 |*/ DNS_RRCLASS_IN); // /*Unicast &*/ INternet - - // TODO: Add knwon answer to the query - (void)p_pKnownAnswers; - - bResult = _sendMDNSMessage(sendParameter); - } // else: FAILED to alloc question - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSQuery: FAILED to alloc question!\n"));); - return bResult; -} - -/** - HELPERS -*/ - -/** - RESOURCE RECORDS -*/ - -/* - MDNSResponder::_readRRQuestion - - Reads a question (eg. MyESP._http._tcp.local ANY IN) from the UPD input buffer. - -*/ -bool MDNSResponder::_readRRQuestion(MDNSResponder::stcMDNS_RRQuestion& p_rRRQuestion) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRQuestion\n"));); - - bool bResult = false; - - if ((bResult = _readRRHeader(p_rRRQuestion.m_Header))) - { - // Extract unicast flag from class field - p_rRRQuestion.m_bUnicast = (p_rRRQuestion.m_Header.m_Attributes.m_u16Class & 0x8000); - p_rRRQuestion.m_Header.m_Attributes.m_u16Class &= (~0x8000); - - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRQuestion ")); - _printRRDomain(p_rRRQuestion.m_Header.m_Domain); - DEBUG_OUTPUT.printf_P(PSTR(" Type:0x%04X Class:0x%04X %s\n"), (unsigned)p_rRRQuestion.m_Header.m_Attributes.m_u16Type, (unsigned)p_rRRQuestion.m_Header.m_Attributes.m_u16Class, (p_rRRQuestion.m_bUnicast ? "Unicast" : "Multicast")); - ); - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRQuestion: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_readRRAnswer - - Reads an answer (eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local) - from the UDP input buffer. - After reading the domain and type info, the further processing of the answer - is transferred the answer specific reading functions. - Unknown answer types are processed by the generic answer reader (to remove them - from the input buffer). - -*/ -bool MDNSResponder::_readRRAnswer(MDNSResponder::stcMDNS_RRAnswer*& p_rpRRAnswer) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer\n"));); - - bool bResult = false; - - stcMDNS_RRHeader header; - uint32_t u32TTL; - uint16_t u16RDLength; - if ((_readRRHeader(header)) && - (_udpRead32(u32TTL)) && - (_udpRead16(u16RDLength))) - { - - /* DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer: Reading 0x%04X answer (class:0x%04X, TTL:%u, RDLength:%u) for "), header.m_Attributes.m_u16Type, header.m_Attributes.m_u16Class, u32TTL, u16RDLength); - _printRRDomain(header.m_Domain); - DEBUG_OUTPUT.printf_P(PSTR("\n")); - );*/ - - switch (header.m_Attributes.m_u16Type & (~0x8000)) // Topmost bit might carry 'cache flush' flag - { -#ifdef MDNS_IP4_SUPPORT - case DNS_RRTYPE_A: - p_rpRRAnswer = new stcMDNS_RRAnswerA(header, u32TTL); - bResult = _readRRAnswerA(*(stcMDNS_RRAnswerA*&)p_rpRRAnswer, u16RDLength); - break; -#endif - case DNS_RRTYPE_PTR: - p_rpRRAnswer = new stcMDNS_RRAnswerPTR(header, u32TTL); - bResult = _readRRAnswerPTR(*(stcMDNS_RRAnswerPTR*&)p_rpRRAnswer, u16RDLength); - break; - case DNS_RRTYPE_TXT: - p_rpRRAnswer = new stcMDNS_RRAnswerTXT(header, u32TTL); - bResult = _readRRAnswerTXT(*(stcMDNS_RRAnswerTXT*&)p_rpRRAnswer, u16RDLength); - break; -#ifdef MDNS_IP6_SUPPORT - case DNS_RRTYPE_AAAA: - p_rpRRAnswer = new stcMDNS_RRAnswerAAAA(header, u32TTL); - bResult = _readRRAnswerAAAA(*(stcMDNS_RRAnswerAAAA*&)p_rpRRAnswer, u16RDLength); - break; -#endif - case DNS_RRTYPE_SRV: - p_rpRRAnswer = new stcMDNS_RRAnswerSRV(header, u32TTL); - bResult = _readRRAnswerSRV(*(stcMDNS_RRAnswerSRV*&)p_rpRRAnswer, u16RDLength); - break; - default: - p_rpRRAnswer = new stcMDNS_RRAnswerGeneric(header, u32TTL); - bResult = _readRRAnswerGeneric(*(stcMDNS_RRAnswerGeneric*&)p_rpRRAnswer, u16RDLength); - break; - } - DEBUG_EX_INFO( - if ((bResult) && - (p_rpRRAnswer)) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer: ")); - _printRRDomain(p_rpRRAnswer->m_Header.m_Domain); - DEBUG_OUTPUT.printf_P(PSTR(" Type:0x%04X Class:0x%04X TTL:%u, RDLength:%u "), p_rpRRAnswer->m_Header.m_Attributes.m_u16Type, p_rpRRAnswer->m_Header.m_Attributes.m_u16Class, p_rpRRAnswer->m_u32TTL, u16RDLength); - switch (header.m_Attributes.m_u16Type & (~0x8000)) // Topmost bit might carry 'cache flush' flag - { -#ifdef MDNS_IP4_SUPPORT - case DNS_RRTYPE_A: - DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((stcMDNS_RRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); - break; -#endif - case DNS_RRTYPE_PTR: - DEBUG_OUTPUT.printf_P(PSTR("PTR ")); - _printRRDomain(((stcMDNS_RRAnswerPTR*&)p_rpRRAnswer)->m_PTRDomain); - break; - case DNS_RRTYPE_TXT: - { - size_t stTxtLength = ((stcMDNS_RRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_strLength(); - char* pTxts = new char[stTxtLength]; - if (pTxts) - { - ((stcMDNS_RRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_str(pTxts); - DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts); - delete[] pTxts; - } - break; - } -#ifdef MDNS_IP6_SUPPORT - case DNS_RRTYPE_AAAA: - DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((stcMDNS_RRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); - break; -#endif - case DNS_RRTYPE_SRV: - DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((stcMDNS_RRAnswerSRV*&)p_rpRRAnswer)->m_u16Port); - _printRRDomain(((stcMDNS_RRAnswerSRV*&)p_rpRRAnswer)->m_SRVDomain); - break; - default: - DEBUG_OUTPUT.printf_P(PSTR("generic ")); - break; - } - DEBUG_OUTPUT.printf_P(PSTR("\n")); - } - else - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer: FAILED to read specific answer of type 0x%04X!\n"), p_rpRRAnswer->m_Header.m_Attributes.m_u16Type); - } - ); // DEBUG_EX_INFO - } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer: FAILED!\n"));); - return bResult; -} - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::_readRRAnswerA -*/ -bool MDNSResponder::_readRRAnswerA(MDNSResponder::stcMDNS_RRAnswerA& p_rRRAnswerA, - uint16_t p_u16RDLength) -{ - - uint32_t u32IP4Address; - bool bResult = ((MDNS_IP4_SIZE == p_u16RDLength) && - (_udpReadBuffer((unsigned char*)&u32IP4Address, MDNS_IP4_SIZE)) && - ((p_rRRAnswerA.m_IPAddress = IPAddress(u32IP4Address)))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerA: FAILED!\n"));); - return bResult; -} -#endif - -/* - MDNSResponder::_readRRAnswerPTR -*/ -bool MDNSResponder::_readRRAnswerPTR(MDNSResponder::stcMDNS_RRAnswerPTR& p_rRRAnswerPTR, - uint16_t p_u16RDLength) -{ - - bool bResult = ((p_u16RDLength) && - (_readRRDomain(p_rRRAnswerPTR.m_PTRDomain))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerPTR: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_readRRAnswerTXT - - Read TXT items from a buffer like 4c#=15ff=20 -*/ -bool MDNSResponder::_readRRAnswerTXT(MDNSResponder::stcMDNS_RRAnswerTXT& p_rRRAnswerTXT, - uint16_t p_u16RDLength) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: RDLength:%u\n"), p_u16RDLength);); - bool bResult = true; - - p_rRRAnswerTXT.clear(); - if (p_u16RDLength) - { - bResult = false; - - unsigned char* pucBuffer = new unsigned char[p_u16RDLength]; - if (pucBuffer) - { - if (_udpReadBuffer(pucBuffer, p_u16RDLength)) - { - bResult = true; - - const unsigned char* pucCursor = pucBuffer; - while ((pucCursor < (pucBuffer + p_u16RDLength)) && - (bResult)) - { - bResult = false; - - stcMDNSServiceTxt* pTxt = 0; - unsigned char ucLength = *pucCursor++; // Length of the next txt item - if (ucLength) - { - DEBUG_EX_INFO( - static char sacBuffer[64]; *sacBuffer = 0; - uint8_t u8MaxLength = ((ucLength > (sizeof(sacBuffer) - 1)) ? (sizeof(sacBuffer) - 1) : ucLength); - os_strncpy(sacBuffer, (const char*)pucCursor, u8MaxLength); sacBuffer[u8MaxLength] = 0; - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: Item(%u): %s\n"), ucLength, sacBuffer); - ); - - unsigned char* pucEqualSign = (unsigned char*)os_strchr((const char*)pucCursor, '='); // Position of the '=' sign - unsigned char ucKeyLength; - if ((pucEqualSign) && - ((ucKeyLength = (pucEqualSign - pucCursor)))) - { - unsigned char ucValueLength = (ucLength - (pucEqualSign - pucCursor + 1)); - bResult = (((pTxt = new stcMDNSServiceTxt)) && - (pTxt->setKey((const char*)pucCursor, ucKeyLength)) && - (pTxt->setValue((const char*)(pucEqualSign + 1), ucValueLength))); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: INVALID TXT format (No '=')!\n"));); - } - pucCursor += ucLength; - } - else // no/zero length TXT - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: TXT answer contains no items.\n"));); - bResult = true; - } - - if ((bResult) && - (pTxt)) // Everythings fine so far - { - // Link TXT item to answer TXTs - pTxt->m_pNext = p_rRRAnswerTXT.m_Txts.m_pTxts; - p_rRRAnswerTXT.m_Txts.m_pTxts = pTxt; - } - else // At least no TXT (migth be OK, if length was 0) OR an error - { - if (!bResult) - { - DEBUG_EX_ERR( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: FAILED to read TXT item!\n")); - DEBUG_OUTPUT.printf_P(PSTR("RData dump:\n")); - _udpDump((m_pUDPContext->tell() - p_u16RDLength), p_u16RDLength); - DEBUG_OUTPUT.printf_P(PSTR("\n")); - ); - } - if (pTxt) - { - delete pTxt; - pTxt = 0; - } - p_rRRAnswerTXT.clear(); - } - } // while - - DEBUG_EX_ERR( - if (!bResult) // Some failure - { - DEBUG_OUTPUT.printf_P(PSTR("RData dump:\n")); - _udpDump((m_pUDPContext->tell() - p_u16RDLength), p_u16RDLength); - DEBUG_OUTPUT.printf_P(PSTR("\n")); - } - ); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: FAILED to read TXT content!\n"));); - } - // Clean up - delete[] pucBuffer; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: FAILED to alloc buffer for TXT content!\n"));); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: WARNING! No content!\n"));); - } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: FAILED!\n"));); - return bResult; -} - -#ifdef MDNS_IP6_SUPPORT -bool MDNSResponder::_readRRAnswerAAAA(MDNSResponder::stcMDNS_RRAnswerAAAA& p_rRRAnswerAAAA, - uint16_t p_u16RDLength) -{ - bool bResult = false; - // TODO: Implement - return bResult; -} -#endif - -/* - MDNSResponder::_readRRAnswerSRV -*/ -bool MDNSResponder::_readRRAnswerSRV(MDNSResponder::stcMDNS_RRAnswerSRV& p_rRRAnswerSRV, - uint16_t p_u16RDLength) -{ - - bool bResult = (((3 * sizeof(uint16_t)) < p_u16RDLength) && - (_udpRead16(p_rRRAnswerSRV.m_u16Priority)) && - (_udpRead16(p_rRRAnswerSRV.m_u16Weight)) && - (_udpRead16(p_rRRAnswerSRV.m_u16Port)) && - (_readRRDomain(p_rRRAnswerSRV.m_SRVDomain))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerSRV: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_readRRAnswerGeneric -*/ -bool MDNSResponder::_readRRAnswerGeneric(MDNSResponder::stcMDNS_RRAnswerGeneric& p_rRRAnswerGeneric, - uint16_t p_u16RDLength) -{ - bool bResult = (0 == p_u16RDLength); - - p_rRRAnswerGeneric.clear(); - if (((p_rRRAnswerGeneric.m_u16RDLength = p_u16RDLength)) && - ((p_rRRAnswerGeneric.m_pu8RDData = new unsigned char[p_rRRAnswerGeneric.m_u16RDLength]))) - { - - bResult = _udpReadBuffer(p_rRRAnswerGeneric.m_pu8RDData, p_rRRAnswerGeneric.m_u16RDLength); - } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerGeneric: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_readRRHeader -*/ -bool MDNSResponder::_readRRHeader(MDNSResponder::stcMDNS_RRHeader& p_rRRHeader) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRHeader\n"));); - - bool bResult = ((_readRRDomain(p_rRRHeader.m_Domain)) && - (_readRRAttributes(p_rRRHeader.m_Attributes))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRHeader: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_readRRDomain - - Reads a (maybe multilevel compressed) domain from the UDP input buffer. - -*/ -bool MDNSResponder::_readRRDomain(MDNSResponder::stcMDNS_RRDomain& p_rRRDomain) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain\n"));); - - bool bResult = ((p_rRRDomain.clear()) && - (_readRRDomain_Loop(p_rRRDomain, 0))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_readRRDomain_Loop - - Reads a domain from the UDP input buffer. For every compression level, the functions - calls itself recursively. To avoid endless recursion because of malformed MDNS records, - the maximum recursion depth is set by MDNS_DOMAIN_MAX_REDIRCTION. - -*/ -bool MDNSResponder::_readRRDomain_Loop(MDNSResponder::stcMDNS_RRDomain& p_rRRDomain, - uint8_t p_u8Depth) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u)\n"), p_u8Depth);); - - bool bResult = false; - - if (MDNS_DOMAIN_MAX_REDIRCTION >= p_u8Depth) - { - bResult = true; - - uint8_t u8Len = 0; - do - { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): Offset:%u p0:%02x\n"), p_u8Depth, m_pUDPContext->tell(), m_pUDPContext->peek());); - _udpRead8(u8Len); - - if (u8Len & MDNS_DOMAIN_COMPRESS_MARK) - { - // Compressed label(s) - uint16_t u16Offset = ((u8Len & ~MDNS_DOMAIN_COMPRESS_MARK) << 8); // Implicit BE to LE conversion! - _udpRead8(u8Len); - u16Offset |= u8Len; - - if (m_pUDPContext->isValidOffset(u16Offset)) - { - size_t stCurrentPosition = m_pUDPContext->tell(); // Prepare return from recursion - - //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): Redirecting from %u to %u!\n"), p_u8Depth, stCurrentPosition, u16Offset);); - m_pUDPContext->seek(u16Offset); - if (_readRRDomain_Loop(p_rRRDomain, p_u8Depth + 1)) // Do recursion - { - //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): Succeeded to read redirected label! Returning to %u\n"), p_u8Depth, stCurrentPosition);); - m_pUDPContext->seek(stCurrentPosition); // Restore after recursion - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): FAILED to read redirected label!\n"), p_u8Depth);); - bResult = false; - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): INVALID offset in redirection!\n"), p_u8Depth);); - bResult = false; - } - break; - } - else - { - // Normal (uncompressed) label (maybe '\0' only) - if (MDNS_DOMAIN_MAXLENGTH > (p_rRRDomain.m_u16NameLength + u8Len)) - { - // Add length byte - p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength] = u8Len; - ++(p_rRRDomain.m_u16NameLength); - if (u8Len) // Add name - { - if ((bResult = _udpReadBuffer((unsigned char*) & (p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength]), u8Len))) - { - /* DEBUG_EX_INFO( - p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength + u8Len] = 0; // Closing '\0' for printing - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): Domain label (%u): %s\n"), p_u8Depth, (unsigned)(p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength - 1]), &(p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength])); - );*/ - - p_rRRDomain.m_u16NameLength += u8Len; - } - } - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(2) offset:%u p0:%x\n"), m_pUDPContext->tell(), m_pUDPContext->peek());); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): ERROR! Domain name too long (%u + %u)!\n"), p_u8Depth, p_rRRDomain.m_u16NameLength, u8Len);); - bResult = false; - break; - } - } - } while ((bResult) && - (0 != u8Len)); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): ERROR! Too many redirections!\n"), p_u8Depth);); - } - return bResult; -} - -/* - MDNSResponder::_readRRAttributes -*/ -bool MDNSResponder::_readRRAttributes(MDNSResponder::stcMDNS_RRAttributes& p_rRRAttributes) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAttributes\n"));); - - bool bResult = ((_udpRead16(p_rRRAttributes.m_u16Type)) && - (_udpRead16(p_rRRAttributes.m_u16Class))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAttributes: FAILED!\n"));); - return bResult; -} - - -/* - DOMAIN NAMES -*/ - -/* - MDNSResponder::_buildDomainForHost - - Builds a MDNS host domain (eg. esp8266.local) for the given hostname. - -*/ -bool MDNSResponder::_buildDomainForHost(const char* p_pcHostname, - MDNSResponder::stcMDNS_RRDomain& p_rHostDomain) const -{ - - p_rHostDomain.clear(); - bool bResult = ((p_pcHostname) && - (*p_pcHostname) && - (p_rHostDomain.addLabel(p_pcHostname)) && - (p_rHostDomain.addLabel(scpcLocal)) && - (p_rHostDomain.addLabel(0))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForHost: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_buildDomainForDNSSD - - Builds the '_services._dns-sd._udp.local' domain. - Used while detecting generic service enum question (DNS-SD) and answering these questions. - -*/ -bool MDNSResponder::_buildDomainForDNSSD(MDNSResponder::stcMDNS_RRDomain& p_rDNSSDDomain) const -{ - - p_rDNSSDDomain.clear(); - bool bResult = ((p_rDNSSDDomain.addLabel(scpcServices, true)) && - (p_rDNSSDDomain.addLabel(scpcDNSSD, true)) && - (p_rDNSSDDomain.addLabel(scpcUDP, true)) && - (p_rDNSSDDomain.addLabel(scpcLocal)) && - (p_rDNSSDDomain.addLabel(0))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForDNSSD: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_buildDomainForService - - Builds the domain for the given service (eg. _http._tcp.local or - MyESP._http._tcp.local (if p_bIncludeName is set)). - -*/ -bool MDNSResponder::_buildDomainForService(const MDNSResponder::stcMDNSService& p_Service, - bool p_bIncludeName, - MDNSResponder::stcMDNS_RRDomain& p_rServiceDomain) const -{ - - p_rServiceDomain.clear(); - bool bResult = (((!p_bIncludeName) || - (p_rServiceDomain.addLabel(p_Service.m_pcName))) && - (p_rServiceDomain.addLabel(p_Service.m_pcService, true)) && - (p_rServiceDomain.addLabel(p_Service.m_pcProtocol, true)) && - (p_rServiceDomain.addLabel(scpcLocal)) && - (p_rServiceDomain.addLabel(0))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForService: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_buildDomainForService - - Builds the domain for the given service properties (eg. _http._tcp.local). - The usual prepended '_' are added, if missing in the input strings. - -*/ -bool MDNSResponder::_buildDomainForService(const char* p_pcService, - const char* p_pcProtocol, - MDNSResponder::stcMDNS_RRDomain& p_rServiceDomain) const -{ - - p_rServiceDomain.clear(); - bool bResult = ((p_pcService) && - (p_pcProtocol) && - (p_rServiceDomain.addLabel(p_pcService, ('_' != *p_pcService))) && - (p_rServiceDomain.addLabel(p_pcProtocol, ('_' != *p_pcProtocol))) && - (p_rServiceDomain.addLabel(scpcLocal)) && - (p_rServiceDomain.addLabel(0))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForService: FAILED for (%s.%s)!\n"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); - return bResult; -} - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::_buildDomainForReverseIP4 - - The IP4 address is stringized by printing the four address bytes into a char buffer in reverse order - and adding 'in-addr.arpa' (eg. 012.789.456.123.in-addr.arpa). - Used while detecting reverse IP4 questions and answering these -*/ -bool MDNSResponder::_buildDomainForReverseIP4(IPAddress p_IP4Address, - MDNSResponder::stcMDNS_RRDomain& p_rReverseIP4Domain) const -{ - - bool bResult = true; - - p_rReverseIP4Domain.clear(); - - char acBuffer[32]; - for (int i = MDNS_IP4_SIZE; ((bResult) && (i >= 1)); --i) - { - itoa(p_IP4Address[i - 1], acBuffer, 10); - bResult = p_rReverseIP4Domain.addLabel(acBuffer); - } - bResult = ((bResult) && - (p_rReverseIP4Domain.addLabel(scpcReverseIP4Domain)) && - (p_rReverseIP4Domain.addLabel(scpcReverseTopDomain)) && - (p_rReverseIP4Domain.addLabel(0))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForReverseIP4: FAILED!\n"));); - return bResult; -} -#endif - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::_buildDomainForReverseIP6 - - Used while detecting reverse IP6 questions and answering these -*/ -bool MDNSResponder::_buildDomainForReverseIP6(IPAddress p_IP4Address, - MDNSResponder::stcMDNS_RRDomain& p_rReverseIP6Domain) const -{ - // TODO: Implement - return false; -} -#endif - - -/* - UDP -*/ - -/* - MDNSResponder::_udpReadBuffer -*/ -bool MDNSResponder::_udpReadBuffer(unsigned char* p_pBuffer, - size_t p_stLength) -{ - - bool bResult = ((m_pUDPContext) && - (true/*m_pUDPContext->getSize() > p_stLength*/) && - (p_pBuffer) && - (p_stLength) && - ((p_stLength == m_pUDPContext->read((char*)p_pBuffer, p_stLength)))); - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _udpReadBuffer: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_udpRead8 -*/ -bool MDNSResponder::_udpRead8(uint8_t& p_ru8Value) -{ - - return _udpReadBuffer((unsigned char*)&p_ru8Value, sizeof(p_ru8Value)); -} - -/* - MDNSResponder::_udpRead16 -*/ -bool MDNSResponder::_udpRead16(uint16_t& p_ru16Value) -{ - - bool bResult = false; - - if (_udpReadBuffer((unsigned char*)&p_ru16Value, sizeof(p_ru16Value))) - { - p_ru16Value = lwip_ntohs(p_ru16Value); - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::_udpRead32 -*/ -bool MDNSResponder::_udpRead32(uint32_t& p_ru32Value) -{ - - bool bResult = false; - - if (_udpReadBuffer((unsigned char*)&p_ru32Value, sizeof(p_ru32Value))) - { - p_ru32Value = lwip_ntohl(p_ru32Value); - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::_udpAppendBuffer -*/ -bool MDNSResponder::_udpAppendBuffer(const unsigned char* p_pcBuffer, - size_t p_stLength) -{ - - bool bResult = ((m_pUDPContext) && - (p_pcBuffer) && - (p_stLength) && - (p_stLength == m_pUDPContext->append((const char*)p_pcBuffer, p_stLength))); - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _udpAppendBuffer: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_udpAppend8 -*/ -bool MDNSResponder::_udpAppend8(uint8_t p_u8Value) -{ - - return (_udpAppendBuffer((unsigned char*)&p_u8Value, sizeof(p_u8Value))); -} - -/* - MDNSResponder::_udpAppend16 -*/ -bool MDNSResponder::_udpAppend16(uint16_t p_u16Value) -{ - - p_u16Value = lwip_htons(p_u16Value); - return (_udpAppendBuffer((unsigned char*)&p_u16Value, sizeof(p_u16Value))); -} - -/* - MDNSResponder::_udpAppend32 -*/ -bool MDNSResponder::_udpAppend32(uint32_t p_u32Value) -{ - - p_u32Value = lwip_htonl(p_u32Value); - return (_udpAppendBuffer((unsigned char*)&p_u32Value, sizeof(p_u32Value))); -} - -#ifdef DEBUG_ESP_MDNS_RESPONDER -/* - MDNSResponder::_udpDump -*/ -bool MDNSResponder::_udpDump(bool p_bMovePointer /*= false*/) -{ - - const uint8_t cu8BytesPerLine = 16; - - uint32_t u32StartPosition = m_pUDPContext->tell(); - DEBUG_OUTPUT.println("UDP Context Dump:"); - uint32_t u32Counter = 0; - uint8_t u8Byte = 0; - - while (_udpRead8(u8Byte)) - { - DEBUG_OUTPUT.printf_P(PSTR("%02x %s"), u8Byte, ((++u32Counter % cu8BytesPerLine) ? "" : "\n")); - } - DEBUG_OUTPUT.printf_P(PSTR("%sDone: %u bytes\n"), (((u32Counter) && (u32Counter % cu8BytesPerLine)) ? "\n" : ""), u32Counter); - - if (!p_bMovePointer) // Restore - { - m_pUDPContext->seek(u32StartPosition); - } - return true; -} - -/* - MDNSResponder::_udpDump -*/ -bool MDNSResponder::_udpDump(unsigned p_uOffset, - unsigned p_uLength) -{ - - if ((m_pUDPContext) && - (m_pUDPContext->isValidOffset(p_uOffset))) - { - unsigned uCurrentPosition = m_pUDPContext->tell(); // Remember start position - - m_pUDPContext->seek(p_uOffset); - uint8_t u8Byte; - for (unsigned u = 0; ((u < p_uLength) && (_udpRead8(u8Byte))); ++u) - { - DEBUG_OUTPUT.printf_P(PSTR("%02x "), u8Byte); - } - // Return to start position - m_pUDPContext->seek(uCurrentPosition); - } - return true; -} -#endif - - -/** - READ/WRITE MDNS STRUCTS -*/ - -/* - MDNSResponder::_readMDNSMsgHeader - - Read a MDNS header from the UDP input buffer. - | 8 | 8 | 8 | 8 | - 00| Identifier | Flags & Codes | - 01| Question count | Answer count | - 02| NS answer count | Ad answer count | - - All 16-bit and 32-bit elements need to be translated form network coding to host coding (done in _udpRead16 and _udpRead32) - In addition, bitfield memory order is undefined in C standard (GCC doesn't order them in the coded direction...), so they - need some mapping here -*/ -bool MDNSResponder::_readMDNSMsgHeader(MDNSResponder::stcMDNS_MsgHeader& p_rMsgHeader) -{ - - bool bResult = false; - - uint8_t u8B1; - uint8_t u8B2; - if ((_udpRead16(p_rMsgHeader.m_u16ID)) && - (_udpRead8(u8B1)) && - (_udpRead8(u8B2)) && - (_udpRead16(p_rMsgHeader.m_u16QDCount)) && - (_udpRead16(p_rMsgHeader.m_u16ANCount)) && - (_udpRead16(p_rMsgHeader.m_u16NSCount)) && - (_udpRead16(p_rMsgHeader.m_u16ARCount))) - { - - p_rMsgHeader.m_1bQR = (u8B1 & 0x80); // Query/Responde flag - p_rMsgHeader.m_4bOpcode = (u8B1 & 0x78); // Operation code (0: Standard query, others ignored) - p_rMsgHeader.m_1bAA = (u8B1 & 0x04); // Authorative answer - p_rMsgHeader.m_1bTC = (u8B1 & 0x02); // Truncation flag - p_rMsgHeader.m_1bRD = (u8B1 & 0x01); // Recursion desired - - p_rMsgHeader.m_1bRA = (u8B2 & 0x80); // Recursion available - p_rMsgHeader.m_3bZ = (u8B2 & 0x70); // Zero - p_rMsgHeader.m_4bRCode = (u8B2 & 0x0F); // Response code - - /* DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readMDNSMsgHeader: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), - (unsigned)p_rMsgHeader.m_u16ID, - (unsigned)p_rMsgHeader.m_1bQR, (unsigned)p_rMsgHeader.m_4bOpcode, (unsigned)p_rMsgHeader.m_1bAA, (unsigned)p_rMsgHeader.m_1bTC, (unsigned)p_rMsgHeader.m_1bRD, - (unsigned)p_rMsgHeader.m_1bRA, (unsigned)p_rMsgHeader.m_4bRCode, - (unsigned)p_rMsgHeader.m_u16QDCount, - (unsigned)p_rMsgHeader.m_u16ANCount, - (unsigned)p_rMsgHeader.m_u16NSCount, - (unsigned)p_rMsgHeader.m_u16ARCount););*/ - bResult = true; - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readMDNSMsgHeader: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_write8 -*/ -bool MDNSResponder::_write8(uint8_t p_u8Value, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - return ((_udpAppend8(p_u8Value)) && - (p_rSendParameter.shiftOffset(sizeof(p_u8Value)))); -} - -/* - MDNSResponder::_write16 -*/ -bool MDNSResponder::_write16(uint16_t p_u16Value, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - return ((_udpAppend16(p_u16Value)) && - (p_rSendParameter.shiftOffset(sizeof(p_u16Value)))); -} - -/* - MDNSResponder::_write32 -*/ -bool MDNSResponder::_write32(uint32_t p_u32Value, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - return ((_udpAppend32(p_u32Value)) && - (p_rSendParameter.shiftOffset(sizeof(p_u32Value)))); -} - -/* - MDNSResponder::_writeMDNSMsgHeader - - Write MDNS header to the UDP output buffer. - - All 16-bit and 32-bit elements need to be translated form host coding to network coding (done in _udpAppend16 and _udpAppend32) - In addition, bitfield memory order is undefined in C standard (GCC doesn't order them in the coded direction...), so they - need some mapping here -*/ -bool MDNSResponder::_writeMDNSMsgHeader(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHeader, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - /* DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSMsgHeader: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), - (unsigned)p_MsgHeader.m_u16ID, - (unsigned)p_MsgHeader.m_1bQR, (unsigned)p_MsgHeader.m_4bOpcode, (unsigned)p_MsgHeader.m_1bAA, (unsigned)p_MsgHeader.m_1bTC, (unsigned)p_MsgHeader.m_1bRD, - (unsigned)p_MsgHeader.m_1bRA, (unsigned)p_MsgHeader.m_4bRCode, - (unsigned)p_MsgHeader.m_u16QDCount, - (unsigned)p_MsgHeader.m_u16ANCount, - (unsigned)p_MsgHeader.m_u16NSCount, - (unsigned)p_MsgHeader.m_u16ARCount););*/ - - uint8_t u8B1((p_MsgHeader.m_1bQR << 7) | (p_MsgHeader.m_4bOpcode << 3) | (p_MsgHeader.m_1bAA << 2) | (p_MsgHeader.m_1bTC << 1) | (p_MsgHeader.m_1bRD)); - uint8_t u8B2((p_MsgHeader.m_1bRA << 7) | (p_MsgHeader.m_3bZ << 4) | (p_MsgHeader.m_4bRCode)); - bool bResult = ((_write16(p_MsgHeader.m_u16ID, p_rSendParameter)) && - (_write8(u8B1, p_rSendParameter)) && - (_write8(u8B2, p_rSendParameter)) && - (_write16(p_MsgHeader.m_u16QDCount, p_rSendParameter)) && - (_write16(p_MsgHeader.m_u16ANCount, p_rSendParameter)) && - (_write16(p_MsgHeader.m_u16NSCount, p_rSendParameter)) && - (_write16(p_MsgHeader.m_u16ARCount, p_rSendParameter))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSMsgHeader: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_writeRRAttributes -*/ -bool MDNSResponder::_writeMDNSRRAttributes(const MDNSResponder::stcMDNS_RRAttributes& p_Attributes, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - bool bResult = ((_write16(p_Attributes.m_u16Type, p_rSendParameter)) && - (_write16(p_Attributes.m_u16Class, p_rSendParameter))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSRRAttributes: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_writeMDNSRRDomain -*/ -bool MDNSResponder::_writeMDNSRRDomain(const MDNSResponder::stcMDNS_RRDomain& p_Domain, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - bool bResult = ((_udpAppendBuffer((const unsigned char*)p_Domain.m_acName, p_Domain.m_u16NameLength)) && - (p_rSendParameter.shiftOffset(p_Domain.m_u16NameLength))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSRRDomain: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_writeMDNSHostDomain - - Write a host domain to the UDP output buffer. - If the domain record is part of the answer, the records length is - prepended (p_bPrependRDLength is set). - - A very simple form of name compression is applied here: - If the domain is written to the UDP output buffer, the write offset is stored - together with a domain id (the pointer) in a p_rSendParameter substructure (cache). - If the same domain (pointer) should be written to the UDP output later again, - the old offset is retrieved from the cache, marked as a compressed domain offset - and written to the output buffer. - -*/ -bool MDNSResponder::_writeMDNSHostDomain(const char* p_pcHostname, - bool p_bPrependRDLength, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - // The 'skip-compression' version is handled in '_writeMDNSAnswer_SRV' - uint16_t u16CachedDomainOffset = p_rSendParameter.findCachedDomainOffset((const void*)p_pcHostname, false); - - stcMDNS_RRDomain hostDomain; - bool bResult = (u16CachedDomainOffset - // Found cached domain -> mark as compressed domain - ? ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset - ((!p_bPrependRDLength) || - (_write16(2, p_rSendParameter))) && // Length of 'Cxxx' - (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) - (_write8((uint8_t)(u16CachedDomainOffset & 0xFF), p_rSendParameter))) - // No cached domain -> add this domain to cache and write full domain name - : ((_buildDomainForHost(p_pcHostname, hostDomain)) && // eg. esp8266.local - ((!p_bPrependRDLength) || - (_write16(hostDomain.m_u16NameLength, p_rSendParameter))) && // RDLength (if needed) - (p_rSendParameter.addDomainCacheItem((const void*)p_pcHostname, false, p_rSendParameter.m_u16Offset)) && - (_writeMDNSRRDomain(hostDomain, p_rSendParameter)))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSHostDomain: FAILED!\n")); - }); - return bResult; - -} - -/* - MDNSResponder::_writeMDNSServiceDomain - - Write a service domain to the UDP output buffer. - If the domain record is part of the answer, the records length is - prepended (p_bPrependRDLength is set). - - A very simple form of name compression is applied here: see '_writeMDNSHostDomain' - The cache differentiates of course between service domains which includes - the instance name (p_bIncludeName is set) and thoose who don't. - -*/ -bool MDNSResponder::_writeMDNSServiceDomain(const MDNSResponder::stcMDNSService& p_Service, - bool p_bIncludeName, - bool p_bPrependRDLength, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - // The 'skip-compression' version is handled in '_writeMDNSAnswer_SRV' - uint16_t u16CachedDomainOffset = p_rSendParameter.findCachedDomainOffset((const void*)&p_Service, p_bIncludeName); - - stcMDNS_RRDomain serviceDomain; - bool bResult = (u16CachedDomainOffset - // Found cached domain -> mark as compressed domain - ? ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset - ((!p_bPrependRDLength) || - (_write16(2, p_rSendParameter))) && // Lenght of 'Cxxx' - (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) - (_write8((uint8_t)(u16CachedDomainOffset & 0xFF), p_rSendParameter))) - // No cached domain -> add this domain to cache and write full domain name - : ((_buildDomainForService(p_Service, p_bIncludeName, serviceDomain)) && // eg. MyESP._http._tcp.local - ((!p_bPrependRDLength) || - (_write16(serviceDomain.m_u16NameLength, p_rSendParameter))) && // RDLength (if needed) - (p_rSendParameter.addDomainCacheItem((const void*)&p_Service, p_bIncludeName, p_rSendParameter.m_u16Offset)) && - (_writeMDNSRRDomain(serviceDomain, p_rSendParameter)))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSServiceDomain: FAILED!\n")); - }); - return bResult; - -} - -/* - MDNSResponder::_writeMDNSQuestion - - Write a MDNS question to the UDP output buffer - - QNAME (host/service domain, eg. esp8266.local) - QTYPE (16bit, eg. ANY) - QCLASS (16bit, eg. IN) - -*/ -bool MDNSResponder::_writeMDNSQuestion(MDNSResponder::stcMDNS_RRQuestion& p_Question, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSQuestion\n"));); - - bool bResult = ((_writeMDNSRRDomain(p_Question.m_Header.m_Domain, p_rSendParameter)) && - (_writeMDNSRRAttributes(p_Question.m_Header.m_Attributes, p_rSendParameter))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSQuestion: FAILED!\n")); - }); - return bResult; - -} - - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::_writeMDNSAnswer_A - - Write a MDNS A answer to the UDP output buffer. - - NAME (var, host/service domain, eg. esp8266.local - TYPE (16bit, eg. A) - CLASS (16bit, eg. IN) - TTL (32bit, eg. 120) - RDLENGTH (16bit, eg 4) - RDATA (var, eg. 123.456.789.012) - - eg. esp8266.local A 0x8001 120 4 123.456.789.012 - Ref: http://www.zytrax.com/books/dns/ch8/a.html -*/ -bool MDNSResponder::_writeMDNSAnswer_A(IPAddress p_IPAddress, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_A (%s)\n"), p_IPAddress.toString().c_str());); - - stcMDNS_RRAttributes attributes(DNS_RRTYPE_A, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - const unsigned char aucIPAddress[MDNS_IP4_SIZE] = { p_IPAddress[0], p_IPAddress[1], p_IPAddress[2], p_IPAddress[3] }; - bool bResult = ((_writeMDNSHostDomain(m_pcHostname, false, p_rSendParameter)) && - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter)) && // TTL - (_write16(MDNS_IP4_SIZE, p_rSendParameter)) && // RDLength - (_udpAppendBuffer(aucIPAddress, MDNS_IP4_SIZE)) && // RData - (p_rSendParameter.shiftOffset(MDNS_IP4_SIZE))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_A: FAILED!\n")); - }); - return bResult; - -} - -/* - MDNSResponder::_writeMDNSAnswer_PTR_IP4 - - Write a MDNS reverse IP4 PTR answer to the UDP output buffer. - See: '_writeMDNSAnswer_A' - - eg. 012.789.456.123.in-addr.arpa PTR 0x8001 120 15 esp8266.local - Used while answering reverse IP4 questions -*/ -bool MDNSResponder::_writeMDNSAnswer_PTR_IP4(IPAddress p_IPAddress, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_IP4 (%s)\n"), p_IPAddress.toString().c_str());); - - stcMDNS_RRDomain reverseIP4Domain; - stcMDNS_RRAttributes attributes(DNS_RRTYPE_PTR, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - stcMDNS_RRDomain hostDomain; - bool bResult = ((_buildDomainForReverseIP4(p_IPAddress, reverseIP4Domain)) && // 012.789.456.123.in-addr.arpa - (_writeMDNSRRDomain(reverseIP4Domain, p_rSendParameter)) && - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter)) && // TTL - (_writeMDNSHostDomain(m_pcHostname, true, p_rSendParameter))); // RDLength & RData (host domain, eg. esp8266.local) - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_IP4: FAILED!\n")); - }); - return bResult; -} -#endif - -/* - MDNSResponder::_writeMDNSAnswer_PTR_TYPE - - Write a MDNS PTR answer to the UDP output buffer. - See: '_writeMDNSAnswer_A' - - PTR all-services -> service type - eg. _services._dns-sd._udp.local PTR 0x8001 5400 xx _http._tcp.local - http://www.zytrax.com/books/dns/ch8/ptr.html -*/ -bool MDNSResponder::_writeMDNSAnswer_PTR_TYPE(MDNSResponder::stcMDNSService& p_rService, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_TYPE\n"));); - - stcMDNS_RRDomain dnssdDomain; - stcMDNS_RRDomain serviceDomain; - stcMDNS_RRAttributes attributes(DNS_RRTYPE_PTR, DNS_RRCLASS_IN); // No cache flush! only INternet - bool bResult = ((_buildDomainForDNSSD(dnssdDomain)) && // _services._dns-sd._udp.local - (_writeMDNSRRDomain(dnssdDomain, p_rSendParameter)) && - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_SERVICE_TTL), p_rSendParameter)) && // TTL - (_writeMDNSServiceDomain(p_rService, false, true, p_rSendParameter))); // RDLength & RData (service domain, eg. _http._tcp.local) - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_TYPE: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_writeMDNSAnswer_PTR_NAME - - Write a MDNS PTR answer to the UDP output buffer. - See: '_writeMDNSAnswer_A' - - PTR service type -> service name - eg. _http.tcp.local PTR 0x8001 120 xx myESP._http._tcp.local - http://www.zytrax.com/books/dns/ch8/ptr.html -*/ -bool MDNSResponder::_writeMDNSAnswer_PTR_NAME(MDNSResponder::stcMDNSService& p_rService, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_NAME\n"));); - - stcMDNS_RRAttributes attributes(DNS_RRTYPE_PTR, DNS_RRCLASS_IN); // No cache flush! only INternet - bool bResult = ((_writeMDNSServiceDomain(p_rService, false, false, p_rSendParameter)) && // _http._tcp.local - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_SERVICE_TTL), p_rSendParameter)) && // TTL - (_writeMDNSServiceDomain(p_rService, true, true, p_rSendParameter))); // RDLength & RData (service domain, eg. MyESP._http._tcp.local) - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_NAME: FAILED!\n")); - }); - return bResult; -} - - -/* - MDNSResponder::_writeMDNSAnswer_TXT - - Write a MDNS TXT answer to the UDP output buffer. - See: '_writeMDNSAnswer_A' - - The TXT items in the RDATA block are 'length byte encoded': [len]vardata - - eg. myESP._http._tcp.local TXT 0x8001 120 4 c#=1 - http://www.zytrax.com/books/dns/ch8/txt.html -*/ -bool MDNSResponder::_writeMDNSAnswer_TXT(MDNSResponder::stcMDNSService& p_rService, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_TXT\n"));); - - bool bResult = false; - - stcMDNS_RRAttributes attributes(DNS_RRTYPE_TXT, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - - if ((_collectServiceTxts(p_rService)) && - (_writeMDNSServiceDomain(p_rService, true, false, p_rSendParameter)) && // MyESP._http._tcp.local - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_SERVICE_TTL), p_rSendParameter)) && // TTL - (_write16(p_rService.m_Txts.length(), p_rSendParameter))) // RDLength - { - - bResult = true; - // RData Txts - for (stcMDNSServiceTxt* pTxt = p_rService.m_Txts.m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) - { - unsigned char ucLengthByte = pTxt->length(); - bResult = ((_udpAppendBuffer((unsigned char*)&ucLengthByte, sizeof(ucLengthByte))) && // Length - (p_rSendParameter.shiftOffset(sizeof(ucLengthByte))) && - ((size_t)os_strlen(pTxt->m_pcKey) == m_pUDPContext->append(pTxt->m_pcKey, os_strlen(pTxt->m_pcKey))) && // Key - (p_rSendParameter.shiftOffset((size_t)os_strlen(pTxt->m_pcKey))) && - (1 == m_pUDPContext->append("=", 1)) && // = - (p_rSendParameter.shiftOffset(1)) && - ((!pTxt->m_pcValue) || - (((size_t)os_strlen(pTxt->m_pcValue) == m_pUDPContext->append(pTxt->m_pcValue, os_strlen(pTxt->m_pcValue))) && // Value - (p_rSendParameter.shiftOffset((size_t)os_strlen(pTxt->m_pcValue)))))); - - DEBUG_EX_ERR(if (!bResult) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_TXT: FAILED to write %sTxt %s=%s!\n"), (pTxt->m_bTemp ? "temp. " : ""), (pTxt->m_pcKey ? : "?"), (pTxt->m_pcValue ? : "?")); - }); - } - } - _releaseTempServiceTxts(p_rService); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_TXT: FAILED!\n")); - }); - return bResult; -} - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::_writeMDNSAnswer_AAAA - - Write a MDNS AAAA answer to the UDP output buffer. - See: '_writeMDNSAnswer_A' - - eg. esp8266.local AAAA 0x8001 120 16 xxxx::xx - http://www.zytrax.com/books/dns/ch8/aaaa.html -*/ -bool MDNSResponder::_writeMDNSAnswer_AAAA(IPAddress p_IPAddress, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_AAAA\n"));); - - stcMDNS_RRAttributes attributes(DNS_RRTYPE_AAAA, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - bool bResult = ((_writeMDNSHostDomain(m_pcHostname, false, p_rSendParameter)) && // esp8266.local - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter)) && // TTL - (_write16(MDNS_IP6_SIZE, p_rSendParameter)) && // RDLength - (false /*TODO: IP6 version of: _udpAppendBuffer((uint32_t)p_IPAddress, MDNS_IP4_SIZE)*/)); // RData - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_AAAA: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_writeMDNSAnswer_PTR_IP6 - - Write a MDNS reverse IP6 PTR answer to the UDP output buffer. - See: '_writeMDNSAnswer_A' - - eg. xxxx::xx.in6.arpa PTR 0x8001 120 15 esp8266.local - Used while answering reverse IP6 questions -*/ -bool MDNSResponder::_writeMDNSAnswer_PTR_IP6(IPAddress p_IPAddress, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_IP6\n"));); - - stcMDNS_RRDomain reverseIP6Domain; - stcMDNS_RRAttributes attributes(DNS_RRTYPE_PTR, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - bool bResult = ((_buildDomainForReverseIP6(p_IPAddress, reverseIP6Domain)) && // xxxx::xx.ip6.arpa - (_writeMDNSRRDomain(reverseIP6Domain, p_rSendParameter)) && - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter)) && // TTL - (_writeMDNSHostDomain(m_pcHostname, true, p_rSendParameter))); // RDLength & RData (host domain, eg. esp8266.local) - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_IP6: FAILED!\n")); - }); - return bResult; -} -#endif - -/* - MDNSResponder::_writeMDNSAnswer_SRV - - eg. MyESP._http.tcp.local SRV 0x8001 120 0 0 60068 esp8266.local - http://www.zytrax.com/books/dns/ch8/srv.html ???? Include instance name ???? -*/ -bool MDNSResponder::_writeMDNSAnswer_SRV(MDNSResponder::stcMDNSService& p_rService, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_SRV\n"));); - - uint16_t u16CachedDomainOffset = (p_rSendParameter.m_bLegacyQuery - ? 0 - : p_rSendParameter.findCachedDomainOffset((const void*)m_pcHostname, false)); - - stcMDNS_RRAttributes attributes(DNS_RRTYPE_SRV, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - stcMDNS_RRDomain hostDomain; - bool bResult = ((_writeMDNSServiceDomain(p_rService, true, false, p_rSendParameter)) && // MyESP._http._tcp.local - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_SERVICE_TTL), p_rSendParameter)) && // TTL - (!u16CachedDomainOffset - // No cache for domain name (or no compression allowed) - ? ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (_write16((sizeof(uint16_t /*Prio*/) + // RDLength - sizeof(uint16_t /*Weight*/) + - sizeof(uint16_t /*Port*/) + - hostDomain.m_u16NameLength), p_rSendParameter)) && // Domain length - (_write16(MDNS_SRV_PRIORITY, p_rSendParameter)) && // Priority - (_write16(MDNS_SRV_WEIGHT, p_rSendParameter)) && // Weight - (_write16(p_rService.m_u16Port, p_rSendParameter)) && // Port - (p_rSendParameter.addDomainCacheItem((const void*)m_pcHostname, false, p_rSendParameter.m_u16Offset)) && - (_writeMDNSRRDomain(hostDomain, p_rSendParameter))) // Host, eg. esp8266.local - // Cache available for domain - : ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset - (_write16((sizeof(uint16_t /*Prio*/) + // RDLength - sizeof(uint16_t /*Weight*/) + - sizeof(uint16_t /*Port*/) + - 2), p_rSendParameter)) && // Length of 'C0xx' - (_write16(MDNS_SRV_PRIORITY, p_rSendParameter)) && // Priority - (_write16(MDNS_SRV_WEIGHT, p_rSendParameter)) && // Weight - (_write16(p_rService.m_u16Port, p_rSendParameter)) && // Port - (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) - (_write8((uint8_t)u16CachedDomainOffset, p_rSendParameter))))); // Offset - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_SRV: FAILED!\n")); - }); - return bResult; -} - -} // namespace MDNSImplementation - -} // namespace esp8266 - - - - - - diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_lwIPdefs.h b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_lwIPdefs.h deleted file mode 100644 index a3bcc4b370..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_lwIPdefs.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - LEAmDNS_Priv.h - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#ifndef MDNS_LWIPDEFS_H -#define MDNS_LWIPDEFS_H - -#include <lwip/init.h> -#if LWIP_VERSION_MAJOR == 1 - -#include <lwip/mdns.h> // DNS_RRTYPE_xxx - -// cherry pick from lwip1 dns.c/mdns.c source files: -#define DNS_MQUERY_PORT 5353 -#define DNS_MQUERY_IPV4_GROUP_INIT IPAddress(224,0,0,251) /* resolver1.opendns.com */ -#define DNS_RRCLASS_ANY 255 /* any class */ - -#else // lwIP > 1 - -#include <lwip/prot/dns.h> // DNS_RRTYPE_xxx, DNS_MQUERY_PORT - -#endif - -#endif // MDNS_LWIPDEFS_H diff --git a/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-SPIFFS.ino b/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino similarity index 100% rename from libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-SPIFFS.ino rename to libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 740b77db6f..c8c05082c5 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -32,6 +32,15 @@ #include <lwip/mld6.h> #endif +/** + STRINGIZE +*/ +#ifndef STRINGIZE +#define STRINGIZE(x) #x +#endif +#ifndef STRINGIZE_VALUE_OF +#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) +#endif namespace // anonymous { @@ -778,6 +787,27 @@ bool clsLEAMDNSHost::restart(void) } +/* + clsLEAMDNSHost_Legacy::enableArduino +*/ +clsLEAMDNSHost::clsService* clsLEAMDNSHost::enableArduino(uint16_t p_u16Port, + bool p_bAuthUpload /*= false*/) +{ + clsLEAMDNSHost::clsService* svc = addService("arduino", "arduino", "tcp", p_u16Port); + if (svc) + { + if ((!svc->addServiceTxt("tcp_check", "no")) + || (!svc->addServiceTxt("ssh_upload", "no")) + || (!svc->addServiceTxt("board", STRINGIZE_VALUE_OF(ARDUINO_BOARD))) + || (!svc->addServiceTxt("auth_upload", (p_bAuthUpload) ? "yes" : "no"))) + { + removeService(svc); + svc = 0; + } + } + return svc; +} + /* P R O T E C T E D diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index ceee11834a..bdcc05e21e 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -1350,6 +1350,8 @@ class clsLEAMDNSHost bool restart(void); + clsService* enableArduino(uint16_t p_u16Port, bool p_bAuthUpload = false); + protected: // File: ..._Host UdpContext* _allocBackbone(void); From 6d22b7073b879668ccdaf0213ec6bdc8252234d1 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 8 May 2020 22:09:05 +0200 Subject: [PATCH 008/152] still using current LEA --- .../OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino | 17 +++++++++++------ libraries/ESP8266mDNS/src/ESP8266mDNS.h | 19 +++++++++++-------- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h | 3 +++ 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino b/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino index 9d0d861474..34ffcc5c89 100644 --- a/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino +++ b/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino @@ -12,8 +12,13 @@ */ +#ifndef APSSID +#define APSSID "your-apssid" +#define APPSK "your-password" +#endif + #ifndef STASSID -#define STASSID "your-ssid" +#define STASSID "your-sta" #define STAPSK "your-password" #endif @@ -30,15 +35,15 @@ @brief mDNS and OTA Constants @{ */ -#define HOSTNAME "ESP8266-OTA-" ///< Hostename. The setup function adds the Chip ID at the end. +#define HOSTNAME "ESP8266-OTA-" ///< Hostname. The setup function adds the Chip ID at the end. /// @} /** @brief Default WiFi connection information. @{ */ -const char* ap_default_ssid = STASSID; ///< Default SSID. -const char* ap_default_psk = STAPSK; ///< Default PSK. +const char* ap_default_ssid = APSSID; ///< Default SSID. +const char* ap_default_psk = APPSK; ///< Default PSK. /// @} /// Uncomment the next line for verbose output over UART. @@ -166,8 +171,8 @@ void setup() { // Load wifi connection information. if (! loadConfig(&station_ssid, &station_psk)) { - station_ssid = ""; - station_psk = ""; + station_ssid = STASSID; + station_psk = STAPSK; Serial.println("No WiFi connection information available."); } diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index c3713c6689..7b921817e7 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -42,19 +42,22 @@ */ -enum class MDNSApiVersion { Legacy, LEA, LEAv2 }; +enum class MDNSApiVersion { Legacy, LEA, LEAv2Compat, LEAv2 }; -#include "ESP8266mDNS_Legacy.h" -#include "LEAmDNS.h" -#include "LEAmDNS2Host.h" +#include "ESP8266mDNS_Legacy.h" // Legacy +#include "LEAmDNS.h" // LEA +#include "LEAmDNS2_Legacy.h" // LEAv2Compat - replacement for LEA using v2 +#include "LEAmDNS2Host.h" // LEAv2 - API updated + +// clsMDNSHost replaces MDNSResponder in LEAv2 using clsMDNSHost = esp8266::experimental::clsLEAMDNSHost; #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) // Maps the implementation to use to the global namespace type -//using MDNSResponder = Legacy_MDNSResponder::MDNSResponder; // Legacy -using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA -//using MDNSResponder = clsMDNSHost; // LEAv2 +//using MDNSResponder = Legacy_MDNSResponder::MDNSResponder; // Legacy +using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA +//using MDNSResponder = esp8266::MDNSImplementation::clsLEAMDNSHost_Legacy; // LEAv2Compat +//using MDNSResponder = clsMDNSHost; // LEAv2 extern MDNSResponder MDNS; #endif - diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h index be4a731216..9ab1f14d0c 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h @@ -128,6 +128,9 @@ class clsLEAMDNSHost_Legacy }; public: + + static constexpr auto ApiVersion = MDNSApiVersion::LEAv2Compat; + /* INTERFACE */ clsLEAMDNSHost_Legacy(void); virtual ~clsLEAMDNSHost_Legacy(void); From b7c35048c77a632352a35fbbe5f69c4e9ea080d9 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 8 May 2020 23:15:28 +0200 Subject: [PATCH 009/152] remove unwanted change --- libraries/ESP8266WebServer/src/detail/RequestHandler.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandler.h b/libraries/ESP8266WebServer/src/detail/RequestHandler.h index c939d573bd..9202f623b3 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h @@ -7,9 +7,8 @@ template<typename ServerType> class RequestHandler { -public: using WebServerType = ESP8266WebServerTemplate<ServerType>; - +public: virtual ~RequestHandler() { } virtual bool canHandle(HTTPMethod method, String uri) { (void) method; (void) uri; return false; } virtual bool canUpload(String uri) { (void) uri; return false; } From ff0b10035dca6812a1a24e63890a8c4c5335033b Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 8 May 2020 23:21:47 +0200 Subject: [PATCH 010/152] remove unwanted changes --- .../src/detail/RequestHandler.h | 3 +- .../OLDmDNS/ESP8266mDNS_Legacy.cpp | 1523 ---------- .../ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.h | 166 -- libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.cpp | 1381 --------- libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.h | 1461 ---------- .../ESP8266mDNS/OLDmDNS/LEAmDNS_Control.cpp | 2134 -------------- .../ESP8266mDNS/OLDmDNS/LEAmDNS_Helpers.cpp | 850 ------ libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Priv.h | 182 -- .../ESP8266mDNS/OLDmDNS/LEAmDNS_Structs.cpp | 2476 ----------------- .../ESP8266mDNS/OLDmDNS/LEAmDNS_Transfer.cpp | 1779 ------------ .../ESP8266mDNS/OLDmDNS/LEAmDNS_lwIPdefs.h | 44 - 11 files changed, 1 insertion(+), 11998 deletions(-) delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.cpp delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.h delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.cpp delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.h delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Control.cpp delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Helpers.cpp delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Priv.h delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Structs.cpp delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Transfer.cpp delete mode 100644 libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_lwIPdefs.h diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandler.h b/libraries/ESP8266WebServer/src/detail/RequestHandler.h index c939d573bd..9202f623b3 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandler.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandler.h @@ -7,9 +7,8 @@ template<typename ServerType> class RequestHandler { -public: using WebServerType = ESP8266WebServerTemplate<ServerType>; - +public: virtual ~RequestHandler() { } virtual bool canHandle(HTTPMethod method, String uri) { (void) method; (void) uri; return false; } virtual bool canUpload(String uri) { (void) uri; return false; } diff --git a/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.cpp b/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.cpp deleted file mode 100644 index 8791195523..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.cpp +++ /dev/null @@ -1,1523 +0,0 @@ -/* - - ESP8266 Multicast DNS (port of CC3000 Multicast DNS library) - Version 1.1 - Copyright (c) 2013 Tony DiCola (tony@tonydicola.com) - ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com) - MDNS-SD Suport 2015 Hristo Gochkov - Extended MDNS-SD support 2016 Lars Englund (lars.englund@gmail.com) - - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -// Important RFC's for reference: -// - DNS request and response: http://www.ietf.org/rfc/rfc1035.txt -// - Multicast DNS: http://www.ietf.org/rfc/rfc6762.txt -// - MDNS-SD: https://tools.ietf.org/html/rfc6763 - -#ifndef LWIP_OPEN_SRC -#define LWIP_OPEN_SRC -#endif - -#include "ESP8266mDNS.h" -#include <functional> - -#include "debug.h" - -extern "C" { -#include "osapi.h" -#include "ets_sys.h" -#include "user_interface.h" -} - -#include "WiFiUdp.h" -#include "lwip/opt.h" -#include "lwip/udp.h" -#include "lwip/inet.h" -#include "lwip/igmp.h" -#include "lwip/mem.h" -#include "include/UdpContext.h" - - - -namespace Legacy_MDNSResponder -{ - - -#ifdef DEBUG_ESP_MDNS -#define DEBUG_ESP_MDNS_ERR -#define DEBUG_ESP_MDNS_TX -#define DEBUG_ESP_MDNS_RX -#endif - -#define MDNS_NAME_REF 0xC000 - -#define MDNS_TYPE_AAAA 0x001C -#define MDNS_TYPE_A 0x0001 -#define MDNS_TYPE_PTR 0x000C -#define MDNS_TYPE_SRV 0x0021 -#define MDNS_TYPE_TXT 0x0010 - -#define MDNS_CLASS_IN 0x0001 -#define MDNS_CLASS_IN_FLUSH_CACHE 0x8001 - -#define MDNS_ANSWERS_ALL 0x0F -#define MDNS_ANSWER_PTR 0x08 -#define MDNS_ANSWER_TXT 0x04 -#define MDNS_ANSWER_SRV 0x02 -#define MDNS_ANSWER_A 0x01 - -#define _conn_read32() (((uint32_t)_conn->read() << 24) | ((uint32_t)_conn->read() << 16) | ((uint32_t)_conn->read() << 8) | _conn->read()) -#define _conn_read16() (((uint16_t)_conn->read() << 8) | _conn->read()) -#define _conn_read8() _conn->read() -#define _conn_readS(b,l) _conn->read((char*)(b),l); - -static const IPAddress MDNS_MULTICAST_ADDR(224, 0, 0, 251); -static const int MDNS_MULTICAST_TTL = 1; -static const int MDNS_PORT = 5353; - -struct MDNSService -{ - MDNSService* _next; - char _name[32]; - char _proto[4]; - uint16_t _port; - uint16_t _txtLen; // length of all txts - struct MDNSTxt * _txts; -}; - -struct MDNSTxt -{ - MDNSTxt * _next; - String _txt; -}; - -struct MDNSAnswer -{ - MDNSAnswer* next; - uint8_t ip[4]; - uint16_t port; - char *hostname; -}; - -struct MDNSQuery -{ - char _service[32]; - char _proto[4]; -}; - - -MDNSResponder::MDNSResponder() : _conn(0) -{ - _services = 0; - _instanceName = ""; - _answers = 0; - _query = 0; - _newQuery = false; - _waitingForAnswers = false; -} -MDNSResponder::~MDNSResponder() -{ - if (_query != 0) - { - os_free(_query); - _query = 0; - } - - // Clear answer list - MDNSAnswer *answer; - int numAnswers = _getNumAnswers(); - for (int n = numAnswers - 1; n >= 0; n--) - { - answer = _getAnswerFromIdx(n); - os_free(answer->hostname); - os_free(answer); - answer = 0; - } - _answers = 0; - - if (_conn) - { - _conn->unref(); - } -} - -bool MDNSResponder::begin(const char* hostname) -{ - size_t n = strlen(hostname); - if (n > 63) // max size for a single label. - { - return false; - } - - // Copy in hostname characters as lowercase - _hostName = hostname; - _hostName.toLowerCase(); - - // If instance name is not already set copy hostname to instance name - if (_instanceName.equals("")) - { - _instanceName = hostname; - } - - _gotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP & event) - { - (void) event; - _restart(); - }); - - _disconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected & event) - { - (void) event; - _restart(); - }); - - return _listen(); -} - -void MDNSResponder::notifyAPChange() -{ - _restart(); -} - -void MDNSResponder::_restart() -{ - if (_conn) - { - _conn->unref(); - _conn = nullptr; - } - _listen(); -} - -bool MDNSResponder::_listen() -{ - // Open the MDNS socket if it isn't already open. - if (!_conn) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.println("MDNS listening"); -#endif - - IPAddress mdns(MDNS_MULTICAST_ADDR); - - if (igmp_joingroup(IP4_ADDR_ANY4, mdns) != ERR_OK) - { - return false; - } - - _conn = new UdpContext; - _conn->ref(); - - if (!_conn->listen(IP_ADDR_ANY, MDNS_PORT)) - { - return false; - } - _conn->setMulticastTTL(MDNS_MULTICAST_TTL); - _conn->onRx(std::bind(&MDNSResponder::update, this)); - _conn->connect(mdns, MDNS_PORT); - } - return true; -} - -void MDNSResponder::update() -{ - if (!_conn || !_conn->next()) - { - return; - } - _parsePacket(); -} - - -void MDNSResponder::setInstanceName(String name) -{ - if (name.length() > 63) - { - return; - } - _instanceName = name; -} - - -bool MDNSResponder::addServiceTxt(char *name, char *proto, char *key, char *value) -{ - MDNSService* servicePtr; - - uint8_t txtLen = os_strlen(key) + os_strlen(value) + 1; // Add one for equals sign - txtLen += 1; //accounts for length byte added when building the txt responce - //Find the service - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - //Checking Service names - if (strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) - { - //found a service name match - if (servicePtr->_txtLen + txtLen > 1300) - { - return false; //max txt record size - } - MDNSTxt *newtxt = new MDNSTxt; - newtxt->_txt = String(key) + '=' + String(value); - newtxt->_next = 0; - if (servicePtr->_txts == 0) //no services have been added - { - //Adding First TXT to service - servicePtr->_txts = newtxt; - servicePtr->_txtLen += txtLen; - return true; - } - else - { - MDNSTxt * txtPtr = servicePtr->_txts; - while (txtPtr->_next != 0) - { - txtPtr = txtPtr->_next; - } - //adding another TXT to service - txtPtr->_next = newtxt; - servicePtr->_txtLen += txtLen; - return true; - } - } - } - return false; -} - -void MDNSResponder::addService(char *name, char *proto, uint16_t port) -{ - if (_getServicePort(name, proto) != 0) - { - return; - } - if (os_strlen(name) > 32 || os_strlen(proto) != 3) - { - return; //bad arguments - } - struct MDNSService *srv = (struct MDNSService*)(os_malloc(sizeof(struct MDNSService))); - os_strcpy(srv->_name, name); - os_strcpy(srv->_proto, proto); - srv->_port = port; - srv->_next = 0; - srv->_txts = 0; - srv->_txtLen = 0; - - if (_services == 0) - { - _services = srv; - } - else - { - MDNSService* servicePtr = _services; - while (servicePtr->_next != 0) - { - servicePtr = servicePtr->_next; - } - servicePtr->_next = srv; - } - -} - -int MDNSResponder::queryService(char *service, char *proto) -{ -#ifdef DEBUG_ESP_MDNS_TX - DEBUG_ESP_PORT.printf("queryService %s %s\n", service, proto); -#endif - while (_answers != 0) - { - MDNSAnswer *currAnswer = _answers; - _answers = _answers->next; - os_free(currAnswer->hostname); - os_free(currAnswer); - currAnswer = 0; - } - if (_query != 0) - { - os_free(_query); - _query = 0; - } - _query = (struct MDNSQuery*)(os_malloc(sizeof(struct MDNSQuery))); - os_strcpy(_query->_service, service); - os_strcpy(_query->_proto, proto); - _newQuery = true; - - char underscore[] = "_"; - - // build service name with _ - char serviceName[os_strlen(service) + 2]; - os_strcpy(serviceName, underscore); - os_strcat(serviceName, service); - size_t serviceNameLen = os_strlen(serviceName); - - //build proto name with _ - char protoName[5]; - os_strcpy(protoName, underscore); - os_strcat(protoName, proto); - size_t protoNameLen = 4; - - //local string - char localName[] = "local"; - size_t localNameLen = 5; - - //terminator - char terminator[] = "\0"; - - // Only supports sending one PTR query - uint8_t questionCount = 1; - - _waitingForAnswers = true; - for (int itfn = 0; itfn < 2; itfn++) - { - struct ip_info ip_info; - - wifi_get_ip_info((!itfn) ? SOFTAP_IF : STATION_IF, &ip_info); - if (!ip_info.ip.addr) - { - continue; - } - _conn->setMulticastInterface(IPAddress(ip_info.ip.addr)); - - // Write the header - _conn->flush(); - uint8_t head[12] = - { - 0x00, 0x00, //ID = 0 - 0x00, 0x00, //Flags = response + authoritative answer - 0x00, questionCount, //Question count - 0x00, 0x00, //Answer count - 0x00, 0x00, //Name server records - 0x00, 0x00 //Additional records - }; - _conn->append(reinterpret_cast<const char*>(head), 12); - - // Only supports sending one PTR query - // Send the Name field (eg. "_http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // lenght of "_" + service - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_" + service - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // lenght of "_" + proto - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_" + proto - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // lenght of "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type and class - uint8_t ptrAttrs[4] = - { - 0x00, 0x0c, //PTR record query - 0x00, 0x01 //Class IN - }; - _conn->append(reinterpret_cast<const char*>(ptrAttrs), 4); - _conn->send(); - } - -#ifdef DEBUG_ESP_MDNS_TX - DEBUG_ESP_PORT.println("Waiting for answers.."); -#endif - delay(1000); - - _waitingForAnswers = false; - - return _getNumAnswers(); -} - -String MDNSResponder::hostname(int idx) -{ - MDNSAnswer *answer = _getAnswerFromIdx(idx); - if (answer == 0) - { - return String(); - } - return answer->hostname; -} - -IPAddress MDNSResponder::IP(int idx) -{ - MDNSAnswer *answer = _getAnswerFromIdx(idx); - if (answer == 0) - { - return IPAddress(); - } - return IPAddress(answer->ip); -} - -uint16_t MDNSResponder::port(int idx) -{ - MDNSAnswer *answer = _getAnswerFromIdx(idx); - if (answer == 0) - { - return 0; - } - return answer->port; -} - -MDNSAnswer* MDNSResponder::_getAnswerFromIdx(int idx) -{ - MDNSAnswer *answer = _answers; - while (answer != 0 && idx-- > 0) - { - answer = answer->next; - } - if (idx > 0) - { - return 0; - } - return answer; -} - -int MDNSResponder::_getNumAnswers() -{ - int numAnswers = 0; - MDNSAnswer *answer = _answers; - while (answer != 0) - { - numAnswers++; - answer = answer->next; - } - return numAnswers; -} - -MDNSTxt * MDNSResponder::_getServiceTxt(char *name, char *proto) -{ - MDNSService* servicePtr; - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - if (servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) - { - if (servicePtr->_txts == 0) - { - return nullptr; - } - return servicePtr->_txts; - } - } - return nullptr; -} - -uint16_t MDNSResponder::_getServiceTxtLen(char *name, char *proto) -{ - MDNSService* servicePtr; - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - if (servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) - { - if (servicePtr->_txts == 0) - { - return false; - } - return servicePtr->_txtLen; - } - } - return 0; -} - -uint16_t MDNSResponder::_getServicePort(char *name, char *proto) -{ - MDNSService* servicePtr; - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - if (servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) - { - return servicePtr->_port; - } - } - return 0; -} - -IPAddress MDNSResponder::_getRequestMulticastInterface() -{ - struct ip_info ip_info; - bool match_ap = false; - if (wifi_get_opmode() & SOFTAP_MODE) - { - const IPAddress& remote_ip = _conn->getRemoteAddress(); - wifi_get_ip_info(SOFTAP_IF, &ip_info); - IPAddress infoIp(ip_info.ip); - IPAddress infoMask(ip_info.netmask); - if (ip_info.ip.addr && ip_addr_netcmp((const ip_addr_t*)remote_ip, (const ip_addr_t*)infoIp, ip_2_ip4((const ip_addr_t*)infoMask))) - { - match_ap = true; - } - } - if (!match_ap) - { - wifi_get_ip_info(STATION_IF, &ip_info); - } - return IPAddress(ip_info.ip.addr); -} - -void MDNSResponder::_parsePacket() -{ - int i; - char tmp; - bool serviceParsed = false; - bool protoParsed = false; - bool localParsed = false; - - char hostName[255]; - uint8_t hostNameLen; - - char serviceName[32]; - uint8_t serviceNameLen; - uint16_t servicePort = 0; - - char protoName[32]; - protoName[0] = 0; - uint8_t protoNameLen = 0; - - uint16_t packetHeader[6]; - - for (i = 0; i < 6; i++) - { - packetHeader[i] = _conn_read16(); - } - - if ((packetHeader[1] & 0x8000) != 0) // Read answers - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("Reading answers RX: REQ, ID:%u, Q:%u, A:%u, NS:%u, ADD:%u\n", packetHeader[0], packetHeader[2], packetHeader[3], packetHeader[4], packetHeader[5]); -#endif - - if (!_waitingForAnswers) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.println("Not expecting any answers right now, returning"); -#endif - _conn->flush(); - return; - } - - int numAnswers = packetHeader[3] + packetHeader[5]; - // Assume that the PTR answer always comes first and that it is always accompanied by a TXT, SRV, AAAA (optional) and A answer in the same packet. - if (numAnswers < 4) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("Expected a packet with 4 or more answers, got %u\n", numAnswers); -#endif - _conn->flush(); - return; - } - - uint8_t tmp8; - uint16_t answerPort = 0; - uint8_t answerIp[4] = { 0, 0, 0, 0 }; - char answerHostName[255]; - bool serviceMatch = false; - MDNSAnswer *answer; - uint8_t partsCollected = 0; - uint8_t stringsRead = 0; - - answerHostName[0] = '\0'; - - // Clear answer list - if (_newQuery) - { - int oldAnswers = _getNumAnswers(); - for (int n = oldAnswers - 1; n >= 0; n--) - { - answer = _getAnswerFromIdx(n); - os_free(answer->hostname); - os_free(answer); - answer = 0; - } - _answers = 0; - _newQuery = false; - } - - while (numAnswers--) - { - // Read name - stringsRead = 0; - size_t last_bufferpos = 0; - do - { - tmp8 = _conn_read8(); - if (tmp8 == 0x00) // End of name - { - break; - } - if (tmp8 & 0xC0) // Compressed pointer - { - uint16_t offset = ((((uint16_t)tmp8) & ~0xC0) << 8) | _conn_read8(); - if (_conn->isValidOffset(offset)) - { - if (0 == last_bufferpos) - { - last_bufferpos = _conn->tell(); - } -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Compressed pointer, jumping from "); - DEBUG_ESP_PORT.print(last_bufferpos); - DEBUG_ESP_PORT.print(" to "); - DEBUG_ESP_PORT.println(offset); -#endif - _conn->seek(offset); - tmp8 = _conn_read8(); - } - else - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Skipping malformed compressed pointer"); -#endif - tmp8 = _conn_read8(); - break; - } - } - if (stringsRead > 3) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.println("failed to read the response name"); -#endif - _conn->flush(); - return; - } - _conn_readS(serviceName, tmp8); - serviceName[tmp8] = '\0'; -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf(" %d ", tmp8); - for (int n = 0; n < tmp8; n++) - { - DEBUG_ESP_PORT.printf("%c", serviceName[n]); - } - DEBUG_ESP_PORT.println(); -#endif - if (serviceName[0] == '_') - { - if (strcmp(&serviceName[1], _query->_service) == 0) - { - serviceMatch = true; -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("found matching service: %s\n", _query->_service); -#endif - } - } - stringsRead++; - } while (true); - if (last_bufferpos > 0) - { - _conn->seek(last_bufferpos); -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Compressed pointer, jumping back to "); - DEBUG_ESP_PORT.println(last_bufferpos); -#endif - } - - uint16_t answerType = _conn_read16(); // Read type - uint16_t answerClass = _conn_read16(); // Read class - uint32_t answerTtl = _conn_read32(); // Read ttl - uint16_t answerRdlength = _conn_read16(); // Read rdlength - - (void) answerClass; - (void) answerTtl; - - if (answerRdlength > 255) - { - if (answerType == MDNS_TYPE_TXT && answerRdlength < 1460) - { - while (--answerRdlength) - { - _conn->read(); - } - } - else - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("Data len too long! %u\n", answerRdlength); -#endif - _conn->flush(); - return; - } - } - -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("type: %04x rdlength: %d\n", answerType, answerRdlength); -#endif - - if (answerType == MDNS_TYPE_PTR) - { - partsCollected |= 0x01; - _conn_readS(hostName, answerRdlength); // Read rdata - if (hostName[answerRdlength - 2] & 0xc0) - { - memcpy(answerHostName, hostName + 1, answerRdlength - 3); - answerHostName[answerRdlength - 3] = '\0'; - } -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("PTR %d ", answerRdlength); - for (int n = 0; n < answerRdlength; n++) - { - DEBUG_ESP_PORT.printf("%c", hostName[n]); - } - DEBUG_ESP_PORT.println(); -#endif - } - - else if (answerType == MDNS_TYPE_TXT) - { - partsCollected |= 0x02; - _conn_readS(hostName, answerRdlength); // Read rdata -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("TXT %d ", answerRdlength); - for (int n = 0; n < answerRdlength; n++) - { - DEBUG_ESP_PORT.printf("%c", hostName[n]); - } - DEBUG_ESP_PORT.println(); -#endif - } - - else if (answerType == MDNS_TYPE_SRV) - { - partsCollected |= 0x04; - uint16_t answerPrio = _conn_read16(); // Read priority - uint16_t answerWeight = _conn_read16(); // Read weight - answerPort = _conn_read16(); // Read port - last_bufferpos = 0; - - (void) answerPrio; - (void) answerWeight; - - // Read hostname - tmp8 = _conn_read8(); - if (tmp8 & 0xC0) // Compressed pointer - { - uint16_t offset = ((((uint16_t)tmp8) & ~0xC0) << 8) | _conn_read8(); - if (_conn->isValidOffset(offset)) - { - last_bufferpos = _conn->tell(); -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Compressed pointer, jumping from "); - DEBUG_ESP_PORT.print(last_bufferpos); - DEBUG_ESP_PORT.print(" to "); - DEBUG_ESP_PORT.println(offset); -#endif - _conn->seek(offset); - tmp8 = _conn_read8(); - } - else - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Skipping malformed compressed pointer"); -#endif - tmp8 = _conn_read8(); - break; - } - } - _conn_readS(answerHostName, tmp8); - answerHostName[tmp8] = '\0'; -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("SRV %d ", tmp8); - for (int n = 0; n < tmp8; n++) - { - DEBUG_ESP_PORT.printf("%02x ", answerHostName[n]); - } - DEBUG_ESP_PORT.printf("\n%s\n", answerHostName); -#endif - if (last_bufferpos > 0) - { - _conn->seek(last_bufferpos); - tmp8 = 2; // Size of compression octets -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Compressed pointer, jumping back to "); - DEBUG_ESP_PORT.println(last_bufferpos); -#endif - } - if (answerRdlength - (6 + 1 + tmp8) > 0) // Skip any remaining rdata - { - _conn_readS(hostName, answerRdlength - (6 + 1 + tmp8)); - } - } - - else if (answerType == MDNS_TYPE_A) - { - partsCollected |= 0x08; - for (int i = 0; i < 4; i++) - { - answerIp[i] = _conn_read8(); - } - } - else - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("Ignoring unsupported type %02x\n", tmp8); -#endif - for (int n = 0; n < answerRdlength; n++) - { - (void)_conn_read8(); - } - } - - if ((partsCollected == 0x0F) && serviceMatch) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.println("All answers parsed, adding to _answers list.."); -#endif - // Add new answer to answer list - if (_answers == 0) - { - _answers = (struct MDNSAnswer*)(os_malloc(sizeof(struct MDNSAnswer))); - answer = _answers; - } - else - { - answer = _answers; - while (answer->next != 0) - { - answer = answer->next; - } - answer->next = (struct MDNSAnswer*)(os_malloc(sizeof(struct MDNSAnswer))); - answer = answer->next; - } - answer->next = 0; - answer->hostname = 0; - - // Populate new answer - answer->port = answerPort; - for (int i = 0; i < 4; i++) - { - answer->ip[i] = answerIp[i]; - } - answer->hostname = (char *)os_malloc(strlen(answerHostName) + 1); - os_strcpy(answer->hostname, answerHostName); - _conn->flush(); - return; - } - } - - _conn->flush(); - return; - } - - // PARSE REQUEST NAME - - hostNameLen = _conn_read8() % 255; - _conn_readS(hostName, hostNameLen); - hostName[hostNameLen] = '\0'; - - if (hostName[0] == '_') - { - serviceParsed = true; - memcpy(serviceName, hostName + 1, hostNameLen); - serviceNameLen = hostNameLen - 1; - hostNameLen = 0; - } - - if (hostNameLen > 0 && !_hostName.equals(hostName) && !_instanceName.equals(hostName)) - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_NO_HOST: %s\n", hostName); - DEBUG_ESP_PORT.printf("hostname: %s\n", _hostName.c_str()); - DEBUG_ESP_PORT.printf("instance: %s\n", _instanceName.c_str()); -#endif - _conn->flush(); - return; - } - - if (!serviceParsed) - { - serviceNameLen = _conn_read8() % 255; - _conn_readS(serviceName, serviceNameLen); - serviceName[serviceNameLen] = '\0'; - - if (serviceName[0] == '_') - { - memmove(serviceName, serviceName + 1, serviceNameLen); - serviceNameLen--; - serviceParsed = true; - } - else if (serviceNameLen == 5 && strcmp("local", serviceName) == 0) - { - tmp = _conn_read8(); - if (tmp == 0) - { - serviceParsed = true; - serviceNameLen = 0; - protoParsed = true; - protoNameLen = 0; - localParsed = true; - } - else - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_FQDN: %s\n", serviceName); -#endif - _conn->flush(); - return; - } - } - else - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_SERVICE: %s\n", serviceName); -#endif - _conn->flush(); - return; - } - } - - if (!protoParsed) - { - protoNameLen = _conn_read8() % 255; - _conn_readS(protoName, protoNameLen); - protoName[protoNameLen] = '\0'; - if (protoNameLen == 4 && protoName[0] == '_') - { - memmove(protoName, protoName + 1, protoNameLen); - protoNameLen--; - protoParsed = true; - } - else if (strcmp("services", serviceName) == 0 && strcmp("_dns-sd", protoName) == 0) - { - _conn->flush(); - IPAddress interface = _getRequestMulticastInterface(); - _replyToTypeEnumRequest(interface); - return; - } - else - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_PROTO: %s\n", protoName); -#endif - _conn->flush(); - return; - } - } - - if (!localParsed) - { - char localName[32]; - uint8_t localNameLen = _conn_read8() % 31; - _conn_readS(localName, localNameLen); - localName[localNameLen] = '\0'; - tmp = _conn_read8(); - if (localNameLen == 5 && strcmp("local", localName) == 0 && tmp == 0) - { - localParsed = true; - } - else - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_FQDN: %s\n", localName); -#endif - _conn->flush(); - return; - } - } - - if (serviceNameLen > 0 && protoNameLen > 0) - { - servicePort = _getServicePort(serviceName, protoName); - if (servicePort == 0) - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_NO_SERVICE: %s\n", serviceName); -#endif - _conn->flush(); - return; - } - } - else if (serviceNameLen > 0 || protoNameLen > 0) - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_SERVICE_PROTO: %s\n", serviceName); -#endif - _conn->flush(); - return; - } - - // RESPOND - -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("RX: REQ, ID:%u, Q:%u, A:%u, NS:%u, ADD:%u\n", packetHeader[0], packetHeader[2], packetHeader[3], packetHeader[4], packetHeader[5]); -#endif - - uint16_t currentType; - uint16_t currentClass; - - int numQuestions = packetHeader[2]; - if (numQuestions > 4) - { - numQuestions = 4; - } - uint16_t questions[4]; - int question = 0; - - while (numQuestions--) - { - currentType = _conn_read16(); - if (currentType & MDNS_NAME_REF) //new header handle it better! - { - currentType = _conn_read16(); - } - currentClass = _conn_read16(); - if (currentClass & MDNS_CLASS_IN) - { - questions[question++] = currentType; - } - - if (numQuestions > 0) - { - if (_conn_read16() != 0xC00C) //new question but for another host/service - { - _conn->flush(); - numQuestions = 0; - } - } - -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("REQ: "); - if (hostNameLen > 0) - { - DEBUG_ESP_PORT.printf("%s.", hostName); - } - if (serviceNameLen > 0) - { - DEBUG_ESP_PORT.printf("_%s.", serviceName); - } - if (protoNameLen > 0) - { - DEBUG_ESP_PORT.printf("_%s.", protoName); - } - DEBUG_ESP_PORT.printf("local. "); - - if (currentType == MDNS_TYPE_AAAA) - { - DEBUG_ESP_PORT.printf(" AAAA "); - } - else if (currentType == MDNS_TYPE_A) - { - DEBUG_ESP_PORT.printf(" A "); - } - else if (currentType == MDNS_TYPE_PTR) - { - DEBUG_ESP_PORT.printf(" PTR "); - } - else if (currentType == MDNS_TYPE_SRV) - { - DEBUG_ESP_PORT.printf(" SRV "); - } - else if (currentType == MDNS_TYPE_TXT) - { - DEBUG_ESP_PORT.printf(" TXT "); - } - else - { - DEBUG_ESP_PORT.printf(" 0x%04X ", currentType); - } - - if (currentClass == MDNS_CLASS_IN) - { - DEBUG_ESP_PORT.printf(" IN "); - } - else if (currentClass == MDNS_CLASS_IN_FLUSH_CACHE) - { - DEBUG_ESP_PORT.printf(" IN[F] "); - } - else - { - DEBUG_ESP_PORT.printf(" 0x%04X ", currentClass); - } - - DEBUG_ESP_PORT.printf("\n"); -#endif - } - uint8_t questionMask = 0; - uint8_t responseMask = 0; - for (i = 0; i < question; i++) - { - if (questions[i] == MDNS_TYPE_A) - { - questionMask |= 0x1; - responseMask |= 0x1; - } - else if (questions[i] == MDNS_TYPE_SRV) - { - questionMask |= 0x2; - responseMask |= 0x3; - } - else if (questions[i] == MDNS_TYPE_TXT) - { - questionMask |= 0x4; - responseMask |= 0x4; - } - else if (questions[i] == MDNS_TYPE_PTR) - { - questionMask |= 0x8; - responseMask |= 0xF; - } - } - - IPAddress interface = _getRequestMulticastInterface(); - return _replyToInstanceRequest(questionMask, responseMask, serviceName, protoName, servicePort, interface); -} - - -/** - STRINGIZE -*/ -#ifndef STRINGIZE -#define STRINGIZE(x) #x -#endif -#ifndef STRINGIZE_VALUE_OF -#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) -#endif - - -void MDNSResponder::enableArduino(uint16_t port, bool auth) -{ - - addService("arduino", "tcp", port); - addServiceTxt("arduino", "tcp", "tcp_check", "no"); - addServiceTxt("arduino", "tcp", "ssh_upload", "no"); - addServiceTxt("arduino", "tcp", "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD)); - addServiceTxt("arduino", "tcp", "auth_upload", (auth) ? "yes" : "no"); -} - -void MDNSResponder::_replyToTypeEnumRequest(IPAddress multicastInterface) -{ - MDNSService* servicePtr; - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - if (servicePtr->_port > 0) - { - char *service = servicePtr->_name; - char *proto = servicePtr->_proto; - //uint16_t port = servicePtr->_port; - -#ifdef DEBUG_ESP_MDNS_TX - DEBUG_ESP_PORT.printf("TX: service:%s, proto:%s\n", service, proto); -#endif - - char sdHostName[] = "_services"; - size_t sdHostNameLen = 9; - char sdServiceName[] = "_dns-sd"; - size_t sdServiceNameLen = 7; - char sdProtoName[] = "_udp"; - size_t sdProtoNameLen = 4; - - char underscore[] = "_"; - - // build service name with _ - char serviceName[os_strlen(service) + 2]; - os_strcpy(serviceName, underscore); - os_strcat(serviceName, service); - size_t serviceNameLen = os_strlen(serviceName); - - //build proto name with _ - char protoName[5]; - os_strcpy(protoName, underscore); - os_strcat(protoName, proto); - size_t protoNameLen = 4; - - //local string - char localName[] = "local"; - size_t localNameLen = 5; - - //terminator - char terminator[] = "\0"; - - //Write the header - _conn->flush(); - uint8_t head[12] = - { - 0x00, 0x00, //ID = 0 - 0x84, 0x00, //Flags = response + authoritative answer - 0x00, 0x00, //Question count - 0x00, 0x01, //Answer count - 0x00, 0x00, //Name server records - 0x00, 0x00, //Additional records - }; - _conn->append(reinterpret_cast<const char*>(head), 12); - - // Send the Name field (ie. "_services._dns-sd._udp.local") - _conn->append(reinterpret_cast<const char*>(&sdHostNameLen), 1); // length of "_services" - _conn->append(reinterpret_cast<const char*>(sdHostName), sdHostNameLen); // "_services" - _conn->append(reinterpret_cast<const char*>(&sdServiceNameLen), 1); // length of "_dns-sd" - _conn->append(reinterpret_cast<const char*>(sdServiceName), sdServiceNameLen);// "_dns-sd" - _conn->append(reinterpret_cast<const char*>(&sdProtoNameLen), 1); // length of "_udp" - _conn->append(reinterpret_cast<const char*>(sdProtoName), sdProtoNameLen); // "_udp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type, class, ttl and rdata length - uint8_t ptrDataLen = serviceNameLen + protoNameLen + localNameLen + 4; // 4 is three label sizes and the terminator - uint8_t ptrAttrs[10] = - { - 0x00, 0x0c, //PTR record query - 0x00, 0x01, //Class IN - 0x00, 0x00, 0x11, 0x94, //TTL 4500 - 0x00, ptrDataLen, //RData length - }; - _conn->append(reinterpret_cast<const char*>(ptrAttrs), 10); - - //Send the RData (ie. "_http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - _conn->setMulticastInterface(multicastInterface); - _conn->send(); - } - } -} - -void MDNSResponder::_replyToInstanceRequest(uint8_t questionMask, uint8_t responseMask, char * service, char *proto, uint16_t port, IPAddress multicastInterface) -{ - int i; - if (questionMask == 0) - { - return; - } - if (responseMask == 0) - { - return; - } - -#ifdef DEBUG_ESP_MDNS_TX - DEBUG_ESP_PORT.printf("TX: qmask:%01X, rmask:%01X, service:%s, proto:%s, port:%u\n", questionMask, responseMask, service, proto, port); -#endif - - - String instanceName = _instanceName; - size_t instanceNameLen = instanceName.length(); - - String hostName = _hostName; - size_t hostNameLen = hostName.length(); - - char underscore[] = "_"; - - // build service name with _ - char serviceName[os_strlen(service) + 2]; - os_strcpy(serviceName, underscore); - os_strcat(serviceName, service); - size_t serviceNameLen = os_strlen(serviceName); - - //build proto name with _ - char protoName[5]; - os_strcpy(protoName, underscore); - os_strcat(protoName, proto); - size_t protoNameLen = 4; - - //local string - char localName[] = "local"; - size_t localNameLen = 5; - - //terminator - char terminator[] = "\0"; - - uint8_t answerMask = responseMask & questionMask; - uint8_t answerCount = 0; - uint8_t additionalMask = responseMask & ~questionMask; - uint8_t additionalCount = 0; - for (i = 0; i < 4; i++) - { - if (answerMask & (1 << i)) - { - answerCount++; - } - if (additionalMask & (1 << i)) - { - additionalCount++; - } - } - - - //Write the header - _conn->flush(); - uint8_t head[12] = - { - 0x00, 0x00, //ID = 0 - 0x84, 0x00, //Flags = response + authoritative answer - 0x00, 0x00, //Question count - 0x00, answerCount, //Answer count - 0x00, 0x00, //Name server records - 0x00, additionalCount, //Additional records - }; - _conn->append(reinterpret_cast<const char*>(head), 12); - - for (int responseSection = 0; responseSection < 2; ++responseSection) - { - - // PTR Response - if ((responseSection == 0 ? answerMask : additionalMask) & 0x8) - { - // Send the Name field (ie. "_http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type, class, ttl and rdata length - uint8_t ptrDataLen = instanceNameLen + serviceNameLen + protoNameLen + localNameLen + 5; // 5 is four label sizes and the terminator - uint8_t ptrAttrs[10] = - { - 0x00, 0x0c, //PTR record query - 0x00, 0x01, //Class IN - 0x00, 0x00, 0x00, 0x78, //TTL 120 - 0x00, ptrDataLen, //RData length - }; - _conn->append(reinterpret_cast<const char*>(ptrAttrs), 10); - - //Send the RData (ie. "My IOT device._http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // length of "My IOT device" - _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - } - - //TXT Responce - if ((responseSection == 0 ? answerMask : additionalMask) & 0x4) - { - //Send the name field (ie. "My IOT device._http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // length of "My IOT device" - _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type, class, ttl and rdata length - uint8_t txtDataLen = _getServiceTxtLen(service, proto); - uint8_t txtAttrs[10] = - { - 0x00, 0x10, //TXT record query - 0x80, 0x01, //Class IN, with cache flush - 0x00, 0x00, 0x11, 0x94, //TTL 4500 - 0x00, txtDataLen, //RData length - }; - _conn->append(reinterpret_cast<const char*>(txtAttrs), 10); - - //Send the RData - MDNSTxt * txtPtr = _getServiceTxt(service, proto); - while (txtPtr != 0) - { - uint8_t txtLen = txtPtr->_txt.length(); - _conn->append(reinterpret_cast<const char*>(&txtLen), 1); // length of txt - _conn->append(reinterpret_cast<const char*>(txtPtr->_txt.c_str()), txtLen);// the txt - txtPtr = txtPtr->_next; - } - } - - - //SRV Responce - if ((responseSection == 0 ? answerMask : additionalMask) & 0x2) - { - //Send the name field (ie. "My IOT device._http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // length of "My IOT device" - _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type, class, ttl, rdata length, priority and weight - uint8_t srvDataSize = hostNameLen + localNameLen + 3; // 3 is 2 lable size bytes and the terminator - srvDataSize += 6; // Size of Priority, weight and port - uint8_t srvAttrs[10] = - { - 0x00, 0x21, //Type SRV - 0x80, 0x01, //Class IN, with cache flush - 0x00, 0x00, 0x00, 0x78, //TTL 120 - 0x00, srvDataSize, //RData length - }; - _conn->append(reinterpret_cast<const char*>(srvAttrs), 10); - - //Send the RData Priority weight and port - uint8_t srvRData[6] = - { - 0x00, 0x00, //Priority 0 - 0x00, 0x00, //Weight 0 - (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF) - }; - _conn->append(reinterpret_cast<const char*>(srvRData), 6); - //Send the RData (ie. "esp8266.local") - _conn->append(reinterpret_cast<const char*>(&hostNameLen), 1); // length of "esp8266" - _conn->append(reinterpret_cast<const char*>(hostName.c_str()), hostNameLen);// "esp8266" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - } - - // A Response - if ((responseSection == 0 ? answerMask : additionalMask) & 0x1) - { - //Send the RData (ie. "esp8266.local") - _conn->append(reinterpret_cast<const char*>(&hostNameLen), 1); // length of "esp8266" - _conn->append(reinterpret_cast<const char*>(hostName.c_str()), hostNameLen);// "esp8266" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - uint8_t aaaAttrs[10] = - { - 0x00, 0x01, //TYPE A - 0x80, 0x01, //Class IN, with cache flush - 0x00, 0x00, 0x00, 0x78, //TTL 120 - 0x00, 0x04, //DATA LEN - }; - _conn->append(reinterpret_cast<const char*>(aaaAttrs), 10); - - // Send RData - uint32_t ip = multicastInterface; - uint8_t aaaRData[4] = - { - (uint8_t)(ip & 0xFF), //IP first octet - (uint8_t)((ip >> 8) & 0xFF), //IP second octet - (uint8_t)((ip >> 16) & 0xFF), //IP third octet - (uint8_t)((ip >> 24) & 0xFF) //IP fourth octet - }; - _conn->append(reinterpret_cast<const char*>(aaaRData), 4); - } - } - - _conn->setMulticastInterface(multicastInterface); - _conn->send(); -} - -#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) -MDNSResponder MDNS; -#endif - -} // namespace Legacy_MDNSResponder - - - - diff --git a/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.h b/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.h deleted file mode 100644 index 9d3cfd2f62..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/ESP8266mDNS_Legacy.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - ESP8266 Multicast DNS (port of CC3000 Multicast DNS library) - Version 1.1 - Copyright (c) 2013 Tony DiCola (tony@tonydicola.com) - ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com) - Extended MDNS-SD support 2016 Lars Englund (lars.englund@gmail.com) - - This is a simple implementation of multicast DNS query support for an Arduino - running on ESP8266 chip. Only support for resolving address queries is currently - implemented. - - Requirements: - - ESP8266WiFi library - - Usage: - - Include the ESP8266 Multicast DNS library in the sketch. - - Call the begin method in the sketch's setup and provide a domain name (without - the '.local' suffix, i.e. just provide 'foo' to resolve 'foo.local'), and the - Adafruit CC3000 class instance. Optionally provide a time to live (in seconds) - for the DNS record--the default is 1 hour. - - Call the update method in each iteration of the sketch's loop function. - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ -#ifndef ESP8266MDNS_LEGACY_H -#define ESP8266MDNS_LEGACY_H - -#include "ESP8266WiFi.h" -#include "WiFiUdp.h" - -//this should be defined at build time -#ifndef ARDUINO_BOARD -#define ARDUINO_BOARD "generic" -#endif - -class UdpContext; - - -namespace Legacy_MDNSResponder -{ - - -struct MDNSService; -struct MDNSTxt; -struct MDNSAnswer; - -class MDNSResponder -{ -public: - MDNSResponder(); - ~MDNSResponder(); - bool begin(const char* hostName); - bool begin(const String& hostName) - { - return begin(hostName.c_str()); - } - //for compatibility - bool begin(const char* hostName, IPAddress ip, uint32_t ttl = 120) - { - (void) ip; - (void) ttl; - return begin(hostName); - } - bool begin(const String& hostName, IPAddress ip, uint32_t ttl = 120) - { - return begin(hostName.c_str(), ip, ttl); - } - /* Application should call this whenever AP is configured/disabled */ - void notifyAPChange(); - void update(); - - void addService(char *service, char *proto, uint16_t port); - void addService(const char *service, const char *proto, uint16_t port) - { - addService((char *)service, (char *)proto, port); - } - void addService(const String& service, const String& proto, uint16_t port) - { - addService(service.c_str(), proto.c_str(), port); - } - - bool addServiceTxt(char *name, char *proto, char * key, char * value); - bool addServiceTxt(const char *name, const char *proto, const char *key, const char * value) - { - return addServiceTxt((char *)name, (char *)proto, (char *)key, (char *)value); - } - bool addServiceTxt(const String& name, const String& proto, const String& key, const String& value) - { - return addServiceTxt(name.c_str(), proto.c_str(), key.c_str(), value.c_str()); - } - - int queryService(char *service, char *proto); - int queryService(const char *service, const char *proto) - { - return queryService((char *)service, (char *)proto); - } - int queryService(const String& service, const String& proto) - { - return queryService(service.c_str(), proto.c_str()); - } - String hostname(int idx); - IPAddress IP(int idx); - uint16_t port(int idx); - - void enableArduino(uint16_t port, bool auth = false); - - void setInstanceName(String name); - void setInstanceName(const char * name) - { - setInstanceName(String(name)); - } - void setInstanceName(char * name) - { - setInstanceName(String(name)); - } - -private: - struct MDNSService * _services; - UdpContext* _conn; - String _hostName; - String _instanceName; - struct MDNSAnswer * _answers; - struct MDNSQuery * _query; - bool _newQuery; - bool _waitingForAnswers; - WiFiEventHandler _disconnectedHandler; - WiFiEventHandler _gotIPHandler; - - - uint16_t _getServicePort(char *service, char *proto); - MDNSTxt * _getServiceTxt(char *name, char *proto); - uint16_t _getServiceTxtLen(char *name, char *proto); - IPAddress _getRequestMulticastInterface(); - void _parsePacket(); - void _replyToTypeEnumRequest(IPAddress multicastInterface); - void _replyToInstanceRequest(uint8_t questionMask, uint8_t responseMask, char * service, char *proto, uint16_t port, IPAddress multicastInterface); - MDNSAnswer* _getAnswerFromIdx(int idx); - int _getNumAnswers(); - bool _listen(); - void _restart(); -}; - -} // namespace Legacy_MDNSResponder - -#endif //ESP8266MDNS_H - - - diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.cpp deleted file mode 100644 index 87ff5167ff..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.cpp +++ /dev/null @@ -1,1381 +0,0 @@ -/* - LEAmDNS.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#include <Schedule.h> -#include <AddrList.h> - -#include "LEAmDNS_Priv.h" - - -namespace esp8266 -{ - -/* - LEAmDNS -*/ -namespace MDNSImplementation -{ - -/** - STRINGIZE -*/ -#ifndef STRINGIZE -#define STRINGIZE(x) #x -#endif -#ifndef STRINGIZE_VALUE_OF -#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) -#endif - - -/** - INTERFACE -*/ - -/** - MDNSResponder::MDNSResponder -*/ -MDNSResponder::MDNSResponder(void) - : m_pServices(0), - m_pUDPContext(0), - m_pcHostname(0), - m_pServiceQueries(0), - m_fnServiceTxtCallback(0), -#ifdef ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE - m_bPassivModeEnabled(true), -#else - m_bPassivModeEnabled(false), -#endif - m_netif(nullptr) -{ -} - -/* - MDNSResponder::~MDNSResponder -*/ -MDNSResponder::~MDNSResponder(void) -{ - - _resetProbeStatus(false); - _releaseServiceQueries(); - _releaseHostname(); - _releaseUDPContext(); - _releaseServices(); -} - -/* - MDNSResponder::begin - - Set the host domain (for probing) and install WiFi event handlers for - IP assignment and disconnection management. In both cases, the MDNS responder - is restarted (reset and restart probe status) - Finally the responder is (re)started - -*/ -bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& p_IPAddress, uint32_t p_u32TTL) -{ - - (void)p_u32TTL; // ignored - bool bResult = false; - - if (0 == m_pUDPContext) - { - if (_setHostname(p_pcHostname)) - { - - //// select interface - - m_netif = nullptr; - IPAddress ipAddress = p_IPAddress; - - if (!ipAddress.isSet()) - { - - IPAddress sta = WiFi.localIP(); - IPAddress ap = WiFi.softAPIP(); - - if (sta.isSet()) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] STA interface selected\n"))); - ipAddress = sta; - } - else if (ap.isSet()) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] AP interface selected\n"))); - ipAddress = ap; - } - else - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] standard interfaces are not up, please specify one in ::begin()\n"))); - return false; - } - - // continue to ensure interface is UP - } - - // check existence of this IP address in the interface list - bool found = false; - m_netif = nullptr; - for (auto a : addrList) - if (ipAddress == a.addr()) - { - if (a.ifUp()) - { - found = true; - m_netif = a.interface(); - break; - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] found interface for IP '%s' but it is not UP\n"), ipAddress.toString().c_str());); - } - if (!found) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] interface defined by IP '%s' not found\n"), ipAddress.toString().c_str());); - return false; - } - - //// done selecting the interface - - if (m_netif->num == STATION_IF) - { - - m_GotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP & pEvent) - { - (void) pEvent; - // Ensure that _restart() runs in USER context - schedule_function([this]() - { - MDNSResponder::_restart(); - }); - }); - - m_DisconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected & pEvent) - { - (void) pEvent; - // Ensure that _restart() runs in USER context - schedule_function([this]() - { - MDNSResponder::_restart(); - }); - }); - } - - bResult = _restart(); - } - DEBUG_EX_ERR(if (!bResult) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] begin: FAILED for '%s'!\n"), (p_pcHostname ? : "-")); - }); - } - else - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] begin: Ignoring multiple calls to begin (Ignored host domain: '%s')!\n"), (p_pcHostname ? : "-"));); - } - return bResult; -} - -/* - MDNSResponder::close - - Ends the MDNS responder. - Announced services are unannounced (by multicasting a goodbye message) - -*/ -bool MDNSResponder::close(void) -{ - bool bResult = false; - - if (0 != m_pUDPContext) - { - m_GotIPHandler.reset(); // reset WiFi event callbacks. - m_DisconnectedHandler.reset(); - - _announce(false, true); - _resetProbeStatus(false); // Stop probing - _releaseServiceQueries(); - _releaseUDPContext(); - _releaseHostname(); - - bResult = true; - } - else - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] close: Ignoring call to close!\n"));); - } - return bResult; -} - -/* - MDNSResponder::end - - Ends the MDNS responder. - for compatibility with esp32 - -*/ - -bool MDNSResponder::end(void) -{ - return close(); -} - -/* - MDNSResponder::setHostname - - Replaces the current hostname and restarts probing. - For services without own instance name (when the host name was used a instance - name), the instance names are replaced also (and the probing is restarted). - -*/ -bool MDNSResponder::setHostname(const char* p_pcHostname) -{ - - bool bResult = false; - - if (_setHostname(p_pcHostname)) - { - m_HostProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart; - - // Replace 'auto-set' service names - bResult = true; - for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) - { - if (pService->m_bAutoName) - { - bResult = pService->setName(p_pcHostname); - pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart; - } - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setHostname: FAILED for '%s'!\n"), (p_pcHostname ? : "-")); - }); - return bResult; -} - -/* - MDNSResponder::setHostname (LEGACY) -*/ -bool MDNSResponder::setHostname(const String& p_strHostname) -{ - - return setHostname(p_strHostname.c_str()); -} - - -/* - SERVICES -*/ - -/* - MDNSResponder::addService - - Add service; using hostname if no name is explicitly provided for the service - The usual '_' underline, which is prepended to service and protocol, eg. _http, - may be given. If not, it is added automatically. - -*/ -MDNSResponder::hMDNSService MDNSResponder::addService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port) -{ - - hMDNSService hResult = 0; - - if (((!p_pcName) || // NO name OR - (MDNS_DOMAIN_LABEL_MAXLENGTH >= os_strlen(p_pcName))) && // Fitting name - (p_pcService) && - (MDNS_SERVICE_NAME_LENGTH >= os_strlen(p_pcService)) && - (p_pcProtocol) && - ((MDNS_SERVICE_PROTOCOL_LENGTH - 1) != os_strlen(p_pcProtocol)) && - (p_u16Port)) - { - - if (!_findService((p_pcName ? : m_pcHostname), p_pcService, p_pcProtocol)) // Not already used - { - if (0 != (hResult = (hMDNSService)_allocService(p_pcName, p_pcService, p_pcProtocol, p_u16Port))) - { - - // Start probing - ((stcMDNSService*)hResult)->m_ProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart; - } - } - } // else: bad arguments - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addService: %s to add '%s.%s.%s'!\n"), (hResult ? "Succeeded" : "FAILED"), (p_pcName ? : "-"), p_pcService, p_pcProtocol);); - DEBUG_EX_ERR(if (!hResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addService: FAILED to add '%s.%s.%s'!\n"), (p_pcName ? : "-"), p_pcService, p_pcProtocol); - }); - return hResult; -} - -/* - MDNSResponder::removeService - - Unanounce a service (by sending a goodbye message) and remove it - from the MDNS responder - -*/ -bool MDNSResponder::removeService(const MDNSResponder::hMDNSService p_hService) -{ - - stcMDNSService* pService = 0; - bool bResult = (((pService = _findService(p_hService))) && - (_announceService(*pService, false)) && - (_releaseService(pService))); - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeService: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::removeService -*/ -bool MDNSResponder::removeService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol) -{ - - return removeService((hMDNSService)_findService((p_pcName ? : m_pcHostname), p_pcService, p_pcProtocol)); -} - -/* - MDNSResponder::addService (LEGACY) -*/ -bool MDNSResponder::addService(const String& p_strService, - const String& p_strProtocol, - uint16_t p_u16Port) -{ - - return (0 != addService(m_pcHostname, p_strService.c_str(), p_strProtocol.c_str(), p_u16Port)); -} - -/* - MDNSResponder::setServiceName -*/ -bool MDNSResponder::setServiceName(const MDNSResponder::hMDNSService p_hService, - const char* p_pcInstanceName) -{ - - stcMDNSService* pService = 0; - bool bResult = (((!p_pcInstanceName) || - (MDNS_DOMAIN_LABEL_MAXLENGTH >= os_strlen(p_pcInstanceName))) && - ((pService = _findService(p_hService))) && - (pService->setName(p_pcInstanceName)) && - ((pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_ReadyToStart))); - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setServiceName: FAILED for '%s'!\n"), (p_pcInstanceName ? : "-")); - }); - return bResult; -} - -/* - SERVICE TXT -*/ - -/* - MDNSResponder::addServiceTxt - - Add a static service TXT item ('Key'='Value') to a service. - -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue) -{ - - hMDNSTxt hTxt = 0; - stcMDNSService* pService = _findService(p_hService); - if (pService) - { - hTxt = (hMDNSTxt)_addServiceTxt(pService, p_pcKey, p_pcValue, false); - } - DEBUG_EX_ERR(if (!hTxt) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addServiceTxt: FAILED for '%s=%s'!\n"), (p_pcKey ? : "-"), (p_pcValue ? : "-")); - }); - return hTxt; -} - -/* - MDNSResponder::addServiceTxt (uint32_t) - - Formats: http://www.cplusplus.com/reference/cstdio/printf/ -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - char acBuffer[32]; *acBuffer = 0; - sprintf(acBuffer, "%u", p_u32Value); - - return addServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (uint16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - char acBuffer[16]; *acBuffer = 0; - sprintf(acBuffer, "%hu", p_u16Value); - - return addServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (uint8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - char acBuffer[8]; *acBuffer = 0; - sprintf(acBuffer, "%hhu", p_u8Value); - - return addServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (int32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value) -{ - char acBuffer[32]; *acBuffer = 0; - sprintf(acBuffer, "%i", p_i32Value); - - return addServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (int16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value) -{ - char acBuffer[16]; *acBuffer = 0; - sprintf(acBuffer, "%hi", p_i16Value); - - return addServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addServiceTxt (int8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value) -{ - char acBuffer[8]; *acBuffer = 0; - sprintf(acBuffer, "%hhi", p_i8Value); - - return addServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::removeServiceTxt - - Remove a static service TXT item from a service. -*/ -bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSService p_hService, - const MDNSResponder::hMDNSTxt p_hTxt) -{ - - bool bResult = false; - - stcMDNSService* pService = _findService(p_hService); - if (pService) - { - stcMDNSServiceTxt* pTxt = _findServiceTxt(pService, p_hTxt); - if (pTxt) - { - bResult = _releaseServiceTxt(pService, pTxt); - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeServiceTxt: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::removeServiceTxt -*/ -bool MDNSResponder::removeServiceTxt(const MDNSResponder::hMDNSService p_hService, - const char* p_pcKey) -{ - - bool bResult = false; - - stcMDNSService* pService = _findService(p_hService); - if (pService) - { - stcMDNSServiceTxt* pTxt = _findServiceTxt(pService, p_pcKey); - if (pTxt) - { - bResult = _releaseServiceTxt(pService, pTxt); - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeServiceTxt: FAILED for '%s'!\n"), (p_pcKey ? : "-")); - }); - return bResult; -} - -/* - MDNSResponder::removeServiceTxt -*/ -bool MDNSResponder::removeServiceTxt(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - const char* p_pcKey) -{ - - bool bResult = false; - - stcMDNSService* pService = _findService((p_pcName ? : m_pcHostname), p_pcService, p_pcProtocol); - if (pService) - { - stcMDNSServiceTxt* pTxt = _findServiceTxt(pService, p_pcKey); - if (pTxt) - { - bResult = _releaseServiceTxt(pService, pTxt); - } - } - return bResult; -} - -/* - MDNSResponder::addServiceTxt (LEGACY) -*/ -bool MDNSResponder::addServiceTxt(const char* p_pcService, - const char* p_pcProtocol, - const char* p_pcKey, - const char* p_pcValue) -{ - - return (0 != _addServiceTxt(_findService(m_pcHostname, p_pcService, p_pcProtocol), p_pcKey, p_pcValue, false)); -} - -/* - MDNSResponder::addServiceTxt (LEGACY) -*/ -bool MDNSResponder::addServiceTxt(const String& p_strService, - const String& p_strProtocol, - const String& p_strKey, - const String& p_strValue) -{ - - return (0 != _addServiceTxt(_findService(m_pcHostname, p_strService.c_str(), p_strProtocol.c_str()), p_strKey.c_str(), p_strValue.c_str(), false)); -} - -/* - MDNSResponder::setDynamicServiceTxtCallback (global) - - Set a global callback for dynamic service TXT items. The callback is called, whenever - service TXT items are needed. - -*/ -bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::MDNSDynamicServiceTxtCallbackFunc p_fnCallback) -{ - - m_fnServiceTxtCallback = p_fnCallback; - - return true; -} - -/* - MDNSResponder::setDynamicServiceTxtCallback (service specific) - - Set a service specific callback for dynamic service TXT items. The callback is called, whenever - service TXT items are needed for the given service. - -*/ -bool MDNSResponder::setDynamicServiceTxtCallback(MDNSResponder::hMDNSService p_hService, - MDNSResponder::MDNSDynamicServiceTxtCallbackFunc p_fnCallback) -{ - - bool bResult = false; - - stcMDNSService* pService = _findService(p_hService); - if (pService) - { - pService->m_fnTxtCallback = p_fnCallback; - - bResult = true; - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] setDynamicServiceTxtCallback: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::addDynamicServiceTxt -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addDynamicServiceTxt (%s=%s)\n"), p_pcKey, p_pcValue);); - - hMDNSTxt hTxt = 0; - - stcMDNSService* pService = _findService(p_hService); - if (pService) - { - hTxt = _addServiceTxt(pService, p_pcKey, p_pcValue, true); - } - DEBUG_EX_ERR(if (!hTxt) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addDynamicServiceTxt: FAILED for '%s=%s'!\n"), (p_pcKey ? : "-"), (p_pcValue ? : "-")); - }); - return hTxt; -} - -/* - MDNSResponder::addDynamicServiceTxt (uint32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - - char acBuffer[32]; *acBuffer = 0; - sprintf(acBuffer, "%u", p_u32Value); - - return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (uint16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - - char acBuffer[16]; *acBuffer = 0; - sprintf(acBuffer, "%hu", p_u16Value); - - return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (uint8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - - char acBuffer[8]; *acBuffer = 0; - sprintf(acBuffer, "%hhu", p_u8Value); - - return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (int32_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value) -{ - - char acBuffer[32]; *acBuffer = 0; - sprintf(acBuffer, "%i", p_i32Value); - - return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (int16_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value) -{ - - char acBuffer[16]; *acBuffer = 0; - sprintf(acBuffer, "%hi", p_i16Value); - - return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); -} - -/* - MDNSResponder::addDynamicServiceTxt (int8_t) -*/ -MDNSResponder::hMDNSTxt MDNSResponder::addDynamicServiceTxt(MDNSResponder::hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value) -{ - - char acBuffer[8]; *acBuffer = 0; - sprintf(acBuffer, "%hhi", p_i8Value); - - return addDynamicServiceTxt(p_hService, p_pcKey, acBuffer); -} - - -/** - STATIC SERVICE QUERY (LEGACY) -*/ - -/* - MDNSResponder::queryService - - Perform a (blocking) static service query. - The arrived answers can be queried by calling: - - answerHostname (or 'hostname') - - answerIP (or 'IP') - - answerPort (or 'port') - -*/ -uint32_t MDNSResponder::queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) -{ - if (0 == m_pUDPContext) - { - // safeguard against misuse - return 0; - } - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService '%s.%s'\n"), p_pcService, p_pcProtocol);); - - uint32_t u32Result = 0; - - stcMDNSServiceQuery* pServiceQuery = 0; - if ((p_pcService) && - (os_strlen(p_pcService)) && - (p_pcProtocol) && - (os_strlen(p_pcProtocol)) && - (p_u16Timeout) && - (_removeLegacyServiceQuery()) && - ((pServiceQuery = _allocServiceQuery())) && - (_buildDomainForService(p_pcService, p_pcProtocol, pServiceQuery->m_ServiceTypeDomain))) - { - - pServiceQuery->m_bLegacyQuery = true; - - if (_sendMDNSServiceQuery(*pServiceQuery)) - { - // Wait for answers to arrive - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService: Waiting %u ms for answers...\n"), p_u16Timeout);); - delay(p_u16Timeout); - - // All answers should have arrived by now -> stop adding new answers - pServiceQuery->m_bAwaitingAnswers = false; - u32Result = pServiceQuery->answerCount(); - } - else // FAILED to send query - { - _removeServiceQuery(pServiceQuery); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] queryService: INVALID input data!\n"));); - } - return u32Result; -} - -/* - MDNSResponder::removeQuery - - Remove the last static service query (and all answers). - -*/ -bool MDNSResponder::removeQuery(void) -{ - - return _removeLegacyServiceQuery(); -} - -/* - MDNSResponder::queryService (LEGACY) -*/ -uint32_t MDNSResponder::queryService(const String& p_strService, - const String& p_strProtocol) -{ - - return queryService(p_strService.c_str(), p_strProtocol.c_str()); -} - -/* - MDNSResponder::answerHostname -*/ -const char* MDNSResponder::answerHostname(const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery(); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - - if ((pSQAnswer) && - (pSQAnswer->m_HostDomain.m_u16NameLength) && - (!pSQAnswer->m_pcHostDomain)) - { - - char* pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); - if (pcHostDomain) - { - pSQAnswer->m_HostDomain.c_str(pcHostDomain); - } - } - return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); -} - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::answerIP -*/ -IPAddress MDNSResponder::answerIP(const uint32_t p_u32AnswerIndex) -{ - - const stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery(); - const stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - const stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address = (((pSQAnswer) && (pSQAnswer->m_pIP4Addresses)) ? pSQAnswer->IP4AddressAtIndex(0) : 0); - return (pIP4Address ? pIP4Address->m_IPAddress : IPAddress()); -} -#endif - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::answerIP6 -*/ -IPAddress MDNSResponder::answerIP6(const uint32_t p_u32AnswerIndex) -{ - - const stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery(); - const stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - const stcMDNSServiceQuery::stcAnswer::stcIP6Address* pIP6Address = (((pSQAnswer) && (pSQAnswer->m_pIP6Addresses)) ? pSQAnswer->IP6AddressAtIndex(0) : 0); - return (pIP6Address ? pIP6Address->m_IPAddress : IP6Address()); -} -#endif - -/* - MDNSResponder::answerPort -*/ -uint16_t MDNSResponder::answerPort(const uint32_t p_u32AnswerIndex) -{ - - const stcMDNSServiceQuery* pServiceQuery = _findLegacyServiceQuery(); - const stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->m_u16Port : 0); -} - -/* - MDNSResponder::hostname (LEGACY) -*/ -String MDNSResponder::hostname(const uint32_t p_u32AnswerIndex) -{ - - return String(answerHostname(p_u32AnswerIndex)); -} - -/* - MDNSResponder::IP (LEGACY) -*/ -IPAddress MDNSResponder::IP(const uint32_t p_u32AnswerIndex) -{ - - return answerIP(p_u32AnswerIndex); -} - -/* - MDNSResponder::port (LEGACY) -*/ -uint16_t MDNSResponder::port(const uint32_t p_u32AnswerIndex) -{ - - return answerPort(p_u32AnswerIndex); -} - - -/** - DYNAMIC SERVICE QUERY -*/ - -/* - MDNSResponder::installServiceQuery - - Add a dynamic service query and a corresponding callback to the MDNS responder. - The callback will be called for every answer update. - The answers can also be queried by calling: - - answerServiceDomain - - answerHostDomain - - answerIP4Address/answerIP6Address - - answerPort - - answerTxts - -*/ -MDNSResponder::hMDNSServiceQuery MDNSResponder::installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - MDNSResponder::MDNSServiceQueryCallbackFunc p_fnCallback) -{ - hMDNSServiceQuery hResult = 0; - - stcMDNSServiceQuery* pServiceQuery = 0; - if ((p_pcService) && - (os_strlen(p_pcService)) && - (p_pcProtocol) && - (os_strlen(p_pcProtocol)) && - (p_fnCallback) && - ((pServiceQuery = _allocServiceQuery())) && - (_buildDomainForService(p_pcService, p_pcProtocol, pServiceQuery->m_ServiceTypeDomain))) - { - - pServiceQuery->m_fnCallback = p_fnCallback; - pServiceQuery->m_bLegacyQuery = false; - - if (_sendMDNSServiceQuery(*pServiceQuery)) - { - pServiceQuery->m_u8SentCount = 1; - pServiceQuery->m_ResendTimeout.reset(MDNS_DYNAMIC_QUERY_RESEND_DELAY); - - hResult = (hMDNSServiceQuery)pServiceQuery; - } - else - { - _removeServiceQuery(pServiceQuery); - } - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] installServiceQuery: %s for '%s.%s'!\n\n"), (hResult ? "Succeeded" : "FAILED"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); - DEBUG_EX_ERR(if (!hResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] installServiceQuery: FAILED for '%s.%s'!\n\n"), (p_pcService ? : "-"), (p_pcProtocol ? : "-")); - }); - return hResult; -} - -/* - MDNSResponder::removeServiceQuery - - Remove a dynamic service query (and all collected answers) from the MDNS responder - -*/ -bool MDNSResponder::removeServiceQuery(MDNSResponder::hMDNSServiceQuery p_hServiceQuery) -{ - - stcMDNSServiceQuery* pServiceQuery = 0; - bool bResult = (((pServiceQuery = _findServiceQuery(p_hServiceQuery))) && - (_removeServiceQuery(pServiceQuery))); - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] removeServiceQuery: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::answerCount -*/ -uint32_t MDNSResponder::answerCount(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - return (pServiceQuery ? pServiceQuery->answerCount() : 0); -} - -std::vector<MDNSResponder::MDNSServiceInfo> MDNSResponder::answerInfo(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery) -{ - std::vector<MDNSResponder::MDNSServiceInfo> tempVector; - for (uint32_t i = 0; i < answerCount(p_hServiceQuery); i++) - { - tempVector.emplace_back(*this, p_hServiceQuery, i); - } - return tempVector; -} - -/* - MDNSResponder::answerServiceDomain - - Returns the domain for the given service. - If not already existing, the string is allocated, filled and attached to the answer. - -*/ -const char* MDNSResponder::answerServiceDomain(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcServiceDomain (if not already done) - if ((pSQAnswer) && - (pSQAnswer->m_ServiceDomain.m_u16NameLength) && - (!pSQAnswer->m_pcServiceDomain)) - { - - pSQAnswer->m_pcServiceDomain = pSQAnswer->allocServiceDomain(pSQAnswer->m_ServiceDomain.c_strLength()); - if (pSQAnswer->m_pcServiceDomain) - { - pSQAnswer->m_ServiceDomain.c_str(pSQAnswer->m_pcServiceDomain); - } - } - return (pSQAnswer ? pSQAnswer->m_pcServiceDomain : 0); -} - -/* - MDNSResponder::hasAnswerHostDomain -*/ -bool MDNSResponder::hasAnswerHostDomain(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_HostDomainAndPort)); -} - -/* - MDNSResponder::answerHostDomain - - Returns the host domain for the given service. - If not already existing, the string is allocated, filled and attached to the answer. - -*/ -const char* MDNSResponder::answerHostDomain(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcHostDomain (if not already done) - if ((pSQAnswer) && - (pSQAnswer->m_HostDomain.m_u16NameLength) && - (!pSQAnswer->m_pcHostDomain)) - { - - pSQAnswer->m_pcHostDomain = pSQAnswer->allocHostDomain(pSQAnswer->m_HostDomain.c_strLength()); - if (pSQAnswer->m_pcHostDomain) - { - pSQAnswer->m_HostDomain.c_str(pSQAnswer->m_pcHostDomain); - } - } - return (pSQAnswer ? pSQAnswer->m_pcHostDomain : 0); -} - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::hasAnswerIP4Address -*/ -bool MDNSResponder::hasAnswerIP4Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_IP4Address)); -} - -/* - MDNSResponder::answerIP4AddressCount -*/ -uint32_t MDNSResponder::answerIP4AddressCount(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->IP4AddressCount() : 0); -} - -/* - MDNSResponder::answerIP4Address -*/ -IPAddress MDNSResponder::answerIP4Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address = (pSQAnswer ? pSQAnswer->IP4AddressAtIndex(p_u32AddressIndex) : 0); - return (pIP4Address ? pIP4Address->m_IPAddress : IPAddress()); -} -#endif - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::hasAnswerIP6Address -*/ -bool MDNSResponder::hasAnswerIP6Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_HostIP6Address)); -} - -/* - MDNSResponder::answerIP6AddressCount -*/ -uint32_t MDNSResponder::answerIP6AddressCount(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->IP6AddressCount() : 0); -} - -/* - MDNSResponder::answerIP6Address -*/ -IPAddress MDNSResponder::answerIP6Address(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - stcMDNSServiceQuery::stcAnswer::stcIP6Address* pIP6Address = (pSQAnswer ? pSQAnswer->IP6AddressAtIndex(p_u32AddressIndex) : 0); - return (pIP6Address ? pIP6Address->m_IPAddress : IPAddress()); -} -#endif - -/* - MDNSResponder::hasAnswerPort -*/ -bool MDNSResponder::hasAnswerPort(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_HostDomainAndPort)); -} - -/* - MDNSResponder::answerPort -*/ -uint16_t MDNSResponder::answerPort(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return (pSQAnswer ? pSQAnswer->m_u16Port : 0); -} - -/* - MDNSResponder::hasAnswerTxts -*/ -bool MDNSResponder::hasAnswerTxts(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - return ((pSQAnswer) && - (pSQAnswer->m_u32ContentFlags & ServiceQueryAnswerType_Txts)); -} - -/* - MDNSResponder::answerTxts - - Returns all TXT items for the given service as a ';'-separated string. - If not already existing; the string is alloced, filled and attached to the answer. - -*/ -const char* MDNSResponder::answerTxts(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcTxts (if not already done) - if ((pSQAnswer) && - (pSQAnswer->m_Txts.m_pTxts) && - (!pSQAnswer->m_pcTxts)) - { - - pSQAnswer->m_pcTxts = pSQAnswer->allocTxts(pSQAnswer->m_Txts.c_strLength()); - if (pSQAnswer->m_pcTxts) - { - pSQAnswer->m_Txts.c_str(pSQAnswer->m_pcTxts); - } - } - return (pSQAnswer ? pSQAnswer->m_pcTxts : 0); -} - -/* - PROBING -*/ - -/* - MDNSResponder::setProbeResultCallback - - Set a global callback for probe results. The callback is called, when probing - for the host domain (or a service domain, without specific probe result callback) - failes or succeedes. - In the case of failure, the domain name should be changed via 'setHostname' or 'setServiceName'. - When succeeded, the host or service domain will be announced by the MDNS responder. - -*/ -bool MDNSResponder::setHostProbeResultCallback(MDNSResponder::MDNSHostProbeFn p_fnCallback) -{ - - m_HostProbeInformation.m_fnHostProbeResultCallback = p_fnCallback; - - return true; -} - -bool MDNSResponder::setHostProbeResultCallback(MDNSHostProbeFn1 pfn) -{ - using namespace std::placeholders; - return setHostProbeResultCallback([this, pfn](const char* p_pcDomainName, bool p_bProbeResult) - { - pfn(*this, p_pcDomainName, p_bProbeResult); - }); -} - -/* - MDNSResponder::setServiceProbeResultCallback - - Set a service specific callback for probe results. The callback is called, when probing - for the service domain failes or succeedes. - In the case of failure, the service name should be changed via 'setServiceName'. - When succeeded, the service domain will be announced by the MDNS responder. - -*/ -bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService, - MDNSResponder::MDNSServiceProbeFn p_fnCallback) -{ - - bool bResult = false; - - stcMDNSService* pService = _findService(p_hService); - if (pService) - { - pService->m_ProbeInformation.m_fnServiceProbeResultCallback = p_fnCallback; - - bResult = true; - } - return bResult; -} - -bool MDNSResponder::setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService, - MDNSResponder::MDNSServiceProbeFn1 p_fnCallback) -{ - using namespace std::placeholders; - return setServiceProbeResultCallback(p_hService, [this, p_fnCallback](const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) - { - p_fnCallback(*this, p_pcServiceName, p_hMDNSService, p_bProbeResult); - }); -} - - -/* - MISC -*/ - -/* - MDNSResponder::notifyAPChange - - Should be called, whenever the AP for the MDNS responder changes. - A bit of this is caught by the event callbacks installed in the constructor. - -*/ -bool MDNSResponder::notifyAPChange(void) -{ - - return _restart(); -} - -/* - MDNSResponder::update - - Should be called in every 'loop'. - -*/ -bool MDNSResponder::update(void) -{ - - if (m_bPassivModeEnabled) - { - m_bPassivModeEnabled = false; - } - return _process(true); -} - -/* - MDNSResponder::announce - - Should be called, if the 'configuration' changes. Mainly this will be changes in the TXT items... -*/ -bool MDNSResponder::announce(void) -{ - - return (_announce(true, true)); -} - -/* - MDNSResponder::enableArduino - - Enable the OTA update service. - -*/ -MDNSResponder::hMDNSService MDNSResponder::enableArduino(uint16_t p_u16Port, - bool p_bAuthUpload /*= false*/) -{ - - hMDNSService hService = addService(0, "arduino", "tcp", p_u16Port); - if (hService) - { - if ((!addServiceTxt(hService, "tcp_check", "no")) || - (!addServiceTxt(hService, "ssh_upload", "no")) || - (!addServiceTxt(hService, "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD))) || - (!addServiceTxt(hService, "auth_upload", (p_bAuthUpload) ? "yes" : "no"))) - { - - removeService(hService); - hService = 0; - } - } - return hService; -} - - -} //namespace MDNSImplementation - -} //namespace esp8266 - - diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.h b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.h deleted file mode 100644 index fe02560aec..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS.h +++ /dev/null @@ -1,1461 +0,0 @@ -/* - LEAmDNS.h - (c) 2018, LaborEtArs - - Version 0.9 beta - - Some notes (from LaborEtArs, 2018): - Essentially, this is an rewrite of the original EPS8266 Multicast DNS code (ESP8266mDNS). - The target of this rewrite was to keep the existing interface as stable as possible while - adding and extending the supported set of mDNS features. - A lot of the additions were basicly taken from Erik Ekman's lwIP mdns app code. - - Supported mDNS features (in some cases somewhat limited): - - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service - - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented - - Probing host and service domains for uniqueness in the local network - - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak) - - Announcing available services after successful probing - - Using fixed service TXT items or - - Using dynamic service TXT items for presented services (via callback) - - Remove services (and un-announcing them to the observers by sending goodbye-messages) - - Static queries for DNS-SD services (creating a fixed answer set after a certain timeout period) - - Dynamic queries for DNS-SD services with cached and updated answers and user notifications - - - Usage: - In most cases, this implementation should work as a 'drop-in' replacement for the original - ESP8266 Multicast DNS code. Adjustments to the existing code would only be needed, if some - of the new features should be used. - - For presenting services: - In 'setup()': - Install a callback for the probing of host (and service) domains via 'MDNS.setProbeResultCallback(probeResultCallback, &userData);' - Register DNS-SD services with 'MDNSResponder::hMDNSService hService = MDNS.addService("MyESP", "http", "tcp", 5000);' - (Install additional callbacks for the probing of these service domains via 'MDNS.setServiceProbeResultCallback(hService, probeResultCallback, &userData);') - Add service TXT items with 'MDNS.addServiceTxt(hService, "c#", "1");' or by installing a service TXT callback - using 'MDNS.setDynamicServiceTxtCallback(dynamicServiceTxtCallback, &userData);' or service specific - 'MDNS.setDynamicServiceTxtCallback(hService, dynamicServiceTxtCallback, &userData);' - Call MDNS.begin("MyHostname"); - - In 'probeResultCallback(MDNSResponder* p_MDNSResponder, const char* p_pcDomain, MDNSResponder:hMDNSService p_hService, bool p_bProbeResult, void* p_pUserdata)': - Check the probe result and update the host or service domain name if the probe failed - - In 'dynamicServiceTxtCallback(MDNSResponder* p_MDNSResponder, const hMDNSService p_hService, void* p_pUserdata)': - Add dynamic TXT items by calling 'MDNS.addDynamicServiceTxt(p_hService, "c#", "1");' - - In loop(): - Call 'MDNS.update();' - - - For querying services: - Static: - Call 'uint32_t u32AnswerCount = MDNS.queryService("http", "tcp");' - Iterate answers by: 'for (uint32_t u=0; u<u32AnswerCount; ++u) { const char* pHostname = MDNS.answerHostname(u); }' - You should call MDNS.removeQuery() sometimes later (when the answers are nott needed anymore) - - Dynamic: - Install a dynamic query by calling 'DNSResponder::hMDNSServiceQuery hServiceQuery = MDNS.installServiceQuery("http", "tcp", serviceQueryCallback, &userData);' - The callback 'serviceQueryCallback(MDNSResponder* p_MDNSResponder, const hMDNSServiceQuery p_hServiceQuery, uint32_t p_u32AnswerIndex, - enuServiceQueryAnswerType p_ServiceQueryAnswerType, bool p_bSetContent, void* p_pUserdata)' - is called for any change in the answer set. - Call 'MDNS.removeServiceQuery(hServiceQuery);' when the answers are not needed anymore - - - Reference: - Used mDNS messages: - A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 - AAAA (0x1C): eg. esp8266.local AAAA OP TTL 1234:5678::90 - PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local - PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local - PTR (0x0C, IP4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local - PTR (0x0C, IP6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local - SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local - TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 - - Some NOT used message types: - OPT (0x29): eDNS - NSEC (0x2F): DNSSEC - - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#ifndef MDNS_H -#define MDNS_H - -#include <functional> // for UdpContext.h -#include "WiFiUdp.h" -#include "lwip/udp.h" -#include "debug.h" -#include "include/UdpContext.h" -#include <limits> -#include <PolledTimeout.h> -#include <map> - - -#include "ESP8266WiFi.h" - - -namespace esp8266 -{ - -/** - LEAmDNS -*/ -namespace MDNSImplementation -{ - -//this should be defined at build time -#ifndef ARDUINO_BOARD -#define ARDUINO_BOARD "generic" -#endif - -#define MDNS_IP4_SUPPORT -//#define MDNS_IP6_SUPPORT - - -#ifdef MDNS_IP4_SUPPORT -#define MDNS_IP4_SIZE 4 -#endif -#ifdef MDNS_IP6_SUPPORT -#define MDNS_IP6_SIZE 16 -#endif -/* - Maximum length for all service txts for one service -*/ -#define MDNS_SERVICE_TXT_MAXLENGTH 1300 -/* - Maximum length for a full domain name eg. MyESP._http._tcp.local -*/ -#define MDNS_DOMAIN_MAXLENGTH 256 -/* - Maximum length of on label in a domain name (length info fits into 6 bits) -*/ -#define MDNS_DOMAIN_LABEL_MAXLENGTH 63 -/* - Maximum length of a service name eg. http -*/ -#define MDNS_SERVICE_NAME_LENGTH 15 -/* - Maximum length of a service protocol name eg. tcp -*/ -#define MDNS_SERVICE_PROTOCOL_LENGTH 3 -/* - Default timeout for static service queries -*/ -#define MDNS_QUERYSERVICES_WAIT_TIME 1000 - - -/** - MDNSResponder -*/ -class MDNSResponder -{ -public: - /* INTERFACE */ - MDNSResponder(void); - virtual ~MDNSResponder(void); - - // Start the MDNS responder by setting the default hostname - // Later call MDNS::update() in every 'loop' to run the process loop - // (probing, announcing, responding, ...) - // if interfaceAddress is not specified, default interface is STA, or AP when STA is not set - bool begin(const char* p_pcHostname, const IPAddress& p_IPAddress = INADDR_ANY, uint32_t p_u32TTL = 120 /*ignored*/); - bool begin(const String& p_strHostname, const IPAddress& p_IPAddress = INADDR_ANY, uint32_t p_u32TTL = 120 /*ignored*/) - { - return begin(p_strHostname.c_str(), p_IPAddress, p_u32TTL); - } - - // Finish MDNS processing - bool close(void); - // for esp32 compatability - bool end(void); - // Change hostname (probing is restarted) - bool setHostname(const char* p_pcHostname); - // for compatibility... - bool setHostname(const String& p_strHostname); - - bool isRunning(void) - { - return (m_pUDPContext != 0); - } - - /** - hMDNSService (opaque handle to access the service) - */ - typedef const void* hMDNSService; - - // Add a new service to the MDNS responder. If no name (instance name) is given (p_pcName = 0) - // the current hostname is used. If the hostname is changed later, the instance names for - // these 'auto-named' services are changed to the new name also (and probing is restarted). - // The usual '_' before p_pcService (eg. http) and protocol (eg. tcp) may be given. - hMDNSService addService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port); - // Removes a service from the MDNS responder - bool removeService(const hMDNSService p_hService); - bool removeService(const char* p_pcInstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol); - // for compatibility... - bool addService(const String& p_strServiceName, - const String& p_strProtocol, - uint16_t p_u16Port); - - - // Change the services instance name (and restart probing). - bool setServiceName(const hMDNSService p_hService, - const char* p_pcInstanceName); - //for compatibility - //Warning: this has the side effect of changing the hostname. - //TODO: implement instancename different from hostname - void setInstanceName(const char* p_pcHostname) - { - setHostname(p_pcHostname); - } - // for esp32 compatibilty - void setInstanceName(const String& s_pcHostname) - { - setInstanceName(s_pcHostname.c_str()); - } - - /** - hMDNSTxt (opaque handle to access the TXT items) - */ - typedef void* hMDNSTxt; - - // 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); - - // Remove an existing (static) MDNS TXT item from the service - bool removeServiceTxt(const hMDNSService p_hService, - const hMDNSTxt p_hTxt); - bool removeServiceTxt(const hMDNSService p_hService, - const char* p_pcKey); - bool removeServiceTxt(const char* p_pcinstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol, - const char* p_pcKey); - // for compatibility... - bool addServiceTxt(const char* p_pcService, - const char* p_pcProtocol, - const char* p_pcKey, - const char* p_pcValue); - bool addServiceTxt(const String& p_strService, - const String& p_strProtocol, - const String& p_strKey, - const String& p_strValue); - - /** - MDNSDynamicServiceTxtCallbackFn - Callback function for dynamic MDNS TXT items - */ - - typedef std::function<void(const hMDNSService p_hService)> MDNSDynamicServiceTxtCallbackFunc; - - // Set a global callback for dynamic MDNS TXT items. The callback function is called - // every time, a TXT item is needed for one of the installed services. - bool setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFunc p_fnCallback); - // Set a service specific callback for dynamic MDNS TXT items. The callback function - // is called every time, a TXT item is needed for the given service. - bool setDynamicServiceTxtCallback(const hMDNSService p_hService, - MDNSDynamicServiceTxtCallbackFunc p_fnCallback); - - // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service - // Dynamic TXT items are removed right after one-time use. So they need to be added - // every time the value s needed (via callback). - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value); - - // Perform a (static) service query. The function returns after p_u16Timeout milliseconds - // The answers (the number of received answers is returned) can be retrieved by calling - // - answerHostname (or hostname) - // - answerIP (or IP) - // - answerPort (or port) - uint32_t queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout = MDNS_QUERYSERVICES_WAIT_TIME); - bool removeQuery(void); - // for compatibility... - uint32_t queryService(const String& p_strService, - const String& p_strProtocol); - - const char* answerHostname(const uint32_t p_u32AnswerIndex); - IPAddress answerIP(const uint32_t p_u32AnswerIndex); - uint16_t answerPort(const uint32_t p_u32AnswerIndex); - // for compatibility... - String hostname(const uint32_t p_u32AnswerIndex); - IPAddress IP(const uint32_t p_u32AnswerIndex); - uint16_t port(const uint32_t p_u32AnswerIndex); - - /** - hMDNSServiceQuery (opaque handle to access dynamic service queries) - */ - typedef const void* hMDNSServiceQuery; - - /** - enuServiceQueryAnswerType - */ - typedef enum _enuServiceQueryAnswerType - { - ServiceQueryAnswerType_ServiceDomain = (1 << 0), // Service instance name - ServiceQueryAnswerType_HostDomainAndPort = (1 << 1), // Host domain and service port - ServiceQueryAnswerType_Txts = (1 << 2), // TXT items -#ifdef MDNS_IP4_SUPPORT - ServiceQueryAnswerType_IP4Address = (1 << 3), // IP4 address -#endif -#ifdef MDNS_IP6_SUPPORT - ServiceQueryAnswerType_IP6Address = (1 << 4), // IP6 address -#endif - } enuServiceQueryAnswerType; - - enum class AnswerType : uint32_t - { - Unknown = 0, - ServiceDomain = ServiceQueryAnswerType_ServiceDomain, - HostDomainAndPort = ServiceQueryAnswerType_HostDomainAndPort, - Txt = ServiceQueryAnswerType_Txts, -#ifdef MDNS_IP4_SUPPORT - IP4Address = ServiceQueryAnswerType_IP4Address, -#endif -#ifdef MDNS_IP6_SUPPORT - IP6Address = ServiceQueryAnswerType_IP6Address, -#endif - }; - - /** - MDNSServiceQueryCallbackFn - Callback function for received answers for dynamic service queries - */ - struct MDNSServiceInfo; // forward declaration - typedef std::function<void(const MDNSServiceInfo& mdnsServiceInfo, - AnswerType answerType, // flag for the updated answer item - bool p_bSetContent // true: Answer component set, false: component deleted - )> MDNSServiceQueryCallbackFunc; - - // Install a dynamic service query. For every received answer (part) the given callback - // function is called. The query will be updated every time, the TTL for an answer - // has timed-out. - // The answers can also be retrieved by calling - // - answerCount - // - answerServiceDomain - // - hasAnswerHostDomain/answerHostDomain - // - hasAnswerIP4Address/answerIP4Address - // - hasAnswerIP6Address/answerIP6Address - // - hasAnswerPort/answerPort - // - hasAnswerTxts/answerTxts - hMDNSServiceQuery installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - MDNSServiceQueryCallbackFunc p_fnCallback); - // Remove a dynamic service query - bool removeServiceQuery(hMDNSServiceQuery p_hServiceQuery); - - uint32_t answerCount(const hMDNSServiceQuery p_hServiceQuery); - std::vector<MDNSResponder::MDNSServiceInfo> answerInfo(const MDNSResponder::hMDNSServiceQuery p_hServiceQuery); - - const char* answerServiceDomain(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerHostDomain(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - const char* answerHostDomain(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); -#ifdef MDNS_IP4_SUPPORT - bool hasAnswerIP4Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIP4AddressCount(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIP4Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); -#endif -#ifdef MDNS_IP6_SUPPORT - bool hasAnswerIP6Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIP6AddressCount(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIP6Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); -#endif - bool hasAnswerPort(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - uint16_t answerPort(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerTxts(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - // Get the TXT items as a ';'-separated string - const char* answerTxts(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - - /** - MDNSProbeResultCallbackFn - Callback function for (host and service domain) probe results - */ - typedef std::function<void(const char* p_pcDomainName, - bool p_bProbeResult)> MDNSHostProbeFn; - - typedef std::function<void(MDNSResponder& resp, - const char* p_pcDomainName, - bool p_bProbeResult)> MDNSHostProbeFn1; - - typedef std::function<void(const char* p_pcServiceName, - const hMDNSService p_hMDNSService, - bool p_bProbeResult)> MDNSServiceProbeFn; - - typedef std::function<void(MDNSResponder& resp, - const char* p_pcServiceName, - const hMDNSService p_hMDNSService, - bool p_bProbeResult)> MDNSServiceProbeFn1; - - // Set a global callback function for host and service probe results - // The callback function is called, when the probing for the host domain - // (or a service domain, which hasn't got a service specific callback) - // Succeeds or fails. - // In case of failure, the failed domain name should be changed. - bool setHostProbeResultCallback(MDNSHostProbeFn p_fnCallback); - bool setHostProbeResultCallback(MDNSHostProbeFn1 p_fnCallback); - - // Set a service specific probe result callback - bool setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService, - MDNSServiceProbeFn p_fnCallback); - bool setServiceProbeResultCallback(const MDNSResponder::hMDNSService p_hService, - MDNSServiceProbeFn1 p_fnCallback); - - // Application should call this whenever AP is configured/disabled - bool notifyAPChange(void); - - // 'update' should be called in every 'loop' to run the MDNS processing - bool update(void); - - // 'announce' can be called every time, the configuration of some service - // changes. Mainly, this would be changed content of TXT items. - bool announce(void); - - // Enable OTA update - hMDNSService enableArduino(uint16_t p_u16Port, - bool p_bAuthUpload = false); - - // Domain name helper - static bool indexDomain(char*& p_rpcDomain, - const char* p_pcDivider = "-", - const char* p_pcDefaultDomain = 0); - - /** STRUCTS **/ - -public: - /** - MDNSServiceInfo, used in application callbacks - */ - struct MDNSServiceInfo - { - MDNSServiceInfo(MDNSResponder& p_pM, MDNSResponder::hMDNSServiceQuery p_hS, uint32_t p_u32A) - : p_pMDNSResponder(p_pM), - p_hServiceQuery(p_hS), - p_u32AnswerIndex(p_u32A) - {}; - struct CompareKey - { - bool operator()(char const *a, char const *b) const - { - return strcmp(a, b) < 0; - } - }; - using KeyValueMap = std::map<const char*, const char*, CompareKey>; - protected: - MDNSResponder& p_pMDNSResponder; - MDNSResponder::hMDNSServiceQuery p_hServiceQuery; - uint32_t p_u32AnswerIndex; - KeyValueMap keyValueMap; - public: - const char* serviceDomain() - { - return p_pMDNSResponder.answerServiceDomain(p_hServiceQuery, p_u32AnswerIndex); - }; - bool hostDomainAvailable() - { - return (p_pMDNSResponder.hasAnswerHostDomain(p_hServiceQuery, p_u32AnswerIndex)); - } - const char* hostDomain() - { - return (hostDomainAvailable()) ? - p_pMDNSResponder.answerHostDomain(p_hServiceQuery, p_u32AnswerIndex) : nullptr; - }; - bool hostPortAvailable() - { - return (p_pMDNSResponder.hasAnswerPort(p_hServiceQuery, p_u32AnswerIndex)); - } - uint16_t hostPort() - { - return (hostPortAvailable()) ? - p_pMDNSResponder.answerPort(p_hServiceQuery, p_u32AnswerIndex) : 0; - }; - bool IP4AddressAvailable() - { - return (p_pMDNSResponder.hasAnswerIP4Address(p_hServiceQuery, p_u32AnswerIndex)); - } - std::vector<IPAddress> IP4Adresses() - { - std::vector<IPAddress> internalIP; - if (IP4AddressAvailable()) - { - uint16_t cntIP4Adress = p_pMDNSResponder.answerIP4AddressCount(p_hServiceQuery, p_u32AnswerIndex); - for (uint32_t u2 = 0; u2 < cntIP4Adress; ++u2) - { - internalIP.emplace_back(p_pMDNSResponder.answerIP4Address(p_hServiceQuery, p_u32AnswerIndex, u2)); - } - } - return internalIP; - }; - bool txtAvailable() - { - return (p_pMDNSResponder.hasAnswerTxts(p_hServiceQuery, p_u32AnswerIndex)); - } - const char* strKeyValue() - { - return (txtAvailable()) ? - p_pMDNSResponder.answerTxts(p_hServiceQuery, p_u32AnswerIndex) : nullptr; - }; - const KeyValueMap& keyValues() - { - if (txtAvailable() && keyValueMap.size() == 0) - { - for (auto kv = p_pMDNSResponder._answerKeyValue(p_hServiceQuery, p_u32AnswerIndex); kv != nullptr; kv = kv->m_pNext) - { - keyValueMap.emplace(std::pair<const char*, const char*>(kv->m_pcKey, kv->m_pcValue)); - } - } - return keyValueMap; - } - const char* value(const char* key) - { - char* result = nullptr; - - for (stcMDNSServiceTxt* pTxt = p_pMDNSResponder._answerKeyValue(p_hServiceQuery, p_u32AnswerIndex); pTxt; pTxt = pTxt->m_pNext) - { - if ((key) && - (0 == strcmp(pTxt->m_pcKey, key))) - { - result = pTxt->m_pcValue; - break; - } - } - return result; - } - }; -protected: - - /** - stcMDNSServiceTxt - */ - struct stcMDNSServiceTxt - { - stcMDNSServiceTxt* m_pNext; - char* m_pcKey; - char* m_pcValue; - bool m_bTemp; - - stcMDNSServiceTxt(const char* p_pcKey = 0, - const char* p_pcValue = 0, - bool p_bTemp = false); - stcMDNSServiceTxt(const stcMDNSServiceTxt& p_Other); - ~stcMDNSServiceTxt(void); - - stcMDNSServiceTxt& operator=(const stcMDNSServiceTxt& p_Other); - bool clear(void); - - char* allocKey(size_t p_stLength); - bool setKey(const char* p_pcKey, - size_t p_stLength); - bool setKey(const char* p_pcKey); - bool releaseKey(void); - - char* allocValue(size_t p_stLength); - bool setValue(const char* p_pcValue, - size_t p_stLength); - bool setValue(const char* p_pcValue); - bool releaseValue(void); - - bool set(const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp = false); - - bool update(const char* p_pcValue); - - size_t length(void) const; - }; - - /** - stcMDNSTxts - */ - struct stcMDNSServiceTxts - { - stcMDNSServiceTxt* m_pTxts; - - stcMDNSServiceTxts(void); - stcMDNSServiceTxts(const stcMDNSServiceTxts& p_Other); - ~stcMDNSServiceTxts(void); - - stcMDNSServiceTxts& operator=(const stcMDNSServiceTxts& p_Other); - - bool clear(void); - - bool add(stcMDNSServiceTxt* p_pTxt); - bool remove(stcMDNSServiceTxt* p_pTxt); - - bool removeTempTxts(void); - - stcMDNSServiceTxt* find(const char* p_pcKey); - const stcMDNSServiceTxt* find(const char* p_pcKey) const; - stcMDNSServiceTxt* find(const stcMDNSServiceTxt* p_pTxt); - - uint16_t length(void) const; - - size_t c_strLength(void) const; - bool c_str(char* p_pcBuffer); - - size_t bufferLength(void) const; - bool buffer(char* p_pcBuffer); - - bool compare(const stcMDNSServiceTxts& p_Other) const; - bool operator==(const stcMDNSServiceTxts& p_Other) const; - bool operator!=(const stcMDNSServiceTxts& p_Other) const; - }; - - /** - enuContentFlags - */ - typedef enum _enuContentFlags - { - // Host - ContentFlag_A = 0x01, - ContentFlag_PTR_IP4 = 0x02, - ContentFlag_PTR_IP6 = 0x04, - ContentFlag_AAAA = 0x08, - // Service - ContentFlag_PTR_TYPE = 0x10, - ContentFlag_PTR_NAME = 0x20, - ContentFlag_TXT = 0x40, - ContentFlag_SRV = 0x80, - } enuContentFlags; - - /** - stcMDNS_MsgHeader - */ - struct stcMDNS_MsgHeader - { - uint16_t m_u16ID; // Identifier - bool m_1bQR : 1; // Query/Response flag - unsigned char m_4bOpcode : 4; // Operation code - bool m_1bAA : 1; // Authoritative Answer flag - bool m_1bTC : 1; // Truncation flag - bool m_1bRD : 1; // Recursion desired - bool m_1bRA : 1; // Recursion available - unsigned char m_3bZ : 3; // Zero - unsigned char m_4bRCode : 4; // Response code - uint16_t m_u16QDCount; // Question count - uint16_t m_u16ANCount; // Answer count - uint16_t m_u16NSCount; // Authority Record count - uint16_t m_u16ARCount; // Additional Record count - - stcMDNS_MsgHeader(uint16_t p_u16ID = 0, - bool p_bQR = false, - unsigned char p_ucOpcode = 0, - bool p_bAA = false, - bool p_bTC = false, - bool p_bRD = false, - bool p_bRA = false, - unsigned char p_ucRCode = 0, - uint16_t p_u16QDCount = 0, - uint16_t p_u16ANCount = 0, - uint16_t p_u16NSCount = 0, - uint16_t p_u16ARCount = 0); - }; - - /** - stcMDNS_RRDomain - */ - struct stcMDNS_RRDomain - { - char m_acName[MDNS_DOMAIN_MAXLENGTH]; // Encoded domain name - uint16_t m_u16NameLength; // Length (incl. '\0') - - stcMDNS_RRDomain(void); - stcMDNS_RRDomain(const stcMDNS_RRDomain& p_Other); - - stcMDNS_RRDomain& operator=(const stcMDNS_RRDomain& p_Other); - - bool clear(void); - - bool addLabel(const char* p_pcLabel, - bool p_bPrependUnderline = false); - - bool compare(const stcMDNS_RRDomain& p_Other) const; - bool operator==(const stcMDNS_RRDomain& p_Other) const; - bool operator!=(const stcMDNS_RRDomain& p_Other) const; - bool operator>(const stcMDNS_RRDomain& p_Other) const; - - size_t c_strLength(void) const; - bool c_str(char* p_pcBuffer); - }; - - /** - stcMDNS_RRAttributes - */ - struct stcMDNS_RRAttributes - { - uint16_t m_u16Type; // Type - uint16_t m_u16Class; // Class, nearly always 'IN' - - stcMDNS_RRAttributes(uint16_t p_u16Type = 0, - uint16_t p_u16Class = 1 /*DNS_RRCLASS_IN Internet*/); - stcMDNS_RRAttributes(const stcMDNS_RRAttributes& p_Other); - - stcMDNS_RRAttributes& operator=(const stcMDNS_RRAttributes& p_Other); - }; - - /** - stcMDNS_RRHeader - */ - struct stcMDNS_RRHeader - { - stcMDNS_RRDomain m_Domain; - stcMDNS_RRAttributes m_Attributes; - - stcMDNS_RRHeader(void); - stcMDNS_RRHeader(const stcMDNS_RRHeader& p_Other); - - stcMDNS_RRHeader& operator=(const stcMDNS_RRHeader& p_Other); - - bool clear(void); - }; - - /** - stcMDNS_RRQuestion - */ - struct stcMDNS_RRQuestion - { - stcMDNS_RRQuestion* m_pNext; - stcMDNS_RRHeader m_Header; - bool m_bUnicast; // Unicast reply requested - - stcMDNS_RRQuestion(void); - }; - - /** - enuAnswerType - */ - typedef enum _enuAnswerType - { - AnswerType_A, - AnswerType_PTR, - AnswerType_TXT, - AnswerType_AAAA, - AnswerType_SRV, - AnswerType_Generic - } enuAnswerType; - - /** - stcMDNS_RRAnswer - */ - struct stcMDNS_RRAnswer - { - stcMDNS_RRAnswer* m_pNext; - const enuAnswerType m_AnswerType; - stcMDNS_RRHeader m_Header; - bool m_bCacheFlush; // Cache flush command bit - uint32_t m_u32TTL; // Validity time in seconds - - virtual ~stcMDNS_RRAnswer(void); - - enuAnswerType answerType(void) const; - - bool clear(void); - - protected: - stcMDNS_RRAnswer(enuAnswerType p_AnswerType, - const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - }; - -#ifdef MDNS_IP4_SUPPORT - /** - stcMDNS_RRAnswerA - */ - struct stcMDNS_RRAnswerA : public stcMDNS_RRAnswer - { - IPAddress m_IPAddress; - - stcMDNS_RRAnswerA(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - ~stcMDNS_RRAnswerA(void); - - bool clear(void); - }; -#endif - - /** - stcMDNS_RRAnswerPTR - */ - struct stcMDNS_RRAnswerPTR : public stcMDNS_RRAnswer - { - stcMDNS_RRDomain m_PTRDomain; - - stcMDNS_RRAnswerPTR(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - ~stcMDNS_RRAnswerPTR(void); - - bool clear(void); - }; - - /** - stcMDNS_RRAnswerTXT - */ - struct stcMDNS_RRAnswerTXT : public stcMDNS_RRAnswer - { - stcMDNSServiceTxts m_Txts; - - stcMDNS_RRAnswerTXT(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - ~stcMDNS_RRAnswerTXT(void); - - bool clear(void); - }; - -#ifdef MDNS_IP6_SUPPORT - /** - stcMDNS_RRAnswerAAAA - */ - struct stcMDNS_RRAnswerAAAA : public stcMDNS_RRAnswer - { - //TODO: IP6Address m_IPAddress; - - stcMDNS_RRAnswerAAAA(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - ~stcMDNS_RRAnswerAAAA(void); - - bool clear(void); - }; -#endif - - /** - stcMDNS_RRAnswerSRV - */ - struct stcMDNS_RRAnswerSRV : public stcMDNS_RRAnswer - { - uint16_t m_u16Priority; - uint16_t m_u16Weight; - uint16_t m_u16Port; - stcMDNS_RRDomain m_SRVDomain; - - stcMDNS_RRAnswerSRV(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - ~stcMDNS_RRAnswerSRV(void); - - bool clear(void); - }; - - /** - stcMDNS_RRAnswerGeneric - */ - struct stcMDNS_RRAnswerGeneric : public stcMDNS_RRAnswer - { - uint16_t m_u16RDLength; // Length of variable answer - uint8_t* m_pu8RDData; // Offset of start of variable answer in packet - - stcMDNS_RRAnswerGeneric(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL); - ~stcMDNS_RRAnswerGeneric(void); - - bool clear(void); - }; - - - /** - enuProbingStatus - */ - typedef enum _enuProbingStatus - { - ProbingStatus_WaitingForData, - ProbingStatus_ReadyToStart, - ProbingStatus_InProgress, - ProbingStatus_Done - } enuProbingStatus; - - /** - stcProbeInformation - */ - struct stcProbeInformation - { - enuProbingStatus m_ProbingStatus; - uint8_t m_u8SentCount; // Used for probes and announcements - esp8266::polledTimeout::oneShotMs m_Timeout; // Used for probes and announcements - //clsMDNSTimeFlag m_TimeFlag; // Used for probes and announcements - bool m_bConflict; - bool m_bTiebreakNeeded; - MDNSHostProbeFn m_fnHostProbeResultCallback; - MDNSServiceProbeFn m_fnServiceProbeResultCallback; - - stcProbeInformation(void); - - bool clear(bool p_bClearUserdata = false); - }; - - - /** - stcMDNSService - */ - struct stcMDNSService - { - stcMDNSService* m_pNext; - char* m_pcName; - bool m_bAutoName; // Name was set automatically to hostname (if no name was supplied) - char* m_pcService; - char* m_pcProtocol; - uint16_t m_u16Port; - uint8_t m_u8ReplyMask; - stcMDNSServiceTxts m_Txts; - MDNSDynamicServiceTxtCallbackFunc m_fnTxtCallback; - stcProbeInformation m_ProbeInformation; - - stcMDNSService(const char* p_pcName = 0, - const char* p_pcService = 0, - const char* p_pcProtocol = 0); - ~stcMDNSService(void); - - bool setName(const char* p_pcName); - bool releaseName(void); - - bool setService(const char* p_pcService); - bool releaseService(void); - - bool setProtocol(const char* p_pcProtocol); - bool releaseProtocol(void); - }; - - /** - stcMDNSServiceQuery - */ - struct stcMDNSServiceQuery - { - /** - stcAnswer - */ - struct stcAnswer - { - /** - stcTTL - */ - struct stcTTL - { - /** - timeoutLevel_t - */ - typedef uint8_t timeoutLevel_t; - /** - TIMEOUTLEVELs - */ - const timeoutLevel_t TIMEOUTLEVEL_UNSET = 0; - const timeoutLevel_t TIMEOUTLEVEL_BASE = 80; - const timeoutLevel_t TIMEOUTLEVEL_INTERVAL = 5; - const timeoutLevel_t TIMEOUTLEVEL_FINAL = 100; - - uint32_t m_u32TTL; - esp8266::polledTimeout::oneShotMs m_TTLTimeout; - timeoutLevel_t m_timeoutLevel; - - stcTTL(void); - bool set(uint32_t p_u32TTL); - - bool flagged(void); - bool restart(void); - - bool prepareDeletion(void); - bool finalTimeoutLevel(void) const; - - unsigned long timeout(void) const; - }; -#ifdef MDNS_IP4_SUPPORT - /** - stcIP4Address - */ - struct stcIP4Address - { - stcIP4Address* m_pNext; - IPAddress m_IPAddress; - stcTTL m_TTL; - - stcIP4Address(IPAddress p_IPAddress, - uint32_t p_u32TTL = 0); - }; -#endif -#ifdef MDNS_IP6_SUPPORT - /** - stcIP6Address - */ - struct stcIP6Address - { - stcIP6Address* m_pNext; - IP6Address m_IPAddress; - stcTTL m_TTL; - - stcIP6Address(IPAddress p_IPAddress, - uint32_t p_u32TTL = 0); - }; -#endif - - stcAnswer* m_pNext; - // The service domain is the first 'answer' (from PTR answer, using service and protocol) to be set - // Defines the key for additional answer, like host domain, etc. - stcMDNS_RRDomain m_ServiceDomain; // 1. level answer (PTR), eg. MyESP._http._tcp.local - char* m_pcServiceDomain; - stcTTL m_TTLServiceDomain; - stcMDNS_RRDomain m_HostDomain; // 2. level answer (SRV, using service domain), eg. esp8266.local - char* m_pcHostDomain; - uint16_t m_u16Port; // 2. level answer (SRV, using service domain), eg. 5000 - stcTTL m_TTLHostDomainAndPort; - stcMDNSServiceTxts m_Txts; // 2. level answer (TXT, using service domain), eg. c#=1 - char* m_pcTxts; - stcTTL m_TTLTxts; -#ifdef MDNS_IP4_SUPPORT - stcIP4Address* m_pIP4Addresses; // 3. level answer (A, using host domain), eg. 123.456.789.012 -#endif -#ifdef MDNS_IP6_SUPPORT - stcIP6Address* m_pIP6Addresses; // 3. level answer (AAAA, using host domain), eg. 1234::09 -#endif - uint32_t m_u32ContentFlags; - - stcAnswer(void); - ~stcAnswer(void); - - bool clear(void); - - char* allocServiceDomain(size_t p_stLength); - bool releaseServiceDomain(void); - - char* allocHostDomain(size_t p_stLength); - bool releaseHostDomain(void); - - char* allocTxts(size_t p_stLength); - bool releaseTxts(void); - -#ifdef MDNS_IP4_SUPPORT - bool releaseIP4Addresses(void); - bool addIP4Address(stcIP4Address* p_pIP4Address); - bool removeIP4Address(stcIP4Address* p_pIP4Address); - const stcIP4Address* findIP4Address(const IPAddress& p_IPAddress) const; - stcIP4Address* findIP4Address(const IPAddress& p_IPAddress); - uint32_t IP4AddressCount(void) const; - const stcIP4Address* IP4AddressAtIndex(uint32_t p_u32Index) const; - stcIP4Address* IP4AddressAtIndex(uint32_t p_u32Index); -#endif -#ifdef MDNS_IP6_SUPPORT - bool releaseIP6Addresses(void); - bool addIP6Address(stcIP6Address* p_pIP6Address); - bool removeIP6Address(stcIP6Address* p_pIP6Address); - const stcIP6Address* findIP6Address(const IPAddress& p_IPAddress) const; - stcIP6Address* findIP6Address(const IPAddress& p_IPAddress); - uint32_t IP6AddressCount(void) const; - const stcIP6Address* IP6AddressAtIndex(uint32_t p_u32Index) const; - stcIP6Address* IP6AddressAtIndex(uint32_t p_u32Index); -#endif - }; - - stcMDNSServiceQuery* m_pNext; - stcMDNS_RRDomain m_ServiceTypeDomain; // eg. _http._tcp.local - MDNSServiceQueryCallbackFunc m_fnCallback; - bool m_bLegacyQuery; - uint8_t m_u8SentCount; - esp8266::polledTimeout::oneShotMs m_ResendTimeout; - bool m_bAwaitingAnswers; - stcAnswer* m_pAnswers; - - stcMDNSServiceQuery(void); - ~stcMDNSServiceQuery(void); - - bool clear(void); - - uint32_t answerCount(void) const; - const stcAnswer* answerAtIndex(uint32_t p_u32Index) const; - stcAnswer* answerAtIndex(uint32_t p_u32Index); - uint32_t indexOfAnswer(const stcAnswer* p_pAnswer) const; - - bool addAnswer(stcAnswer* p_pAnswer); - bool removeAnswer(stcAnswer* p_pAnswer); - - stcAnswer* findAnswerForServiceDomain(const stcMDNS_RRDomain& p_ServiceDomain); - stcAnswer* findAnswerForHostDomain(const stcMDNS_RRDomain& p_HostDomain); - }; - - /** - stcMDNSSendParameter - */ - struct stcMDNSSendParameter - { - protected: - /** - stcDomainCacheItem - */ - struct stcDomainCacheItem - { - stcDomainCacheItem* m_pNext; - const void* m_pHostnameOrService; // Opaque id for host or service domain (pointer) - bool m_bAdditionalData; // Opaque flag for special info (service domain included) - uint16_t m_u16Offset; // Offset in UDP output buffer - - stcDomainCacheItem(const void* p_pHostnameOrService, - bool p_bAdditionalData, - uint32_t p_u16Offset); - }; - - public: - uint16_t m_u16ID; // Query ID (used only in lagacy queries) - stcMDNS_RRQuestion* m_pQuestions; // A list of queries - uint8_t m_u8HostReplyMask; // Flags for reply components/answers - bool m_bLegacyQuery; // Flag: Legacy query - bool m_bResponse; // Flag: Response to a query - bool m_bAuthorative; // Flag: Authorative (owner) response - bool m_bCacheFlush; // Flag: Clients should flush their caches - bool m_bUnicast; // Flag: Unicast response - bool m_bUnannounce; // Flag: Unannounce service - uint16_t m_u16Offset; // Current offset in UDP write buffer (mainly for domain cache) - stcDomainCacheItem* m_pDomainCacheItems; // Cached host and service domains - - stcMDNSSendParameter(void); - ~stcMDNSSendParameter(void); - - bool clear(void); - - bool shiftOffset(uint16_t p_u16Shift); - - bool addDomainCacheItem(const void* p_pHostnameOrService, - bool p_bAdditionalData, - uint16_t p_u16Offset); - uint16_t findCachedDomainOffset(const void* p_pHostnameOrService, - bool p_bAdditionalData) const; - }; - - // Instance variables - stcMDNSService* m_pServices; - UdpContext* m_pUDPContext; - char* m_pcHostname; - stcMDNSServiceQuery* m_pServiceQueries; - WiFiEventHandler m_DisconnectedHandler; - WiFiEventHandler m_GotIPHandler; - MDNSDynamicServiceTxtCallbackFunc m_fnServiceTxtCallback; - bool m_bPassivModeEnabled; - stcProbeInformation m_HostProbeInformation; - CONST netif* m_netif; // network interface to run on - - /** CONTROL **/ - /* MAINTENANCE */ - bool _process(bool p_bUserContext); - bool _restart(void); - - /* RECEIVING */ - bool _parseMessage(void); - bool _parseQuery(const stcMDNS_MsgHeader& p_Header); - - bool _parseResponse(const stcMDNS_MsgHeader& p_Header); - bool _processAnswers(const stcMDNS_RRAnswer* p_pPTRAnswers); - bool _processPTRAnswer(const stcMDNS_RRAnswerPTR* p_pPTRAnswer, - bool& p_rbFoundNewKeyAnswer); - bool _processSRVAnswer(const stcMDNS_RRAnswerSRV* p_pSRVAnswer, - bool& p_rbFoundNewKeyAnswer); - bool _processTXTAnswer(const stcMDNS_RRAnswerTXT* p_pTXTAnswer); -#ifdef MDNS_IP4_SUPPORT - bool _processAAnswer(const stcMDNS_RRAnswerA* p_pAAnswer); -#endif -#ifdef MDNS_IP6_SUPPORT - bool _processAAAAAnswer(const stcMDNS_RRAnswerAAAA* p_pAAAAAnswer); -#endif - - /* PROBING */ - bool _updateProbeStatus(void); - bool _resetProbeStatus(bool p_bRestart = true); - bool _hasProbesWaitingForAnswers(void) const; - bool _sendHostProbe(void); - bool _sendServiceProbe(stcMDNSService& p_rService); - bool _cancelProbingForHost(void); - bool _cancelProbingForService(stcMDNSService& p_rService); - - /* ANNOUNCE */ - bool _announce(bool p_bAnnounce, - bool p_bIncludeServices); - bool _announceService(stcMDNSService& p_rService, - bool p_bAnnounce = true); - - /* SERVICE QUERY CACHE */ - bool _hasServiceQueriesWaitingForAnswers(void) const; - bool _checkServiceQueryCache(void); - - /** TRANSFER **/ - /* SENDING */ - bool _sendMDNSMessage(stcMDNSSendParameter& p_SendParameter); - bool _sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParameter& p_rSendParameter); - bool _prepareMDNSMessage(stcMDNSSendParameter& p_SendParameter, - IPAddress p_IPAddress); - bool _sendMDNSServiceQuery(const stcMDNSServiceQuery& p_ServiceQuery); - bool _sendMDNSQuery(const stcMDNS_RRDomain& p_QueryDomain, - uint16_t p_u16QueryType, - stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers = 0); - - const IPAddress _getResponseMulticastInterface() const - { - return IPAddress(m_netif->ip_addr); - } - - uint8_t _replyMaskForHost(const stcMDNS_RRHeader& p_RRHeader, - bool* p_pbFullNameMatch = 0) const; - uint8_t _replyMaskForService(const stcMDNS_RRHeader& p_RRHeader, - const stcMDNSService& p_Service, - bool* p_pbFullNameMatch = 0) const; - - /* RESOURCE RECORD */ - bool _readRRQuestion(stcMDNS_RRQuestion& p_rQuestion); - bool _readRRAnswer(stcMDNS_RRAnswer*& p_rpAnswer); -#ifdef MDNS_IP4_SUPPORT - bool _readRRAnswerA(stcMDNS_RRAnswerA& p_rRRAnswerA, - uint16_t p_u16RDLength); -#endif - bool _readRRAnswerPTR(stcMDNS_RRAnswerPTR& p_rRRAnswerPTR, - uint16_t p_u16RDLength); - bool _readRRAnswerTXT(stcMDNS_RRAnswerTXT& p_rRRAnswerTXT, - uint16_t p_u16RDLength); -#ifdef MDNS_IP6_SUPPORT - bool _readRRAnswerAAAA(stcMDNS_RRAnswerAAAA& p_rRRAnswerAAAA, - uint16_t p_u16RDLength); -#endif - bool _readRRAnswerSRV(stcMDNS_RRAnswerSRV& p_rRRAnswerSRV, - uint16_t p_u16RDLength); - bool _readRRAnswerGeneric(stcMDNS_RRAnswerGeneric& p_rRRAnswerGeneric, - uint16_t p_u16RDLength); - - bool _readRRHeader(stcMDNS_RRHeader& p_rHeader); - bool _readRRDomain(stcMDNS_RRDomain& p_rRRDomain); - bool _readRRDomain_Loop(stcMDNS_RRDomain& p_rRRDomain, - uint8_t p_u8Depth); - bool _readRRAttributes(stcMDNS_RRAttributes& p_rAttributes); - - /* DOMAIN NAMES */ - bool _buildDomainForHost(const char* p_pcHostname, - stcMDNS_RRDomain& p_rHostDomain) const; - bool _buildDomainForDNSSD(stcMDNS_RRDomain& p_rDNSSDDomain) const; - bool _buildDomainForService(const stcMDNSService& p_Service, - bool p_bIncludeName, - stcMDNS_RRDomain& p_rServiceDomain) const; - bool _buildDomainForService(const char* p_pcService, - const char* p_pcProtocol, - stcMDNS_RRDomain& p_rServiceDomain) const; -#ifdef MDNS_IP4_SUPPORT - bool _buildDomainForReverseIP4(IPAddress p_IP4Address, - stcMDNS_RRDomain& p_rReverseIP4Domain) const; -#endif -#ifdef MDNS_IP6_SUPPORT - bool _buildDomainForReverseIP6(IPAddress p_IP4Address, - stcMDNS_RRDomain& p_rReverseIP6Domain) const; -#endif - - /* UDP */ - bool _udpReadBuffer(unsigned char* p_pBuffer, - size_t p_stLength); - bool _udpRead8(uint8_t& p_ru8Value); - bool _udpRead16(uint16_t& p_ru16Value); - bool _udpRead32(uint32_t& p_ru32Value); - - bool _udpAppendBuffer(const unsigned char* p_pcBuffer, - size_t p_stLength); - bool _udpAppend8(uint8_t p_u8Value); - bool _udpAppend16(uint16_t p_u16Value); - bool _udpAppend32(uint32_t p_u32Value); - -#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER - bool _udpDump(bool p_bMovePointer = false); - bool _udpDump(unsigned p_uOffset, - unsigned p_uLength); -#endif - - /* READ/WRITE MDNS STRUCTS */ - bool _readMDNSMsgHeader(stcMDNS_MsgHeader& p_rMsgHeader); - - bool _write8(uint8_t p_u8Value, - stcMDNSSendParameter& p_rSendParameter); - bool _write16(uint16_t p_u16Value, - stcMDNSSendParameter& p_rSendParameter); - bool _write32(uint32_t p_u32Value, - stcMDNSSendParameter& p_rSendParameter); - - bool _writeMDNSMsgHeader(const stcMDNS_MsgHeader& p_MsgHeader, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSRRAttributes(const stcMDNS_RRAttributes& p_Attributes, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSRRDomain(const stcMDNS_RRDomain& p_Domain, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSHostDomain(const char* m_pcHostname, - bool p_bPrependRDLength, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSServiceDomain(const stcMDNSService& p_Service, - bool p_bIncludeName, - bool p_bPrependRDLength, - stcMDNSSendParameter& p_rSendParameter); - - bool _writeMDNSQuestion(stcMDNS_RRQuestion& p_Question, - stcMDNSSendParameter& p_rSendParameter); - -#ifdef MDNS_IP4_SUPPORT - bool _writeMDNSAnswer_A(IPAddress p_IPAddress, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSAnswer_PTR_IP4(IPAddress p_IPAddress, - stcMDNSSendParameter& p_rSendParameter); -#endif - bool _writeMDNSAnswer_PTR_TYPE(stcMDNSService& p_rService, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSAnswer_PTR_NAME(stcMDNSService& p_rService, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSAnswer_TXT(stcMDNSService& p_rService, - stcMDNSSendParameter& p_rSendParameter); -#ifdef MDNS_IP6_SUPPORT - bool _writeMDNSAnswer_AAAA(IPAddress p_IPAddress, - stcMDNSSendParameter& p_rSendParameter); - bool _writeMDNSAnswer_PTR_IP6(IPAddress p_IPAddress, - stcMDNSSendParameter& p_rSendParameter); -#endif - bool _writeMDNSAnswer_SRV(stcMDNSService& p_rService, - stcMDNSSendParameter& p_rSendParameter); - - /** HELPERS **/ - /* UDP CONTEXT */ - bool _callProcess(void); - bool _allocUDPContext(void); - bool _releaseUDPContext(void); - - /* SERVICE QUERY */ - stcMDNSServiceQuery* _allocServiceQuery(void); - bool _removeServiceQuery(stcMDNSServiceQuery* p_pServiceQuery); - bool _removeLegacyServiceQuery(void); - stcMDNSServiceQuery* _findServiceQuery(hMDNSServiceQuery p_hServiceQuery); - stcMDNSServiceQuery* _findLegacyServiceQuery(void); - bool _releaseServiceQueries(void); - stcMDNSServiceQuery* _findNextServiceQueryByServiceType(const stcMDNS_RRDomain& p_ServiceDomain, - const stcMDNSServiceQuery* p_pPrevServiceQuery); - - /* HOSTNAME */ - bool _setHostname(const char* p_pcHostname); - bool _releaseHostname(void); - - /* SERVICE */ - stcMDNSService* _allocService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port); - bool _releaseService(stcMDNSService* p_pService); - bool _releaseServices(void); - - stcMDNSService* _findService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol); - stcMDNSService* _findService(const hMDNSService p_hService); - - size_t _countServices(void) const; - - /* SERVICE TXT */ - stcMDNSServiceTxt* _allocServiceTxt(stcMDNSService* p_pService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp); - bool _releaseServiceTxt(stcMDNSService* p_pService, - stcMDNSServiceTxt* p_pTxt); - stcMDNSServiceTxt* _updateServiceTxt(stcMDNSService* p_pService, - stcMDNSServiceTxt* p_pTxt, - const char* p_pcValue, - bool p_bTemp); - - stcMDNSServiceTxt* _findServiceTxt(stcMDNSService* p_pService, - const char* p_pcKey); - stcMDNSServiceTxt* _findServiceTxt(stcMDNSService* p_pService, - const hMDNSTxt p_hTxt); - - stcMDNSServiceTxt* _addServiceTxt(stcMDNSService* p_pService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp); - - stcMDNSServiceTxt* _answerKeyValue(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - - bool _collectServiceTxts(stcMDNSService& p_rService); - bool _releaseTempServiceTxts(stcMDNSService& p_rService); - const stcMDNSServiceTxt* _serviceTxts(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol); - - /* MISC */ -#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER - bool _printRRDomain(const stcMDNS_RRDomain& p_rRRDomain) const; - bool _printRRAnswer(const MDNSResponder::stcMDNS_RRAnswer& p_RRAnswer) const; -#endif -}; - -}// namespace MDNSImplementation - -}// namespace esp8266 - -#endif // MDNS_H diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Control.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Control.cpp deleted file mode 100644 index 41e9524aba..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Control.cpp +++ /dev/null @@ -1,2134 +0,0 @@ -/* - LEAmDNS_Control.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#include <sys/time.h> -#include <IPAddress.h> -#include <AddrList.h> -#include <lwip/ip_addr.h> -#include <WString.h> -#include <cstdint> - -/* - ESP8266mDNS Control.cpp -*/ - -extern "C" { -#include "user_interface.h" -} - -#include "LEAmDNS_lwIPdefs.h" -#include "LEAmDNS_Priv.h" - -namespace esp8266 -{ -/* - LEAmDNS -*/ -namespace MDNSImplementation -{ - -/** - CONTROL -*/ - - -/** - MAINTENANCE -*/ - -/* - MDNSResponder::_process - - Run the MDNS process. - Is called, every time the UDPContext receives data AND - should be called in every 'loop' by calling 'MDNS::update()'. - -*/ -bool MDNSResponder::_process(bool p_bUserContext) -{ - - bool bResult = true; - - if (!p_bUserContext) - { - - if ((m_pUDPContext) && // UDPContext available AND - (m_pUDPContext->next())) // has content - { - - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _update: Calling _parseMessage\n"));); - bResult = _parseMessage(); - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parsePacket %s\n"), (bResult ? "succeeded" : "FAILED"));); - } - } - else - { - bResult = (m_netif != nullptr) && - (m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running - _updateProbeStatus() && // Probing - _checkServiceQueryCache(); // Service query cache check - } - return bResult; -} - -/* - MDNSResponder::_restart -*/ -bool MDNSResponder::_restart(void) -{ - - return ((m_netif != nullptr) && - (m_netif->flags & NETIF_FLAG_UP) && // network interface is up and running - (_resetProbeStatus(true)) && // Stop and restart probing - (_allocUDPContext())); // Restart UDP -} - - -/** - RECEIVING -*/ - -/* - MDNSResponder::_parseMessage -*/ -bool MDNSResponder::_parseMessage(void) -{ - DEBUG_EX_INFO( - unsigned long ulStartTime = millis(); - unsigned uStartMemory = ESP.getFreeHeap(); - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage (Time: %lu ms, heap: %u bytes, from %s(%u), to %s(%u))\n"), ulStartTime, uStartMemory, - IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str(), m_pUDPContext->getRemotePort(), - IPAddress(m_pUDPContext->getDestAddress()).toString().c_str(), m_pUDPContext->getLocalPort()); - ); - //DEBUG_EX_INFO(_udpDump();); - - bool bResult = false; - - stcMDNS_MsgHeader header; - if (_readMDNSMsgHeader(header)) - { - if (0 == header.m_4bOpcode) // A standard query - { - if (header.m_1bQR) // Received a response -> answers to a query - { - //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: Reading answers: ID:%u, Q:%u, A:%u, NS:%u, AR:%u\n"), header.m_u16ID, header.m_u16QDCount, header.m_u16ANCount, header.m_u16NSCount, header.m_u16ARCount);); - bResult = _parseResponse(header); - } - else // Received a query (Questions) - { - //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: Reading query: ID:%u, Q:%u, A:%u, NS:%u, AR:%u\n"), header.m_u16ID, header.m_u16QDCount, header.m_u16ANCount, header.m_u16NSCount, header.m_u16ARCount);); - bResult = _parseQuery(header); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: Received UNEXPECTED opcode:%u. Ignoring message!\n"), header.m_4bOpcode);); - m_pUDPContext->flush(); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: FAILED to read header\n"));); - m_pUDPContext->flush(); - } - DEBUG_EX_INFO( - unsigned uFreeHeap = ESP.getFreeHeap(); - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseMessage: Done (%s after %lu ms, ate %i bytes, remaining %u)\n\n"), (bResult ? "Succeeded" : "FAILED"), (millis() - ulStartTime), (uStartMemory - uFreeHeap), uFreeHeap); - ); - return bResult; -} - -/* - MDNSResponder::_parseQuery - - Queries are of interest in two cases: - 1. allow for tiebreaking while probing in the case of a race condition between two instances probing for - the same name at the same time - 2. provide answers to questions for our host domain or any presented service - - When reading the questions, a set of (planned) responses is created, eg. a reverse PTR question for the host domain - gets an A (IP address) response, a PTR question for the _services._dns-sd domain gets a PTR (type) response for any - registered service, ... - - As any mDNS responder should be able to handle 'legacy' queries (from DNS clients), this case is handled here also. - Legacy queries have got only one (unicast) question and are directed to the local DNS port (not the multicast port). - - 1. -*/ -bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHeader) -{ - - bool bResult = true; - - stcMDNSSendParameter sendParameter; - uint8_t u8HostOrServiceReplies = 0; - for (uint16_t qd = 0; ((bResult) && (qd < p_MsgHeader.m_u16QDCount)); ++qd) - { - - stcMDNS_RRQuestion questionRR; - if ((bResult = _readRRQuestion(questionRR))) - { - // Define host replies, BUT only answer queries after probing is done - u8HostOrServiceReplies = - sendParameter.m_u8HostReplyMask |= (((m_bPassivModeEnabled) || - (ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus)) - ? _replyMaskForHost(questionRR.m_Header, 0) - : 0); - DEBUG_EX_INFO(if (u8HostOrServiceReplies) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Host reply needed 0x%X\n"), u8HostOrServiceReplies); - }); - - // Check tiebreak need for host domain - if (ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) - { - bool bFullNameMatch = false; - if ((_replyMaskForHost(questionRR.m_Header, &bFullNameMatch)) && - (bFullNameMatch)) - { - // We're in 'probing' state and someone is asking for our host domain: this might be - // a race-condition: Two host with the same domain names try simutanously to probe their domains - // See: RFC 6762, 8.2 (Tiebraking) - // However, we're using a max. reduced approach for tiebreaking here: The higher IP-address wins! - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Possible race-condition for host domain detected while probing.\n"));); - - m_HostProbeInformation.m_bTiebreakNeeded = true; - } - } - - // Define service replies - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - // Define service replies, BUT only answer queries after probing is done - uint8_t u8ReplyMaskForQuestion = (((m_bPassivModeEnabled) || - (ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus)) - ? _replyMaskForService(questionRR.m_Header, *pService, 0) - : 0); - u8HostOrServiceReplies |= (pService->m_u8ReplyMask |= u8ReplyMaskForQuestion); - DEBUG_EX_INFO(if (u8ReplyMaskForQuestion) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service reply needed for (%s.%s.%s): 0x%X (%s)\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol, u8ReplyMaskForQuestion, IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str()); - }); - - // Check tiebreak need for service domain - if (ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) - { - bool bFullNameMatch = false; - if ((_replyMaskForService(questionRR.m_Header, *pService, &bFullNameMatch)) && - (bFullNameMatch)) - { - // We're in 'probing' state and someone is asking for this service domain: this might be - // a race-condition: Two services with the same domain names try simutanously to probe their domains - // See: RFC 6762, 8.2 (Tiebraking) - // However, we're using a max. reduced approach for tiebreaking here: The 'higher' SRV host wins! - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Possible race-condition for service domain %s.%s.%s detected while probing.\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); - - pService->m_ProbeInformation.m_bTiebreakNeeded = true; - } - } - } - - // Handle unicast and legacy specialities - // If only one question asks for unicast reply, the whole reply packet is send unicast - if (((DNS_MQUERY_PORT != m_pUDPContext->getRemotePort()) || // Unicast (maybe legacy) query OR - (questionRR.m_bUnicast)) && // Expressivly unicast query - (!sendParameter.m_bUnicast)) - { - - sendParameter.m_bUnicast = true; - sendParameter.m_bCacheFlush = false; - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Unicast response for %s!\n"), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str());); - - if ((DNS_MQUERY_PORT != m_pUDPContext->getRemotePort()) && // Unicast (maybe legacy) query AND - (1 == p_MsgHeader.m_u16QDCount) && // Only one question AND - ((sendParameter.m_u8HostReplyMask) || // Host replies OR - (u8HostOrServiceReplies))) // Host or service replies available - { - // We're a match for this legacy query, BUT - // make sure, that the query comes from a local host - ip_info IPInfo_Local; - ip_info IPInfo_Remote; - if (((IPInfo_Remote.ip.addr = m_pUDPContext->getRemoteAddress())) && - (((wifi_get_ip_info(SOFTAP_IF, &IPInfo_Local)) && - (ip4_addr_netcmp(&IPInfo_Remote.ip, &IPInfo_Local.ip, &IPInfo_Local.netmask))) || // Remote IP in SOFTAP's subnet OR - ((wifi_get_ip_info(STATION_IF, &IPInfo_Local)) && - (ip4_addr_netcmp(&IPInfo_Remote.ip, &IPInfo_Local.ip, &IPInfo_Local.netmask))))) // Remote IP in STATION's subnet - { - - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Legacy query from local host %s, id %u!\n"), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str(), p_MsgHeader.m_u16ID);); - - sendParameter.m_u16ID = p_MsgHeader.m_u16ID; - sendParameter.m_bLegacyQuery = true; - sendParameter.m_pQuestions = new stcMDNS_RRQuestion; - if ((bResult = (0 != sendParameter.m_pQuestions))) - { - sendParameter.m_pQuestions->m_Header.m_Domain = questionRR.m_Header.m_Domain; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = questionRR.m_Header.m_Attributes.m_u16Type; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = questionRR.m_Header.m_Attributes.m_u16Class; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: FAILED to add legacy question!\n"));); - } - } - else - { - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Legacy query from NON-LOCAL host!\n"));); - bResult = false; - } - } - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: FAILED to read question!\n"));); - } - } // for questions - - //DEBUG_EX_INFO(if (u8HostOrServiceReplies) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Reply needed: %u (%s: %s->%s)\n"), u8HostOrServiceReplies, clsTimeSyncer::timestr(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str(), IPAddress(m_pUDPContext->getDestAddress()).toString().c_str()); } ); - - // Handle known answers - uint32_t u32Answers = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); - DEBUG_EX_INFO(if ((u8HostOrServiceReplies) && (u32Answers)) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Known answers(%u):\n"), u32Answers); - }); - - for (uint32_t an = 0; ((bResult) && (an < u32Answers)); ++an) - { - stcMDNS_RRAnswer* pKnownRRAnswer = 0; - if (((bResult = _readRRAnswer(pKnownRRAnswer))) && - (pKnownRRAnswer)) - { - - if ((DNS_RRTYPE_ANY != pKnownRRAnswer->m_Header.m_Attributes.m_u16Type) && // No ANY type answer - (DNS_RRCLASS_ANY != pKnownRRAnswer->m_Header.m_Attributes.m_u16Class)) // No ANY class answer - { - - // Find match between planned answer (sendParameter.m_u8HostReplyMask) and this 'known answer' - uint8_t u8HostMatchMask = (sendParameter.m_u8HostReplyMask & _replyMaskForHost(pKnownRRAnswer->m_Header)); - if ((u8HostMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND - ((MDNS_HOST_TTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new host TTL (120s) - { - - // Compare contents - if (AnswerType_PTR == pKnownRRAnswer->answerType()) - { - stcMDNS_RRDomain hostDomain; - if ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (((stcMDNS_RRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain == hostDomain)) - { - // Host domain match -#ifdef MDNS_IP4_SUPPORT - if (u8HostMatchMask & ContentFlag_PTR_IP4) - { - // IP4 PTR was asked for, but is already known -> skipping - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP4 PTR already known... skipping!\n"));); - sendParameter.m_u8HostReplyMask &= ~ContentFlag_PTR_IP4; - } -#endif -#ifdef MDNS_IP6_SUPPORT - if (u8HostMatchMask & ContentFlag_PTR_IP6) - { - // IP6 PTR was asked for, but is already known -> skipping - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP6 PTR already known... skipping!\n"));); - sendParameter.m_u8HostReplyMask &= ~ContentFlag_PTR_IP6; - } -#endif - } - } - else if (u8HostMatchMask & ContentFlag_A) - { - // IP4 address was asked for -#ifdef MDNS_IP4_SUPPORT - if ((AnswerType_A == pKnownRRAnswer->answerType()) && - (((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == _getResponseMulticastInterface())) - { - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP4 address already known... skipping!\n"));); - sendParameter.m_u8HostReplyMask &= ~ContentFlag_A; - } // else: RData NOT IP4 length !! -#endif - } - else if (u8HostMatchMask & ContentFlag_AAAA) - { - // IP6 address was asked for -#ifdef MDNS_IP6_SUPPORT - if ((AnswerType_AAAA == pAnswerRR->answerType()) && - (((stcMDNS_RRAnswerAAAA*)pAnswerRR)->m_IPAddress == _getResponseMulticastInterface())) - { - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP6 address already known... skipping!\n"));); - sendParameter.m_u8HostReplyMask &= ~ContentFlag_AAAA; - } // else: RData NOT IP6 length !! -#endif - } - } // Host match /*and TTL*/ - - // - // Check host tiebreak possibility - if (m_HostProbeInformation.m_bTiebreakNeeded) - { - stcMDNS_RRDomain hostDomain; - if ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (pKnownRRAnswer->m_Header.m_Domain == hostDomain)) - { - // Host domain match -#ifdef MDNS_IP4_SUPPORT - if (AnswerType_A == pKnownRRAnswer->answerType()) - { - IPAddress localIPAddress(_getResponseMulticastInterface()); - if (((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) - { - // SAME IP address -> We've received an old message from ourselfs (same IP) - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (IP4) WON (was an old message)!\n"));); - m_HostProbeInformation.m_bTiebreakNeeded = false; - } - else - { - if ((uint32_t)(((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress) > (uint32_t)localIPAddress) // The OTHER IP is 'higher' -> LOST - { - // LOST tiebreak - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (IP4) LOST (lower)!\n"));); - _cancelProbingForHost(); - m_HostProbeInformation.m_bTiebreakNeeded = false; - } - else // WON tiebreak - { - //TiebreakState = TiebreakState_Won; // We received an 'old' message from ourselfs -> Just ignore - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (IP4) WON (higher IP)!\n"));); - m_HostProbeInformation.m_bTiebreakNeeded = false; - } - } - } -#endif -#ifdef MDNS_IP6_SUPPORT - if (AnswerType_AAAA == pAnswerRR->answerType()) - { - // TODO - } -#endif - } - } // Host tiebreak possibility - - // Check service answers - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - - uint8_t u8ServiceMatchMask = (pService->m_u8ReplyMask & _replyMaskForService(pKnownRRAnswer->m_Header, *pService)); - - if ((u8ServiceMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND - ((MDNS_SERVICE_TTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new service TTL (4500s) - { - - if (AnswerType_PTR == pKnownRRAnswer->answerType()) - { - stcMDNS_RRDomain serviceDomain; - if ((u8ServiceMatchMask & ContentFlag_PTR_TYPE) && - (_buildDomainForService(*pService, false, serviceDomain)) && - (serviceDomain == ((stcMDNS_RRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service type PTR already known... skipping!\n"));); - pService->m_u8ReplyMask &= ~ContentFlag_PTR_TYPE; - } - if ((u8ServiceMatchMask & ContentFlag_PTR_NAME) && - (_buildDomainForService(*pService, true, serviceDomain)) && - (serviceDomain == ((stcMDNS_RRAnswerPTR*)pKnownRRAnswer)->m_PTRDomain)) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service name PTR already known... skipping!\n"));); - pService->m_u8ReplyMask &= ~ContentFlag_PTR_NAME; - } - } - else if (u8ServiceMatchMask & ContentFlag_SRV) - { - DEBUG_EX_ERR(if (AnswerType_SRV != pKnownRRAnswer->answerType()) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: ERROR! INVALID answer type (SRV)!\n"));); - stcMDNS_RRDomain hostDomain; - if ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (hostDomain == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain)) // Host domain match - { - - if ((MDNS_SRV_PRIORITY == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_u16Priority) && - (MDNS_SRV_WEIGHT == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_u16Weight) && - (pService->m_u16Port == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_u16Port)) - { - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service SRV answer already known... skipping!\n"));); - pService->m_u8ReplyMask &= ~ContentFlag_SRV; - } // else: Small differences -> send update message - } - } - else if (u8ServiceMatchMask & ContentFlag_TXT) - { - DEBUG_EX_ERR(if (AnswerType_TXT != pKnownRRAnswer->answerType()) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: ERROR! INVALID answer type (TXT)!\n"));); - _collectServiceTxts(*pService); - if (pService->m_Txts == ((stcMDNS_RRAnswerTXT*)pKnownRRAnswer)->m_Txts) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service TXT answer already known... skipping!\n"));); - pService->m_u8ReplyMask &= ~ContentFlag_TXT; - } - _releaseTempServiceTxts(*pService); - } - } // Service match and enough TTL - - // - // Check service tiebreak possibility - if (pService->m_ProbeInformation.m_bTiebreakNeeded) - { - stcMDNS_RRDomain serviceDomain; - if ((_buildDomainForService(*pService, true, serviceDomain)) && - (pKnownRRAnswer->m_Header.m_Domain == serviceDomain)) - { - // Service domain match - if (AnswerType_SRV == pKnownRRAnswer->answerType()) - { - stcMDNS_RRDomain hostDomain; - if ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (hostDomain == ((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain)) // Host domain match - { - - // We've received an old message from ourselfs (same SRV) - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (SRV) won (was an old message)!\n"));); - pService->m_ProbeInformation.m_bTiebreakNeeded = false; - } - else - { - if (((stcMDNS_RRAnswerSRV*)pKnownRRAnswer)->m_SRVDomain > hostDomain) // The OTHER domain is 'higher' -> LOST - { - // LOST tiebreak - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (SRV) LOST (lower)!\n"));); - _cancelProbingForService(*pService); - pService->m_ProbeInformation.m_bTiebreakNeeded = false; - } - else // WON tiebreak - { - //TiebreakState = TiebreakState_Won; // We received an 'old' message from ourselfs -> Just ignore - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (SRV) won (higher)!\n"));); - pService->m_ProbeInformation.m_bTiebreakNeeded = false; - } - } - } - } - } // service tiebreak possibility - } // for services - } // ANY answers - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: FAILED to read known answer!\n"));); - } - - if (pKnownRRAnswer) - { - delete pKnownRRAnswer; - pKnownRRAnswer = 0; - } - } // for answers - - if (bResult) - { - // Check, if a reply is needed - uint8_t u8ReplyNeeded = sendParameter.m_u8HostReplyMask; - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - u8ReplyNeeded |= pService->m_u8ReplyMask; - } - - if (u8ReplyNeeded) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Sending answer(0x%X)...\n"), u8ReplyNeeded);); - - sendParameter.m_bResponse = true; - sendParameter.m_bAuthorative = true; - - bResult = _sendMDNSMessage(sendParameter); - } - DEBUG_EX_INFO( - else - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: No reply needed\n")); - } - ); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Something FAILED!\n"));); - m_pUDPContext->flush(); - } - - // - // Check and reset tiebreak-states - if (m_HostProbeInformation.m_bTiebreakNeeded) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: UNSOLVED tiebreak-need for host domain!\n"));); - m_HostProbeInformation.m_bTiebreakNeeded = false; - } - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - if (pService->m_ProbeInformation.m_bTiebreakNeeded) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: UNSOLVED tiebreak-need for service domain (%s.%s.%s)\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); - pService->m_ProbeInformation.m_bTiebreakNeeded = false; - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_parseResponse - - Responses are of interest in two cases: - 1. find domain name conflicts while probing - 2. get answers to service queries - - In both cases any included questions are ignored - - 1. If any answer has a domain name similar to one of the domain names we're planning to use (and are probing for), - then we've got a 'probing conflict'. The conflict has to be solved on our side of the conflict (eg. by - setting a new hostname and restart probing). The callback 'm_fnProbeResultCallback' is called with - 'p_bProbeResult=false' in this case. - - 2. Service queries like '_http._tcp.local' will (if available) produce PTR, SRV, TXT and A/AAAA answers. - All stored answers are pivoted by the service instance name (from the PTR record). Other answer parts, - like host domain or IP address are than attached to this element. - Any answer part carries a TTL, this is also stored (incl. the reception time); if the TTL is '0' the - answer (part) is withdrawn by the sender and should be removed from any cache. RFC 6762, 10.1 proposes to - set the caches TTL-value to 1 second in such a case and to delete the item only, if no update has - has taken place in this second. - Answer parts may arrive in 'unsorted' order, so they are grouped into three levels: - Level 1: PRT - names the service instance (and is used as pivot), voids all other parts if is withdrawn or outdates - Level 2: SRV - links the instance name to a host domain and port, voids A/AAAA parts if is withdrawn or outdates - TXT - links the instance name to services TXTs - Level 3: A/AAAA - links the host domain to an IP address -*/ -bool MDNSResponder::_parseResponse(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHeader) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse\n"));); - //DEBUG_EX_INFO(_udpDump();); - - bool bResult = false; - - // A response should be the result of a query or a probe - if ((_hasServiceQueriesWaitingForAnswers()) || // Waiting for query answers OR - (_hasProbesWaitingForAnswers())) // Probe responses - { - - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: Received a response\n")); - //_udpDump(); - ); - - bResult = true; - // - // Ignore questions here - stcMDNS_RRQuestion dummyRRQ; - for (uint16_t qd = 0; ((bResult) && (qd < p_MsgHeader.m_u16QDCount)); ++qd) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: Received a response containing a question... ignoring!\n"));); - bResult = _readRRQuestion(dummyRRQ); - } // for queries - - // - // Read and collect answers - stcMDNS_RRAnswer* pCollectedRRAnswers = 0; - uint32_t u32NumberOfAnswerRRs = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); - for (uint32_t an = 0; ((bResult) && (an < u32NumberOfAnswerRRs)); ++an) - { - stcMDNS_RRAnswer* pRRAnswer = 0; - if (((bResult = _readRRAnswer(pRRAnswer))) && - (pRRAnswer)) - { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: ADDING answer!\n"));); - pRRAnswer->m_pNext = pCollectedRRAnswers; - pCollectedRRAnswers = pRRAnswer; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: FAILED to read answer!\n"));); - if (pRRAnswer) - { - delete pRRAnswer; - pRRAnswer = 0; - } - bResult = false; - } - } // for answers - - // - // Process answers - if (bResult) - { - bResult = ((!pCollectedRRAnswers) || - (_processAnswers(pCollectedRRAnswers))); - } - else // Some failure while reading answers - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: FAILED to read answers!\n"));); - m_pUDPContext->flush(); - } - - // Delete collected answers - while (pCollectedRRAnswers) - { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: DELETING answer!\n"));); - stcMDNS_RRAnswer* pNextAnswer = pCollectedRRAnswers->m_pNext; - delete pCollectedRRAnswers; - pCollectedRRAnswers = pNextAnswer; - } - } - else // Received an unexpected response -> ignore - { - /* DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: Received an unexpected response... ignoring!\nDUMP:\n")); - bool bDumpResult = true; - for (uint16_t qd=0; ((bDumpResult) && (qd<p_MsgHeader.m_u16QDCount)); ++qd) { - stcMDNS_RRQuestion questionRR; - bDumpResult = _readRRQuestion(questionRR); - esp_yield(); - } // for questions - // Handle known answers - uint32_t u32Answers = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); - for (uint32_t an=0; ((bDumpResult) && (an<u32Answers)); ++an) { - stcMDNS_RRAnswer* pRRAnswer = 0; - bDumpResult = _readRRAnswer(pRRAnswer); - if (pRRAnswer) { - delete pRRAnswer; - pRRAnswer = 0; - } - esp_yield(); - } - );*/ - m_pUDPContext->flush(); - bResult = true; - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseResponse: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_processAnswers - Host: - A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 - AAAA (01Cx): eg. esp8266.local AAAA OP TTL 1234:5678::90 - PTR (0x0C, IP4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local - PTR (0x0C, IP6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local - Service: - PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local - PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local - SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local - TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 - -*/ -bool MDNSResponder::_processAnswers(const MDNSResponder::stcMDNS_RRAnswer* p_pAnswers) -{ - - bool bResult = false; - - if (p_pAnswers) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAnswers: Processing answers...\n"));); - bResult = true; - - // Answers may arrive in an unexpected order. So we loop our answers as long, as we - // can connect new information to service queries - bool bFoundNewKeyAnswer; - do - { - bFoundNewKeyAnswer = false; - - const stcMDNS_RRAnswer* pRRAnswer = p_pAnswers; - while ((pRRAnswer) && - (bResult)) - { - // 1. level answer (PTR) - if (AnswerType_PTR == pRRAnswer->answerType()) - { - // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local - bResult = _processPTRAnswer((stcMDNS_RRAnswerPTR*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new SRV or TXT answers to be linked to queries - } - // 2. level answers - // SRV -> host domain and port - else if (AnswerType_SRV == pRRAnswer->answerType()) - { - // eg. MyESP_http._tcp.local SRV xxxx xx yy zz 5000 esp8266.local - bResult = _processSRVAnswer((stcMDNS_RRAnswerSRV*)pRRAnswer, bFoundNewKeyAnswer); // May 'enable' new A/AAAA answers to be linked to queries - } - // TXT -> Txts - else if (AnswerType_TXT == pRRAnswer->answerType()) - { - // eg. MyESP_http._tcp.local TXT xxxx xx c#=1 - bResult = _processTXTAnswer((stcMDNS_RRAnswerTXT*)pRRAnswer); - } - // 3. level answers -#ifdef MDNS_IP4_SUPPORT - // A -> IP4Address - else if (AnswerType_A == pRRAnswer->answerType()) - { - // eg. esp8266.local A xxxx xx 192.168.2.120 - bResult = _processAAnswer((stcMDNS_RRAnswerA*)pRRAnswer); - } -#endif -#ifdef MDNS_IP6_SUPPORT - // AAAA -> IP6Address - else if (AnswerType_AAAA == pRRAnswer->answerType()) - { - // eg. esp8266.local AAAA xxxx xx 09cf::0c - bResult = _processAAAAAnswer((stcMDNS_RRAnswerAAAA*)pRRAnswer); - } -#endif - - // Finally check for probing conflicts - // Host domain - if ((ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) && - ((AnswerType_A == pRRAnswer->answerType()) || - (AnswerType_AAAA == pRRAnswer->answerType()))) - { - - stcMDNS_RRDomain hostDomain; - if ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (pRRAnswer->m_Header.m_Domain == hostDomain)) - { - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAnswers: Probing CONFLICT found with: %s.local\n"), m_pcHostname);); - _cancelProbingForHost(); - } - } - // Service domains - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - if ((ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) && - ((AnswerType_TXT == pRRAnswer->answerType()) || - (AnswerType_SRV == pRRAnswer->answerType()))) - { - - stcMDNS_RRDomain serviceDomain; - if ((_buildDomainForService(*pService, true, serviceDomain)) && - (pRRAnswer->m_Header.m_Domain == serviceDomain)) - { - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAnswers: Probing CONFLICT found with: %s.%s.%s\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); - _cancelProbingForService(*pService); - } - } - } - - pRRAnswer = pRRAnswer->m_pNext; // Next collected answer - } // while (answers) - } while ((bFoundNewKeyAnswer) && - (bResult)); - } // else: No answers provided - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAnswers: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_processPTRAnswer -*/ -bool MDNSResponder::_processPTRAnswer(const MDNSResponder::stcMDNS_RRAnswerPTR* p_pPTRAnswer, - bool& p_rbFoundNewKeyAnswer) -{ - - bool bResult = false; - - if ((bResult = (0 != p_pPTRAnswer))) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: Processing PTR answers...\n"));); - // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local - // Check pending service queries for eg. '_http._tcp' - - stcMDNSServiceQuery* pServiceQuery = _findNextServiceQueryByServiceType(p_pPTRAnswer->m_Header.m_Domain, 0); - while (pServiceQuery) - { - if (pServiceQuery->m_bAwaitingAnswers) - { - // Find answer for service domain (eg. MyESP._http._tcp.local) - stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForServiceDomain(p_pPTRAnswer->m_PTRDomain); - if (pSQAnswer) // existing answer - { - if (p_pPTRAnswer->m_u32TTL) // Received update message - { - pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); // Update TTL tag - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: Updated TTL(%d) for "), (int)p_pPTRAnswer->m_u32TTL); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR("\n")); - ); - } - else // received goodbye-message - { - pSQAnswer->m_TTLServiceDomain.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: 'Goodbye' received for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR("\n")); - ); - } - } - else if ((p_pPTRAnswer->m_u32TTL) && // Not just a goodbye-message - ((pSQAnswer = new stcMDNSServiceQuery::stcAnswer))) // Not yet included -> add answer - { - pSQAnswer->m_ServiceDomain = p_pPTRAnswer->m_PTRDomain; - pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_ServiceDomain; - pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); - pSQAnswer->releaseServiceDomain(); - - bResult = pServiceQuery->addAnswer(pSQAnswer); - p_rbFoundNewKeyAnswer = true; - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_ServiceDomain), true); - } - } - } - pServiceQuery = _findNextServiceQueryByServiceType(p_pPTRAnswer->m_Header.m_Domain, pServiceQuery); - } - } // else: No p_pPTRAnswer - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_processSRVAnswer -*/ -bool MDNSResponder::_processSRVAnswer(const MDNSResponder::stcMDNS_RRAnswerSRV* p_pSRVAnswer, - bool& p_rbFoundNewKeyAnswer) -{ - - bool bResult = false; - - if ((bResult = (0 != p_pSRVAnswer))) - { - // eg. MyESP._http._tcp.local SRV xxxx xx yy zz 5000 esp8266.local - - stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; - while (pServiceQuery) - { - stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForServiceDomain(p_pSRVAnswer->m_Header.m_Domain); - if (pSQAnswer) // Answer for this service domain (eg. MyESP._http._tcp.local) available - { - if (p_pSRVAnswer->m_u32TTL) // First or update message (TTL != 0) - { - pSQAnswer->m_TTLHostDomainAndPort.set(p_pSRVAnswer->m_u32TTL); // Update TTL tag - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: Updated TTL(%d) for "), (int)p_pSRVAnswer->m_u32TTL); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); - ); - // Host domain & Port - if ((pSQAnswer->m_HostDomain != p_pSRVAnswer->m_SRVDomain) || - (pSQAnswer->m_u16Port != p_pSRVAnswer->m_u16Port)) - { - - pSQAnswer->m_HostDomain = p_pSRVAnswer->m_SRVDomain; - pSQAnswer->releaseHostDomain(); - pSQAnswer->m_u16Port = p_pSRVAnswer->m_u16Port; - pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_HostDomainAndPort; - - p_rbFoundNewKeyAnswer = true; - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_HostDomainAndPort), true); - } - } - } - else // Goodby message - { - pSQAnswer->m_TTLHostDomainAndPort.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: 'Goodbye' received for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); - ); - } - } - pServiceQuery = pServiceQuery->m_pNext; - } // while(service query) - } // else: No p_pSRVAnswer - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_processTXTAnswer -*/ -bool MDNSResponder::_processTXTAnswer(const MDNSResponder::stcMDNS_RRAnswerTXT* p_pTXTAnswer) -{ - - bool bResult = false; - - if ((bResult = (0 != p_pTXTAnswer))) - { - // eg. MyESP._http._tcp.local TXT xxxx xx c#=1 - - stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; - while (pServiceQuery) - { - stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForServiceDomain(p_pTXTAnswer->m_Header.m_Domain); - if (pSQAnswer) // Answer for this service domain (eg. MyESP._http._tcp.local) available - { - if (p_pTXTAnswer->m_u32TTL) // First or update message - { - pSQAnswer->m_TTLTxts.set(p_pTXTAnswer->m_u32TTL); // Update TTL tag - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: Updated TTL(%d) for "), (int)p_pTXTAnswer->m_u32TTL); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); - ); - if (!pSQAnswer->m_Txts.compare(p_pTXTAnswer->m_Txts)) - { - pSQAnswer->m_Txts = p_pTXTAnswer->m_Txts; - pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_Txts; - pSQAnswer->releaseTxts(); - - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_Txts), true); - } - } - } - else // Goodby message - { - pSQAnswer->m_TTLTxts.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: 'Goodbye' received for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); - ); - } - } - pServiceQuery = pServiceQuery->m_pNext; - } // while(service query) - } // else: No p_pTXTAnswer - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: FAILED!\n")); - }); - return bResult; -} - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::_processAAnswer -*/ -bool MDNSResponder::_processAAnswer(const MDNSResponder::stcMDNS_RRAnswerA* p_pAAnswer) -{ - - bool bResult = false; - - if ((bResult = (0 != p_pAAnswer))) - { - // eg. esp8266.local A xxxx xx 192.168.2.120 - - stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; - while (pServiceQuery) - { - stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForHostDomain(p_pAAnswer->m_Header.m_Domain); - if (pSQAnswer) // Answer for this host domain (eg. esp8266.local) available - { - stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address = pSQAnswer->findIP4Address(p_pAAnswer->m_IPAddress); - if (pIP4Address) - { - // Already known IP4 address - if (p_pAAnswer->m_u32TTL) // Valid TTL -> Update answers TTL - { - pIP4Address->m_TTL.set(p_pAAnswer->m_u32TTL); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL(%d) for "), (int)p_pAAnswer->m_u32TTL); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP4Address (%s)\n"), pIP4Address->m_IPAddress.toString().c_str()); - ); - } - else // 'Goodbye' message for known IP4 address - { - pIP4Address->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: 'Goodbye' received for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP4 address (%s)\n"), pIP4Address->m_IPAddress.toString().c_str()); - ); - } - } - else - { - // Until now unknown IP4 address -> Add (if the message isn't just a 'Goodbye' note) - if (p_pAAnswer->m_u32TTL) // NOT just a 'Goodbye' message - { - pIP4Address = new stcMDNSServiceQuery::stcAnswer::stcIP4Address(p_pAAnswer->m_IPAddress, p_pAAnswer->m_u32TTL); - if ((pIP4Address) && - (pSQAnswer->addIP4Address(pIP4Address))) - { - - pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_IP4Address; - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_IP4Address), true); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: FAILED to add IP4 address (%s)!\n"), p_pAAnswer->m_IPAddress.toString().c_str());); - } - } - } - } - pServiceQuery = pServiceQuery->m_pNext; - } // while(service query) - } // else: No p_pAAnswer - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: FAILED!\n")); - }); - return bResult; -} -#endif - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::_processAAAAAnswer -*/ -bool MDNSResponder::_processAAAAAnswer(const MDNSResponder::stcMDNS_RRAnswerAAAA* p_pAAAAAnswer) -{ - - bool bResult = false; - - if ((bResult = (0 != p_pAAAAAnswer))) - { - // eg. esp8266.local AAAA xxxx xx 0bf3::0c - - stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; - while (pServiceQuery) - { - stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->findAnswerForHostDomain(p_pAAAAAnswer->m_Header.m_Domain); - if (pSQAnswer) // Answer for this host domain (eg. esp8266.local) available - { - stcIP6Address* pIP6Address = pSQAnswer->findIP6Address(p_pAAAAAnswer->m_IPAddress); - if (pIP6Address) - { - // Already known IP6 address - if (p_pAAAAAnswer->m_u32TTL) // Valid TTL -> Update answers TTL - { - pIP6Address->m_TTL.set(p_pAAAAAnswer->m_u32TTL); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL(%lu) for "), p_pAAAAAnswer->m_u32TTL); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP6 address (%s)\n"), pIP6Address->m_IPAddress.toString().c_str()); - ); - } - else // 'Goodbye' message for known IP6 address - { - pIP6Address->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: 'Goodbye' received for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP6 address (%s)\n"), pIP6Address->m_IPAddress.toString().c_str()); - ); - } - } - else - { - // Until now unknown IP6 address -> Add (if the message isn't just a 'Goodbye' note) - if (p_pAAAAAnswer->m_u32TTL) // NOT just a 'Goodbye' message - { - pIP6Address = new stcIP6Address(p_pAAAAAnswer->m_IPAddress, p_pAAAAAnswer->m_u32TTL); - if ((pIP6Address) && - (pSQAnswer->addIP6Address(pIP6Address))) - { - - pSQAnswer->m_u32ContentFlags |= ServiceQueryAnswerType_IP6Address; - - if (pServiceQuery->m_fnCallback) - { - pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), ServiceQueryAnswerType_IP6Address, true, pServiceQuery->m_pUserdata); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: FAILED to add IP6 address (%s)!\n"), p_pAAAAAnswer->m_IPAddress.toString().c_str());); - } - } - } - } - pServiceQuery = pServiceQuery->m_pNext; - } // while(service query) - } // else: No p_pAAAAAnswer - - return bResult; -} -#endif - - -/* - PROBING -*/ - -/* - MDNSResponder::_updateProbeStatus - - Manages the (outgoing) probing process. - - If probing has not been started yet (ProbingStatus_NotStarted), the initial delay (see RFC 6762) is determined and - the process is started - - After timeout (of initial or subsequential delay) a probe message is send out for three times. If the message has - already been sent out three times, the probing has been successful and is finished. - - Conflict management is handled in '_parseResponse ff.' - Tiebraking is handled in 'parseQuery ff.' -*/ -bool MDNSResponder::_updateProbeStatus(void) -{ - - bool bResult = true; - - // - // Probe host domain - if ((ProbingStatus_ReadyToStart == m_HostProbeInformation.m_ProbingStatus) && // Ready to get started AND - //TODO: Fix the following to allow Ethernet shield or other interfaces - (_getResponseMulticastInterface() != IPAddress())) // Has IP address - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Starting host probing...\n"));); - - // First probe delay SHOULD be random 0-250 ms - m_HostProbeInformation.m_Timeout.reset(rand() % MDNS_PROBE_DELAY); - m_HostProbeInformation.m_ProbingStatus = ProbingStatus_InProgress; - } - else if ((ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing AND - (m_HostProbeInformation.m_Timeout.expired())) // Time for next probe - { - - if (MDNS_PROBE_COUNT > m_HostProbeInformation.m_u8SentCount) // Send next probe - { - if ((bResult = _sendHostProbe())) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Did sent host probe\n\n"));); - m_HostProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); - ++m_HostProbeInformation.m_u8SentCount; - } - } - else // Probing finished - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done host probing.\n"));); - m_HostProbeInformation.m_ProbingStatus = ProbingStatus_Done; - m_HostProbeInformation.m_Timeout.resetToNeverExpires(); - if (m_HostProbeInformation.m_fnHostProbeResultCallback) - { - m_HostProbeInformation.m_fnHostProbeResultCallback(m_pcHostname, true); - } - - // Prepare to announce host - m_HostProbeInformation.m_u8SentCount = 0; - m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Prepared host announcing.\n\n"));); - } - } // else: Probing already finished OR waiting for next time slot - else if ((ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus) && - (m_HostProbeInformation.m_Timeout.expired())) - { - - if ((bResult = _announce(true, false))) // Don't announce services here - { - ++m_HostProbeInformation.m_u8SentCount; - - if (MDNS_ANNOUNCE_COUNT > m_HostProbeInformation.m_u8SentCount) - { - m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing host (%d).\n\n"), m_HostProbeInformation.m_u8SentCount);); - } - else - { - m_HostProbeInformation.m_Timeout.resetToNeverExpires(); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done host announcing.\n\n"));); - } - } - } - - // - // Probe services - for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) - { - if (ProbingStatus_ReadyToStart == pService->m_ProbeInformation.m_ProbingStatus) // Ready to get started - { - - pService->m_ProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); // More or equal than first probe for host domain - pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_InProgress; - } - else if ((ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing AND - (pService->m_ProbeInformation.m_Timeout.expired())) // Time for next probe - { - - if (MDNS_PROBE_COUNT > pService->m_ProbeInformation.m_u8SentCount) // Send next probe - { - if ((bResult = _sendServiceProbe(*pService))) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Did sent service probe (%u)\n\n"), (pService->m_ProbeInformation.m_u8SentCount + 1));); - pService->m_ProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); - ++pService->m_ProbeInformation.m_u8SentCount; - } - } - else // Probing finished - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done service probing %s.%s.%s\n\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); - pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_Done; - pService->m_ProbeInformation.m_Timeout.resetToNeverExpires(); - if (pService->m_ProbeInformation.m_fnServiceProbeResultCallback) - { - pService->m_ProbeInformation.m_fnServiceProbeResultCallback(pService->m_pcName, pService, true); - } - // Prepare to announce service - pService->m_ProbeInformation.m_u8SentCount = 0; - pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Prepared service announcing.\n\n"));); - } - } // else: Probing already finished OR waiting for next time slot - else if ((ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus) && - (pService->m_ProbeInformation.m_Timeout.expired())) - { - - if ((bResult = _announceService(*pService))) // Announce service - { - ++pService->m_ProbeInformation.m_u8SentCount; - - if (MDNS_ANNOUNCE_COUNT > pService->m_ProbeInformation.m_u8SentCount) - { - pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing service %s.%s.%s (%d)\n\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_ProbeInformation.m_u8SentCount);); - } - else - { - pService->m_ProbeInformation.m_Timeout.resetToNeverExpires(); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done service announcing for %s.%s.%s\n\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); - } - } - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: FAILED!\n\n")); - }); - return bResult; -} - -/* - MDNSResponder::_resetProbeStatus - - Resets the probe status. - If 'p_bRestart' is set, the status is set to ProbingStatus_NotStarted. Consequently, - when running 'updateProbeStatus' (which is done in every '_update' loop), the probing - process is restarted. -*/ -bool MDNSResponder::_resetProbeStatus(bool p_bRestart /*= true*/) -{ - - m_HostProbeInformation.clear(false); - m_HostProbeInformation.m_ProbingStatus = (p_bRestart ? ProbingStatus_ReadyToStart : ProbingStatus_Done); - - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - pService->m_ProbeInformation.clear(false); - pService->m_ProbeInformation.m_ProbingStatus = (p_bRestart ? ProbingStatus_ReadyToStart : ProbingStatus_Done); - } - return true; -} - -/* - MDNSResponder::_hasProbesWaitingForAnswers -*/ -bool MDNSResponder::_hasProbesWaitingForAnswers(void) const -{ - - bool bResult = ((ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing - (0 < m_HostProbeInformation.m_u8SentCount)); // And really probing - - for (stcMDNSService* pService = m_pServices; ((!bResult) && (pService)); pService = pService->m_pNext) - { - bResult = ((ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing - (0 < pService->m_ProbeInformation.m_u8SentCount)); // And really probing - } - return bResult; -} - -/* - MDNSResponder::_sendHostProbe - - Asks (probes) in the local network for the planned host domain - - (eg. esp8266.local) - - To allow 'tiebreaking' (see '_parseQuery'), the answers for these questions are delivered in - the 'knwon answers' section of the query. - Host domain: - - A/AAAA (eg. esp8266.esp -> 192.168.2.120) -*/ -bool MDNSResponder::_sendHostProbe(void) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendHostProbe (%s, %lu)\n"), m_pcHostname, millis());); - - bool bResult = true; - - // Requests for host domain - stcMDNSSendParameter sendParameter; - sendParameter.m_bCacheFlush = false; // RFC 6762 10.2 - - sendParameter.m_pQuestions = new stcMDNS_RRQuestion; - if (((bResult = (0 != sendParameter.m_pQuestions))) && - ((bResult = _buildDomainForHost(m_pcHostname, sendParameter.m_pQuestions->m_Header.m_Domain)))) - { - - //sendParameter.m_pQuestions->m_bUnicast = true; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet - - // Add known answers -#ifdef MDNS_IP4_SUPPORT - sendParameter.m_u8HostReplyMask |= ContentFlag_A; // Add A answer -#endif -#ifdef MDNS_IP6_SUPPORT - sendParameter.m_u8HostReplyMask |= ContentFlag_AAAA; // Add AAAA answer -#endif - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendHostProbe: FAILED to create host question!\n"));); - if (sendParameter.m_pQuestions) - { - delete sendParameter.m_pQuestions; - sendParameter.m_pQuestions = 0; - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendHostProbe: FAILED!\n")); - }); - return ((bResult) && - (_sendMDNSMessage(sendParameter))); -} - -/* - MDNSResponder::_sendServiceProbe - - Asks (probes) in the local network for the planned service instance domain - - (eg. MyESP._http._tcp.local). - - To allow 'tiebreaking' (see '_parseQuery'), the answers for these questions are delivered in - the 'knwon answers' section of the query. - Service domain: - - SRV (eg. MyESP._http._tcp.local -> 5000 esp8266.local) - - PTR NAME (eg. _http._tcp.local -> MyESP._http._tcp.local) (TODO: Check if needed, maybe TXT is better) -*/ -bool MDNSResponder::_sendServiceProbe(stcMDNSService& p_rService) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendServiceProbe (%s.%s.%s, %lu)\n"), (p_rService.m_pcName ? : m_pcHostname), p_rService.m_pcService, p_rService.m_pcProtocol, millis());); - - bool bResult = true; - - // Requests for service instance domain - stcMDNSSendParameter sendParameter; - sendParameter.m_bCacheFlush = false; // RFC 6762 10.2 - - sendParameter.m_pQuestions = new stcMDNS_RRQuestion; - if (((bResult = (0 != sendParameter.m_pQuestions))) && - ((bResult = _buildDomainForService(p_rService, true, sendParameter.m_pQuestions->m_Header.m_Domain)))) - { - - sendParameter.m_pQuestions->m_bUnicast = true; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet - - // Add known answers - p_rService.m_u8ReplyMask = (ContentFlag_SRV | ContentFlag_PTR_NAME); // Add SRV and PTR NAME answers - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendServiceProbe: FAILED to create service question!\n"));); - if (sendParameter.m_pQuestions) - { - delete sendParameter.m_pQuestions; - sendParameter.m_pQuestions = 0; - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendServiceProbe: FAILED!\n")); - }); - return ((bResult) && - (_sendMDNSMessage(sendParameter))); -} - -/* - MDNSResponder::_cancelProbingForHost -*/ -bool MDNSResponder::_cancelProbingForHost(void) -{ - - bool bResult = false; - - m_HostProbeInformation.clear(false); - // Send host notification - if (m_HostProbeInformation.m_fnHostProbeResultCallback) - { - m_HostProbeInformation.m_fnHostProbeResultCallback(m_pcHostname, false); - - bResult = true; - } - - for (stcMDNSService* pService = m_pServices; ((!bResult) && (pService)); pService = pService->m_pNext) - { - bResult = _cancelProbingForService(*pService); - } - return bResult; -} - -/* - MDNSResponder::_cancelProbingForService -*/ -bool MDNSResponder::_cancelProbingForService(stcMDNSService& p_rService) -{ - - bool bResult = false; - - p_rService.m_ProbeInformation.clear(false); - // Send notification - if (p_rService.m_ProbeInformation.m_fnServiceProbeResultCallback) - { - p_rService.m_ProbeInformation.m_fnServiceProbeResultCallback(p_rService.m_pcName, &p_rService, false); - bResult = true; - } - return bResult; -} - - - -/** - ANNOUNCING -*/ - -/* - MDNSResponder::_announce - - Announces the host domain: - - A/AAAA (eg. esp8266.local -> 192.168.2.120) - - PTR (eg. 192.168.2.120.in-addr.arpa -> esp8266.local) - - and all presented services: - - PTR_TYPE (_services._dns-sd._udp.local -> _http._tcp.local) - - PTR_NAME (eg. _http._tcp.local -> MyESP8266._http._tcp.local) - - SRV (eg. MyESP8266._http._tcp.local -> 5000 esp8266.local) - - TXT (eg. MyESP8266._http._tcp.local -> c#=1) - - Goodbye (Un-Announcing) for the host domain and all services is also handled here. - Goodbye messages are created by setting the TTL for the answer to 0, this happens - inside the '_writeXXXAnswer' procs via 'sendParameter.m_bUnannounce = true' -*/ -bool MDNSResponder::_announce(bool p_bAnnounce, - bool p_bIncludeServices) -{ - - bool bResult = false; - - stcMDNSSendParameter sendParameter; - if (ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus) - { - - bResult = true; - - sendParameter.m_bResponse = true; // Announces are 'Unsolicited authorative responses' - sendParameter.m_bAuthorative = true; - sendParameter.m_bUnannounce = !p_bAnnounce; // When unannouncing, the TTL is set to '0' while creating the answers - - // Announce host - sendParameter.m_u8HostReplyMask = 0; -#ifdef MDNS_IP4_SUPPORT - sendParameter.m_u8HostReplyMask |= ContentFlag_A; // A answer - sendParameter.m_u8HostReplyMask |= ContentFlag_PTR_IP4; // PTR_IP4 answer -#endif -#ifdef MDNS_IP6_SUPPORT - sendParameter.m_u8HostReplyMask |= ContentFlag_AAAA; // AAAA answer - sendParameter.m_u8HostReplyMask |= ContentFlag_PTR_IP6; // PTR_IP6 answer -#endif - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: Announcing host %s (content 0x%X)\n"), m_pcHostname, sendParameter.m_u8HostReplyMask);); - - if (p_bIncludeServices) - { - // Announce services (service type, name, SRV (location) and TXTs) - for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) - { - if (ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus) - { - pService->m_u8ReplyMask = (ContentFlag_PTR_TYPE | ContentFlag_PTR_NAME | ContentFlag_SRV | ContentFlag_TXT); - - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: Announcing service %s.%s.%s (content %u)\n"), (pService->m_pcName ? : m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_u8ReplyMask);); - } - } - } - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: FAILED!\n")); - }); - return ((bResult) && - (_sendMDNSMessage(sendParameter))); -} - -/* - MDNSResponder::_announceService -*/ -bool MDNSResponder::_announceService(stcMDNSService& p_rService, - bool p_bAnnounce /*= true*/) -{ - - bool bResult = false; - - stcMDNSSendParameter sendParameter; - if (ProbingStatus_Done == p_rService.m_ProbeInformation.m_ProbingStatus) - { - - sendParameter.m_bResponse = true; // Announces are 'Unsolicited authorative responses' - sendParameter.m_bAuthorative = true; - sendParameter.m_bUnannounce = !p_bAnnounce; // When unannouncing, the TTL is set to '0' while creating the answers - - // DON'T announce host - sendParameter.m_u8HostReplyMask = 0; - - // Announce services (service type, name, SRV (location) and TXTs) - p_rService.m_u8ReplyMask = (ContentFlag_PTR_TYPE | ContentFlag_PTR_NAME | ContentFlag_SRV | ContentFlag_TXT); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announceService: Announcing service %s.%s.%s (content 0x%X)\n"), (p_rService.m_pcName ? : m_pcHostname), p_rService.m_pcService, p_rService.m_pcProtocol, p_rService.m_u8ReplyMask);); - - bResult = true; - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announceService: FAILED!\n")); - }); - return ((bResult) && - (_sendMDNSMessage(sendParameter))); -} - - -/** - SERVICE QUERY CACHE -*/ - -/* - MDNSResponder::_hasServiceQueriesWaitingForAnswers -*/ -bool MDNSResponder::_hasServiceQueriesWaitingForAnswers(void) const -{ - - bool bOpenQueries = false; - - for (stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; pServiceQuery; pServiceQuery = pServiceQuery->m_pNext) - { - if (pServiceQuery->m_bAwaitingAnswers) - { - bOpenQueries = true; - break; - } - } - return bOpenQueries; -} - -/* - MDNSResponder::_checkServiceQueryCache - - For any 'living' service query (m_bAwaitingAnswers == true) all available answers (their components) - are checked for topicality based on the stored reception time and the answers TTL. - When the components TTL is outlasted by more than 80%, a new question is generated, to get updated information. - When no update arrived (in time), the component is removed from the answer (cache). - -*/ -bool MDNSResponder::_checkServiceQueryCache(void) -{ - - bool bResult = true; - - DEBUG_EX_INFO( - bool printedInfo = false; - ); - for (stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; ((bResult) && (pServiceQuery)); pServiceQuery = pServiceQuery->m_pNext) - { - - // - // Resend dynamic service queries, if not already done often enough - if ((!pServiceQuery->m_bLegacyQuery) && - (MDNS_DYNAMIC_QUERY_RESEND_COUNT > pServiceQuery->m_u8SentCount) && - (pServiceQuery->m_ResendTimeout.expired())) - { - - if ((bResult = _sendMDNSServiceQuery(*pServiceQuery))) - { - ++pServiceQuery->m_u8SentCount; - pServiceQuery->m_ResendTimeout.reset((MDNS_DYNAMIC_QUERY_RESEND_COUNT > pServiceQuery->m_u8SentCount) - ? (MDNS_DYNAMIC_QUERY_RESEND_DELAY * (pServiceQuery->m_u8SentCount - 1)) - : esp8266::polledTimeout::oneShotMs::neverExpires); - } - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: %s to resend service query!"), (bResult ? "Succeeded" : "FAILED")); - printedInfo = true; - ); - } - - // - // Schedule updates for cached answers - if (pServiceQuery->m_bAwaitingAnswers) - { - stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->m_pAnswers; - while ((bResult) && - (pSQAnswer)) - { - stcMDNSServiceQuery::stcAnswer* pNextSQAnswer = pSQAnswer->m_pNext; - - // 1. level answer - if ((bResult) && - (pSQAnswer->m_TTLServiceDomain.flagged())) - { - - if (!pSQAnswer->m_TTLServiceDomain.finalTimeoutLevel()) - { - - bResult = ((_sendMDNSServiceQuery(*pServiceQuery)) && - (pSQAnswer->m_TTLServiceDomain.restart())); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: PTR update scheduled for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" %s\n"), (bResult ? "OK" : "FAILURE")); - printedInfo = true; - ); - } - else - { - // Timed out! -> Delete - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_ServiceDomain), false); - } - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove PTR answer for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR("\n")); - printedInfo = true; - ); - - bResult = pServiceQuery->removeAnswer(pSQAnswer); - pSQAnswer = 0; - continue; // Don't use this answer anymore - } - } // ServiceDomain flagged - - // 2. level answers - // HostDomain & Port (from SRV) - if ((bResult) && - (pSQAnswer->m_TTLHostDomainAndPort.flagged())) - { - - if (!pSQAnswer->m_TTLHostDomainAndPort.finalTimeoutLevel()) - { - - bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_SRV)) && - (pSQAnswer->m_TTLHostDomainAndPort.restart())); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: SRV update scheduled for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" host domain and port %s\n"), (bResult ? "OK" : "FAILURE")); - printedInfo = true; - ); - } - else - { - // Timed out! -> Delete - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove SRV answer for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); - printedInfo = true; - ); - // Delete - pSQAnswer->m_HostDomain.clear(); - pSQAnswer->releaseHostDomain(); - pSQAnswer->m_u16Port = 0; - pSQAnswer->m_TTLHostDomainAndPort.set(0); - uint32_t u32ContentFlags = ServiceQueryAnswerType_HostDomainAndPort; - // As the host domain is the base for the IP4- and IP6Address, remove these too -#ifdef MDNS_IP4_SUPPORT - pSQAnswer->releaseIP4Addresses(); - u32ContentFlags |= ServiceQueryAnswerType_IP4Address; -#endif -#ifdef MDNS_IP6_SUPPORT - pSQAnswer->releaseIP6Addresses(); - u32ContentFlags |= ServiceQueryAnswerType_IP6Address; -#endif - - // Remove content flags for deleted answer parts - pSQAnswer->m_u32ContentFlags &= ~u32ContentFlags; - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(u32ContentFlags), false); - } - } - } // HostDomainAndPort flagged - - // Txts (from TXT) - if ((bResult) && - (pSQAnswer->m_TTLTxts.flagged())) - { - - if (!pSQAnswer->m_TTLTxts.finalTimeoutLevel()) - { - - bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_TXT)) && - (pSQAnswer->m_TTLTxts.restart())); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: TXT update scheduled for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" TXTs %s\n"), (bResult ? "OK" : "FAILURE")); - printedInfo = true; - ); - } - else - { - // Timed out! -> Delete - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove TXT answer for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); - printedInfo = true; - ); - // Delete - pSQAnswer->m_Txts.clear(); - pSQAnswer->m_TTLTxts.set(0); - - // Remove content flags for deleted answer parts - pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_Txts; - - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_Txts), false); - } - } - } // TXTs flagged - - // 3. level answers -#ifdef MDNS_IP4_SUPPORT - // IP4Address (from A) - stcMDNSServiceQuery::stcAnswer::stcIP4Address* pIP4Address = pSQAnswer->m_pIP4Addresses; - bool bAUpdateQuerySent = false; - while ((pIP4Address) && - (bResult)) - { - - stcMDNSServiceQuery::stcAnswer::stcIP4Address* pNextIP4Address = pIP4Address->m_pNext; // Get 'next' early, as 'current' may be deleted at the end... - - if (pIP4Address->m_TTL.flagged()) - { - - if (!pIP4Address->m_TTL.finalTimeoutLevel()) // Needs update - { - - if ((bAUpdateQuerySent) || - ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_A)))) - { - - pIP4Address->m_TTL.restart(); - bAUpdateQuerySent = true; - - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: IP4 update scheduled for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP4 address (%s)\n"), (pIP4Address->m_IPAddress.toString().c_str())); - printedInfo = true; - ); - } - } - else - { - // Timed out! -> Delete - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove IP4 answer for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP4 address\n")); - printedInfo = true; - ); - pSQAnswer->removeIP4Address(pIP4Address); - if (!pSQAnswer->m_pIP4Addresses) // NO IP4 address left -> remove content flag - { - pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_IP4Address; - } - // Notify client - if (pServiceQuery->m_fnCallback) - { - MDNSServiceInfo serviceInfo(*this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)); - pServiceQuery->m_fnCallback(serviceInfo, static_cast<AnswerType>(ServiceQueryAnswerType_IP4Address), false); - } - } - } // IP4 flagged - - pIP4Address = pNextIP4Address; // Next - } // while -#endif -#ifdef MDNS_IP6_SUPPORT - // IP6Address (from AAAA) - stcMDNSServiceQuery::stcAnswer::stcIP6Address* pIP6Address = pSQAnswer->m_pIP6Addresses; - bool bAAAAUpdateQuerySent = false; - while ((pIP6Address) && - (bResult)) - { - - stcMDNSServiceQuery::stcAnswer::stcIP6Address* pNextIP6Address = pIP6Address->m_pNext; // Get 'next' early, as 'current' may be deleted at the end... - - if (pIP6Address->m_TTL.flagged()) - { - - if (!pIP6Address->m_TTL.finalTimeoutLevel()) // Needs update - { - - if ((bAAAAUpdateQuerySent) || - ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) - { - - pIP6Address->m_TTL.restart(); - bAAAAUpdateQuerySent = true; - - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: IP6 update scheduled for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP6 address (%s)\n"), (pIP6Address->m_IPAddress.toString().c_str())); - printedInfo = true; - ); - } - } - else - { - // Timed out! -> Delete - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove answer for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP6Address\n")); - printedInfo = true; - ); - pSQAnswer->removeIP6Address(pIP6Address); - if (!pSQAnswer->m_pIP6Addresses) // NO IP6 address left -> remove content flag - { - pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_IP6Address; - } - // Notify client - if (pServiceQuery->m_fnCallback) - { - pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), ServiceQueryAnswerType_IP6Address, false, pServiceQuery->m_pUserdata); - } - } - } // IP6 flagged - - pIP6Address = pNextIP6Address; // Next - } // while -#endif - pSQAnswer = pNextSQAnswer; - } - } - } - DEBUG_EX_INFO( - if (printedInfo) -{ - DEBUG_OUTPUT.printf_P(PSTR("\n")); - } - ); - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: FAILED!\n")); - }); - return bResult; -} - - -/* - MDNSResponder::_replyMaskForHost - - Determines the relavant host answers for the given question. - - A question for the hostname (eg. esp8266.local) will result in an A/AAAA (eg. 192.168.2.129) reply. - - A question for the reverse IP address (eg. 192-168.2.120.inarpa.arpa) will result in an PTR_IP4 (eg. esp8266.local) reply. - - In addition, a full name match (question domain == host domain) is marked. -*/ -uint8_t MDNSResponder::_replyMaskForHost(const MDNSResponder::stcMDNS_RRHeader& p_RRHeader, - bool* p_pbFullNameMatch /*= 0*/) const -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForHost\n"));); - - uint8_t u8ReplyMask = 0; - (p_pbFullNameMatch ? *p_pbFullNameMatch = false : 0); - - if ((DNS_RRCLASS_IN == p_RRHeader.m_Attributes.m_u16Class) || - (DNS_RRCLASS_ANY == p_RRHeader.m_Attributes.m_u16Class)) - { - - if ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) - { - // PTR request -#ifdef MDNS_IP4_SUPPORT - stcMDNS_RRDomain reverseIP4Domain; - if ((_buildDomainForReverseIP4(_getResponseMulticastInterface(), reverseIP4Domain)) && - (p_RRHeader.m_Domain == reverseIP4Domain)) - { - // Reverse domain match - u8ReplyMask |= ContentFlag_PTR_IP4; - } -#endif -#ifdef MDNS_IP6_SUPPORT - // TODO -#endif - } // Address qeuest - - stcMDNS_RRDomain hostDomain; - if ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (p_RRHeader.m_Domain == hostDomain)) // Host domain match - { - - (p_pbFullNameMatch ? (*p_pbFullNameMatch = true) : (0)); - -#ifdef MDNS_IP4_SUPPORT - if ((DNS_RRTYPE_A == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) - { - // IP4 address request - u8ReplyMask |= ContentFlag_A; - } -#endif -#ifdef MDNS_IP6_SUPPORT - if ((DNS_RRTYPE_AAAA == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) - { - // IP6 address request - u8ReplyMask |= ContentFlag_AAAA; - } -#endif - } - } - else - { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForHost: INVALID RR-class (0x%04X)!\n"), p_RRHeader.m_Attributes.m_u16Class);); - } - DEBUG_EX_INFO(if (u8ReplyMask) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForHost: 0x%X\n"), u8ReplyMask); - }); - return u8ReplyMask; -} - -/* - MDNSResponder::_replyMaskForService - - Determines the relevant service answers for the given question - - A PTR dns-sd service enum question (_services.dns-sd._udp.local) will result into an PTR_TYPE (eg. _http._tcp.local) answer - - A PTR service type question (eg. _http._tcp.local) will result into an PTR_NAME (eg. MyESP._http._tcp.local) answer - - A PTR service name question (eg. MyESP._http._tcp.local) will result into an PTR_NAME (eg. MyESP._http._tcp.local) answer - - A SRV service name question (eg. MyESP._http._tcp.local) will result into an SRV (eg. 5000 MyESP.local) answer - - A TXT service name question (eg. MyESP._http._tcp.local) will result into an TXT (eg. c#=1) answer - - In addition, a full name match (question domain == service instance domain) is marked. -*/ -uint8_t MDNSResponder::_replyMaskForService(const MDNSResponder::stcMDNS_RRHeader& p_RRHeader, - const MDNSResponder::stcMDNSService& p_Service, - bool* p_pbFullNameMatch /*= 0*/) const -{ - - uint8_t u8ReplyMask = 0; - (p_pbFullNameMatch ? *p_pbFullNameMatch = false : 0); - - if ((DNS_RRCLASS_IN == p_RRHeader.m_Attributes.m_u16Class) || - (DNS_RRCLASS_ANY == p_RRHeader.m_Attributes.m_u16Class)) - { - - stcMDNS_RRDomain DNSSDDomain; - if ((_buildDomainForDNSSD(DNSSDDomain)) && // _services._dns-sd._udp.local - (p_RRHeader.m_Domain == DNSSDDomain) && - ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type))) - { - // Common service info requested - u8ReplyMask |= ContentFlag_PTR_TYPE; - } - - stcMDNS_RRDomain serviceDomain; - if ((_buildDomainForService(p_Service, false, serviceDomain)) && // eg. _http._tcp.local - (p_RRHeader.m_Domain == serviceDomain) && - ((DNS_RRTYPE_PTR == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type))) - { - // Special service info requested - u8ReplyMask |= ContentFlag_PTR_NAME; - } - - if ((_buildDomainForService(p_Service, true, serviceDomain)) && // eg. MyESP._http._tcp.local - (p_RRHeader.m_Domain == serviceDomain)) - { - - (p_pbFullNameMatch ? (*p_pbFullNameMatch = true) : (0)); - - if ((DNS_RRTYPE_SRV == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) - { - // Instance info SRV requested - u8ReplyMask |= ContentFlag_SRV; - } - if ((DNS_RRTYPE_TXT == p_RRHeader.m_Attributes.m_u16Type) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) - { - // Instance info TXT requested - u8ReplyMask |= ContentFlag_TXT; - } - } - } - else - { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForService: INVALID RR-class (0x%04X)!\n"), p_RRHeader.m_Attributes.m_u16Class);); - } - DEBUG_EX_INFO(if (u8ReplyMask) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForService(%s.%s.%s): 0x%X\n"), p_Service.m_pcName, p_Service.m_pcService, p_Service.m_pcProtocol, u8ReplyMask); - }); - return u8ReplyMask; -} - -} // namespace MDNSImplementation - -} // namespace esp8266 diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Helpers.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Helpers.cpp deleted file mode 100644 index d23941ce53..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Helpers.cpp +++ /dev/null @@ -1,850 +0,0 @@ -/* - LEAmDNS_Helpers.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#include "lwip/igmp.h" - -#include "LEAmDNS_lwIPdefs.h" -#include "LEAmDNS_Priv.h" - - -namespace -{ - -/* - strrstr (static) - - Backwards search for p_pcPattern in p_pcString - Based on: https://stackoverflow.com/a/1634398/2778898 - -*/ -const char* strrstr(const char*__restrict p_pcString, const char*__restrict p_pcPattern) -{ - - const char* pcResult = 0; - - size_t stStringLength = (p_pcString ? strlen(p_pcString) : 0); - size_t stPatternLength = (p_pcPattern ? strlen(p_pcPattern) : 0); - - if ((stStringLength) && - (stPatternLength) && - (stPatternLength <= stStringLength)) - { - // Pattern is shorter or has the same length tham the string - - for (const char* s = (p_pcString + stStringLength - stPatternLength); s >= p_pcString; --s) - { - if (0 == strncmp(s, p_pcPattern, stPatternLength)) - { - pcResult = s; - break; - } - } - } - return pcResult; -} - - -} // anonymous - - - - - -namespace esp8266 -{ - -/* - LEAmDNS -*/ -namespace MDNSImplementation -{ - -/** - HELPERS -*/ - -/* - MDNSResponder::indexDomain (static) - - Updates the given domain 'p_rpcHostname' by appending a delimiter and an index number. - - If the given domain already hasa numeric index (after the given delimiter), this index - incremented. If not, the delimiter and index '2' is added. - - If 'p_rpcHostname' is empty (==0), the given default name 'p_pcDefaultHostname' is used, - if no default is given, 'esp8266' is used. - -*/ -/*static*/ bool MDNSResponder::indexDomain(char*& p_rpcDomain, - const char* p_pcDivider /*= "-"*/, - const char* p_pcDefaultDomain /*= 0*/) -{ - - bool bResult = false; - - // Ensure a divider exists; use '-' as default - const char* pcDivider = (p_pcDivider ? : "-"); - - if (p_rpcDomain) - { - const char* pFoundDivider = strrstr(p_rpcDomain, pcDivider); - if (pFoundDivider) // maybe already extended - { - char* pEnd = 0; - unsigned long ulIndex = strtoul((pFoundDivider + strlen(pcDivider)), &pEnd, 10); - if ((ulIndex) && - ((pEnd - p_rpcDomain) == (ptrdiff_t)strlen(p_rpcDomain)) && - (!*pEnd)) // Valid (old) index found - { - - char acIndexBuffer[16]; - sprintf(acIndexBuffer, "%lu", (++ulIndex)); - size_t stLength = ((pFoundDivider - p_rpcDomain + strlen(pcDivider)) + strlen(acIndexBuffer) + 1); - char* pNewHostname = new char[stLength]; - if (pNewHostname) - { - memcpy(pNewHostname, p_rpcDomain, (pFoundDivider - p_rpcDomain + strlen(pcDivider))); - pNewHostname[pFoundDivider - p_rpcDomain + strlen(pcDivider)] = 0; - strcat(pNewHostname, acIndexBuffer); - - delete[] p_rpcDomain; - p_rpcDomain = pNewHostname; - - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.println(F("[MDNSResponder] indexDomain: FAILED to alloc new hostname!"));); - } - } - else - { - pFoundDivider = 0; // Flag the need to (base) extend the hostname - } - } - - if (!pFoundDivider) // not yet extended (or failed to increment extension) -> start indexing - { - size_t stLength = strlen(p_rpcDomain) + (strlen(pcDivider) + 1 + 1); // Name + Divider + '2' + '\0' - char* pNewHostname = new char[stLength]; - if (pNewHostname) - { - sprintf(pNewHostname, "%s%s2", p_rpcDomain, pcDivider); - - delete[] p_rpcDomain; - p_rpcDomain = pNewHostname; - - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.println(F("[MDNSResponder] indexDomain: FAILED to alloc new hostname!"));); - } - } - } - else - { - // No given host domain, use base or default - const char* cpcDefaultName = (p_pcDefaultDomain ? : "esp8266"); - - size_t stLength = strlen(cpcDefaultName) + 1; // '\0' - p_rpcDomain = new char[stLength]; - if (p_rpcDomain) - { - strncpy(p_rpcDomain, cpcDefaultName, stLength); - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.println(F("[MDNSResponder] indexDomain: FAILED to alloc new hostname!"));); - } - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] indexDomain: %s\n"), p_rpcDomain);); - return bResult; -} - - -/* - UDP CONTEXT -*/ - -bool MDNSResponder::_callProcess(void) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf("[MDNSResponder] _callProcess (%lu, triggered by: %s)\n", millis(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str());); - - return _process(false); -} - -/* - MDNSResponder::_allocUDPContext - - (Re-)Creates the one-and-only UDP context for the MDNS responder. - The context is added to the 'multicast'-group and listens to the MDNS port (5353). - The travel-distance for multicast messages is set to 1 (local, via MDNS_MULTICAST_TTL). - Messages are received via the MDNSResponder '_update' function. CAUTION: This function - is called from the WiFi stack side of the ESP stack system. - -*/ -bool MDNSResponder::_allocUDPContext(void) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.println("[MDNSResponder] _allocUDPContext");); - - bool bResult = false; - - _releaseUDPContext(); - -#ifdef MDNS_IP4_SUPPORT - ip_addr_t multicast_addr = DNS_MQUERY_IPV4_GROUP_INIT; -#endif -#ifdef MDNS_IP6_SUPPORT - //TODO: set multicast address (lwip_joingroup() is IPv4 only at the time of writing) - multicast_addr.addr = DNS_MQUERY_IPV6_GROUP_INIT; -#endif - if (ERR_OK == igmp_joingroup(ip_2_ip4(&m_netif->ip_addr), ip_2_ip4(&multicast_addr))) - { - m_pUDPContext = new UdpContext; - m_pUDPContext->ref(); - - if (m_pUDPContext->listen(IP4_ADDR_ANY, DNS_MQUERY_PORT)) - { - m_pUDPContext->setMulticastTTL(MDNS_MULTICAST_TTL); - m_pUDPContext->onRx(std::bind(&MDNSResponder::_callProcess, this)); - - bResult = m_pUDPContext->connect(&multicast_addr, DNS_MQUERY_PORT); - } - } - return bResult; -} - -/* - MDNSResponder::_releaseUDPContext -*/ -bool MDNSResponder::_releaseUDPContext(void) -{ - - if (m_pUDPContext) - { - m_pUDPContext->unref(); - m_pUDPContext = 0; - } - return true; -} - - -/* - SERVICE QUERY -*/ - -/* - MDNSResponder::_allocServiceQuery -*/ -MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_allocServiceQuery(void) -{ - - stcMDNSServiceQuery* pServiceQuery = new stcMDNSServiceQuery; - if (pServiceQuery) - { - // Link to query list - pServiceQuery->m_pNext = m_pServiceQueries; - m_pServiceQueries = pServiceQuery; - } - return m_pServiceQueries; -} - -/* - MDNSResponder::_removeServiceQuery -*/ -bool MDNSResponder::_removeServiceQuery(MDNSResponder::stcMDNSServiceQuery* p_pServiceQuery) -{ - - bool bResult = false; - - if (p_pServiceQuery) - { - stcMDNSServiceQuery* pPred = m_pServiceQueries; - while ((pPred) && - (pPred->m_pNext != p_pServiceQuery)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pServiceQuery->m_pNext; - delete p_pServiceQuery; - bResult = true; - } - else // No predecesor - { - if (m_pServiceQueries == p_pServiceQuery) - { - m_pServiceQueries = p_pServiceQuery->m_pNext; - delete p_pServiceQuery; - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.println("[MDNSResponder] _releaseServiceQuery: INVALID service query!");); - } - } - } - return bResult; -} - -/* - MDNSResponder::_removeLegacyServiceQuery -*/ -bool MDNSResponder::_removeLegacyServiceQuery(void) -{ - - stcMDNSServiceQuery* pLegacyServiceQuery = _findLegacyServiceQuery(); - return (pLegacyServiceQuery ? _removeServiceQuery(pLegacyServiceQuery) : true); -} - -/* - MDNSResponder::_findServiceQuery - - 'Convert' hMDNSServiceQuery to stcMDNSServiceQuery* (ensure existance) - -*/ -MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_findServiceQuery(MDNSResponder::hMDNSServiceQuery p_hServiceQuery) -{ - - stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; - while (pServiceQuery) - { - if ((hMDNSServiceQuery)pServiceQuery == p_hServiceQuery) - { - break; - } - pServiceQuery = pServiceQuery->m_pNext; - } - return pServiceQuery; -} - -/* - MDNSResponder::_findLegacyServiceQuery -*/ -MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_findLegacyServiceQuery(void) -{ - - stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries; - while (pServiceQuery) - { - if (pServiceQuery->m_bLegacyQuery) - { - break; - } - pServiceQuery = pServiceQuery->m_pNext; - } - return pServiceQuery; -} - -/* - MDNSResponder::_releaseServiceQueries -*/ -bool MDNSResponder::_releaseServiceQueries(void) -{ - while (m_pServiceQueries) - { - stcMDNSServiceQuery* pNext = m_pServiceQueries->m_pNext; - delete m_pServiceQueries; - m_pServiceQueries = pNext; - } - return true; -} - -/* - MDNSResponder::_findNextServiceQueryByServiceType -*/ -MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_findNextServiceQueryByServiceType(const stcMDNS_RRDomain& p_ServiceTypeDomain, - const stcMDNSServiceQuery* p_pPrevServiceQuery) -{ - stcMDNSServiceQuery* pMatchingServiceQuery = 0; - - stcMDNSServiceQuery* pServiceQuery = (p_pPrevServiceQuery ? p_pPrevServiceQuery->m_pNext : m_pServiceQueries); - while (pServiceQuery) - { - if (p_ServiceTypeDomain == pServiceQuery->m_ServiceTypeDomain) - { - pMatchingServiceQuery = pServiceQuery; - break; - } - pServiceQuery = pServiceQuery->m_pNext; - } - return pMatchingServiceQuery; -} - - -/* - HOSTNAME -*/ - -/* - MDNSResponder::_setHostname -*/ -bool MDNSResponder::_setHostname(const char* p_pcHostname) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _allocHostname (%s)\n"), p_pcHostname);); - - bool bResult = false; - - _releaseHostname(); - - size_t stLength = 0; - if ((p_pcHostname) && - (MDNS_DOMAIN_LABEL_MAXLENGTH >= (stLength = strlen(p_pcHostname)))) // char max size for a single label - { - // Copy in hostname characters as lowercase - if ((bResult = (0 != (m_pcHostname = new char[stLength + 1])))) - { -#ifdef MDNS_FORCE_LOWERCASE_HOSTNAME - size_t i = 0; - for (; i < stLength; ++i) - { - m_pcHostname[i] = (isupper(p_pcHostname[i]) ? tolower(p_pcHostname[i]) : p_pcHostname[i]); - } - m_pcHostname[i] = 0; -#else - strncpy(m_pcHostname, p_pcHostname, (stLength + 1)); -#endif - } - } - return bResult; -} - -/* - MDNSResponder::_releaseHostname -*/ -bool MDNSResponder::_releaseHostname(void) -{ - - if (m_pcHostname) - { - delete[] m_pcHostname; - m_pcHostname = 0; - } - return true; -} - - -/* - SERVICE -*/ - -/* - MDNSResponder::_allocService -*/ -MDNSResponder::stcMDNSService* MDNSResponder::_allocService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port) -{ - - stcMDNSService* pService = 0; - if (((!p_pcName) || - (MDNS_DOMAIN_LABEL_MAXLENGTH >= strlen(p_pcName))) && - (p_pcService) && - (MDNS_SERVICE_NAME_LENGTH >= strlen(p_pcService)) && - (p_pcProtocol) && - (MDNS_SERVICE_PROTOCOL_LENGTH >= strlen(p_pcProtocol)) && - (p_u16Port) && - (0 != (pService = new stcMDNSService)) && - (pService->setName(p_pcName ? : m_pcHostname)) && - (pService->setService(p_pcService)) && - (pService->setProtocol(p_pcProtocol))) - { - - pService->m_bAutoName = (0 == p_pcName); - pService->m_u16Port = p_u16Port; - - // Add to list (or start list) - pService->m_pNext = m_pServices; - m_pServices = pService; - } - return pService; -} - -/* - MDNSResponder::_releaseService -*/ -bool MDNSResponder::_releaseService(MDNSResponder::stcMDNSService* p_pService) -{ - - bool bResult = false; - - if (p_pService) - { - stcMDNSService* pPred = m_pServices; - while ((pPred) && - (pPred->m_pNext != p_pService)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pService->m_pNext; - delete p_pService; - bResult = true; - } - else // No predecesor - { - if (m_pServices == p_pService) - { - m_pServices = p_pService->m_pNext; - delete p_pService; - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.println("[MDNSResponder] _releaseService: INVALID service!");); - } - } - } - return bResult; -} - -/* - MDNSResponder::_releaseServices -*/ -bool MDNSResponder::_releaseServices(void) -{ - - stcMDNSService* pService = m_pServices; - while (pService) - { - _releaseService(pService); - pService = m_pServices; - } - return true; -} - -/* - MDNSResponder::_findService -*/ -MDNSResponder::stcMDNSService* MDNSResponder::_findService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol) -{ - - stcMDNSService* pService = m_pServices; - while (pService) - { - if ((0 == strcmp(pService->m_pcName, p_pcName)) && - (0 == strcmp(pService->m_pcService, p_pcService)) && - (0 == strcmp(pService->m_pcProtocol, p_pcProtocol))) - { - - break; - } - pService = pService->m_pNext; - } - return pService; -} - -/* - MDNSResponder::_findService -*/ -MDNSResponder::stcMDNSService* MDNSResponder::_findService(const MDNSResponder::hMDNSService p_hService) -{ - - stcMDNSService* pService = m_pServices; - while (pService) - { - if (p_hService == (hMDNSService)pService) - { - break; - } - pService = pService->m_pNext; - } - return pService; -} - - -/* - SERVICE TXT -*/ - -/* - MDNSResponder::_allocServiceTxt -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_allocServiceTxt(MDNSResponder::stcMDNSService* p_pService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp) -{ - - stcMDNSServiceTxt* pTxt = 0; - - if ((p_pService) && - (p_pcKey) && - (MDNS_SERVICE_TXT_MAXLENGTH > (p_pService->m_Txts.length() + - 1 + // Length byte - (p_pcKey ? strlen(p_pcKey) : 0) + - 1 + // '=' - (p_pcValue ? strlen(p_pcValue) : 0)))) - { - - pTxt = new stcMDNSServiceTxt; - if (pTxt) - { - size_t stLength = (p_pcKey ? strlen(p_pcKey) : 0); - pTxt->m_pcKey = new char[stLength + 1]; - if (pTxt->m_pcKey) - { - strncpy(pTxt->m_pcKey, p_pcKey, stLength); pTxt->m_pcKey[stLength] = 0; - } - - if (p_pcValue) - { - stLength = (p_pcValue ? strlen(p_pcValue) : 0); - pTxt->m_pcValue = new char[stLength + 1]; - if (pTxt->m_pcValue) - { - strncpy(pTxt->m_pcValue, p_pcValue, stLength); pTxt->m_pcValue[stLength] = 0; - } - } - pTxt->m_bTemp = p_bTemp; - - // Add to list (or start list) - p_pService->m_Txts.add(pTxt); - } - } - return pTxt; -} - -/* - MDNSResponder::_releaseServiceTxt -*/ -bool MDNSResponder::_releaseServiceTxt(MDNSResponder::stcMDNSService* p_pService, - MDNSResponder::stcMDNSServiceTxt* p_pTxt) -{ - - return ((p_pService) && - (p_pTxt) && - (p_pService->m_Txts.remove(p_pTxt))); -} - -/* - MDNSResponder::_updateServiceTxt -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_updateServiceTxt(MDNSResponder::stcMDNSService* p_pService, - MDNSResponder::stcMDNSServiceTxt* p_pTxt, - const char* p_pcValue, - bool p_bTemp) -{ - - if ((p_pService) && - (p_pTxt) && - (MDNS_SERVICE_TXT_MAXLENGTH > (p_pService->m_Txts.length() - - (p_pTxt->m_pcValue ? strlen(p_pTxt->m_pcValue) : 0) + - (p_pcValue ? strlen(p_pcValue) : 0)))) - { - p_pTxt->update(p_pcValue); - p_pTxt->m_bTemp = p_bTemp; - } - return p_pTxt; -} - -/* - MDNSResponder::_findServiceTxt -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_findServiceTxt(MDNSResponder::stcMDNSService* p_pService, - const char* p_pcKey) -{ - - return (p_pService ? p_pService->m_Txts.find(p_pcKey) : 0); -} - -/* - MDNSResponder::_findServiceTxt -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_findServiceTxt(MDNSResponder::stcMDNSService* p_pService, - const hMDNSTxt p_hTxt) -{ - - return (((p_pService) && (p_hTxt)) ? p_pService->m_Txts.find((stcMDNSServiceTxt*)p_hTxt) : 0); -} - -/* - MDNSResponder::_addServiceTxt -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_addServiceTxt(MDNSResponder::stcMDNSService* p_pService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp) -{ - stcMDNSServiceTxt* pResult = 0; - - if ((p_pService) && - (p_pcKey) && - (strlen(p_pcKey))) - { - - stcMDNSServiceTxt* pTxt = p_pService->m_Txts.find(p_pcKey); - if (pTxt) - { - pResult = _updateServiceTxt(p_pService, pTxt, p_pcValue, p_bTemp); - } - else - { - pResult = _allocServiceTxt(p_pService, p_pcKey, p_pcValue, p_bTemp); - } - } - return pResult; -} - -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_answerKeyValue(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery); - stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0); - // Fill m_pcTxts (if not already done) - return (pSQAnswer) ? pSQAnswer->m_Txts.m_pTxts : 0; -} - -/* - MDNSResponder::_collectServiceTxts -*/ -bool MDNSResponder::_collectServiceTxts(MDNSResponder::stcMDNSService& p_rService) -{ - - // Call Dynamic service callbacks - if (m_fnServiceTxtCallback) - { - m_fnServiceTxtCallback((hMDNSService)&p_rService); - } - if (p_rService.m_fnTxtCallback) - { - p_rService.m_fnTxtCallback((hMDNSService)&p_rService); - } - return true; -} - -/* - MDNSResponder::_releaseTempServiceTxts -*/ -bool MDNSResponder::_releaseTempServiceTxts(MDNSResponder::stcMDNSService& p_rService) -{ - - return (p_rService.m_Txts.removeTempTxts()); -} - - -/* - MISC -*/ - -#ifdef DEBUG_ESP_MDNS_RESPONDER -/* - MDNSResponder::_printRRDomain -*/ -bool MDNSResponder::_printRRDomain(const MDNSResponder::stcMDNS_RRDomain& p_RRDomain) const -{ - - //DEBUG_OUTPUT.printf_P(PSTR("Domain: ")); - - const char* pCursor = p_RRDomain.m_acName; - uint8_t u8Length = *pCursor++; - if (u8Length) - { - while (u8Length) - { - for (uint8_t u = 0; u < u8Length; ++u) - { - DEBUG_OUTPUT.printf_P(PSTR("%c"), *(pCursor++)); - } - u8Length = *pCursor++; - if (u8Length) - { - DEBUG_OUTPUT.printf_P(PSTR(".")); - } - } - } - else // empty domain - { - DEBUG_OUTPUT.printf_P(PSTR("-empty-")); - } - //DEBUG_OUTPUT.printf_P(PSTR("\n")); - - return true; -} - -/* - MDNSResponder::_printRRAnswer -*/ -bool MDNSResponder::_printRRAnswer(const MDNSResponder::stcMDNS_RRAnswer& p_RRAnswer) const -{ - - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] RRAnswer: ")); - _printRRDomain(p_RRAnswer.m_Header.m_Domain); - DEBUG_OUTPUT.printf_P(PSTR(" Type:0x%04X Class:0x%04X TTL:%u, "), p_RRAnswer.m_Header.m_Attributes.m_u16Type, p_RRAnswer.m_Header.m_Attributes.m_u16Class, p_RRAnswer.m_u32TTL); - switch (p_RRAnswer.m_Header.m_Attributes.m_u16Type & (~0x8000)) // Topmost bit might carry 'cache flush' flag - { -#ifdef MDNS_IP4_SUPPORT - case DNS_RRTYPE_A: - DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((const stcMDNS_RRAnswerA*)&p_RRAnswer)->m_IPAddress.toString().c_str()); - break; -#endif - case DNS_RRTYPE_PTR: - DEBUG_OUTPUT.printf_P(PSTR("PTR ")); - _printRRDomain(((const stcMDNS_RRAnswerPTR*)&p_RRAnswer)->m_PTRDomain); - break; - case DNS_RRTYPE_TXT: - { - size_t stTxtLength = ((const stcMDNS_RRAnswerTXT*)&p_RRAnswer)->m_Txts.c_strLength(); - char* pTxts = new char[stTxtLength]; - if (pTxts) - { - ((/*const c_str()!!*/stcMDNS_RRAnswerTXT*)&p_RRAnswer)->m_Txts.c_str(pTxts); - DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts); - delete[] pTxts; - } - break; - } -#ifdef MDNS_IP6_SUPPORT - case DNS_RRTYPE_AAAA: - DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((stcMDNS_RRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); - break; -#endif - case DNS_RRTYPE_SRV: - DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((const stcMDNS_RRAnswerSRV*)&p_RRAnswer)->m_u16Port); - _printRRDomain(((const stcMDNS_RRAnswerSRV*)&p_RRAnswer)->m_SRVDomain); - break; - default: - DEBUG_OUTPUT.printf_P(PSTR("generic ")); - break; - } - DEBUG_OUTPUT.printf_P(PSTR("\n")); - - return true; -} -#endif - -} // namespace MDNSImplementation - -} // namespace esp8266 - - - - diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Priv.h b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Priv.h deleted file mode 100644 index cc56b133a9..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Priv.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - LEAmDNS_Priv.h - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#ifndef MDNS_PRIV_H -#define MDNS_PRIV_H - -namespace esp8266 -{ - -/* - LEAmDNS -*/ - -namespace MDNSImplementation -{ - -// Enable class debug functions -#define ESP_8266_MDNS_INCLUDE -//#define DEBUG_ESP_MDNS_RESPONDER - -#if !defined(DEBUG_ESP_MDNS_RESPONDER) && defined(DEBUG_ESP_MDNS) -#define DEBUG_ESP_MDNS_RESPONDER -#endif - -#ifndef LWIP_OPEN_SRC -#define LWIP_OPEN_SRC -#endif - -// -// If ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE is defined, the mDNS responder ignores a successful probing -// This allows to drive the responder in a environment, where 'update()' isn't called in the loop -//#define ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE - -// Enable/disable debug trace macros -#ifdef DEBUG_ESP_MDNS_RESPONDER -#define DEBUG_ESP_MDNS_INFO -#define DEBUG_ESP_MDNS_ERR -#define DEBUG_ESP_MDNS_TX -#define DEBUG_ESP_MDNS_RX -#endif - -#ifdef DEBUG_ESP_MDNS_RESPONDER -#ifdef DEBUG_ESP_MDNS_INFO -#define DEBUG_EX_INFO(A) A -#else -#define DEBUG_EX_INFO(A) do { (void)0; } while (0) -#endif -#ifdef DEBUG_ESP_MDNS_ERR -#define DEBUG_EX_ERR(A) A -#else -#define DEBUG_EX_ERR(A) do { (void)0; } while (0) -#endif -#ifdef DEBUG_ESP_MDNS_TX -#define DEBUG_EX_TX(A) A -#else -#define DEBUG_EX_TX(A) do { (void)0; } while (0) -#endif -#ifdef DEBUG_ESP_MDNS_RX -#define DEBUG_EX_RX(A) A -#else -#define DEBUG_EX_RX(A) do { (void)0; } while (0) -#endif - -#ifdef DEBUG_ESP_PORT -#define DEBUG_OUTPUT DEBUG_ESP_PORT -#else -#define DEBUG_OUTPUT Serial -#endif -#else -#define DEBUG_EX_INFO(A) do { (void)0; } while (0) -#define DEBUG_EX_ERR(A) do { (void)0; } while (0) -#define DEBUG_EX_TX(A) do { (void)0; } while (0) -#define DEBUG_EX_RX(A) do { (void)0; } while (0) -#endif - - -/* Replaced by 'lwip/prot/dns.h' definitions - #ifdef MDNS_IP4_SUPPORT - #define MDNS_MULTICAST_ADDR_IP4 (IPAddress(224, 0, 0, 251)) // ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT - #endif - #ifdef MDNS_IP6_SUPPORT - #define MDNS_MULTICAST_ADDR_IP6 (IPAddress("FF02::FB")) // ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT - #endif*/ -//#define MDNS_MULTICAST_PORT 5353 - -/* - This is NOT the TTL (Time-To-Live) for MDNS records, but the - subnet level distance MDNS records should travel. - 1 sets the subnet distance to 'local', which is default for MDNS. - (Btw.: 255 would set it to 'as far as possible' -> internet) - - However, RFC 3171 seems to force 255 instead -*/ -#define MDNS_MULTICAST_TTL 255/*1*/ - -/* - This is the MDNS record TTL - Host level records are set to 2min (120s) - service level records are set to 75min (4500s) -*/ -#define MDNS_HOST_TTL 120 -#define MDNS_SERVICE_TTL 4500 - -/* - Compressed labels are flaged by the two topmost bits of the length byte being set -*/ -#define MDNS_DOMAIN_COMPRESS_MARK 0xC0 -/* - Avoid endless recursion because of malformed compressed labels -*/ -#define MDNS_DOMAIN_MAX_REDIRCTION 6 - -/* - Default service priority and weight in SRV answers -*/ -#define MDNS_SRV_PRIORITY 0 -#define MDNS_SRV_WEIGHT 0 - -/* - Delay between and number of probes for host and service domains - Delay between and number of announces for host and service domains - Delay between and number of service queries; the delay is multiplied by the resent number in '_checkServiceQueryCache' -*/ -#define MDNS_PROBE_DELAY 250 -#define MDNS_PROBE_COUNT 3 -#define MDNS_ANNOUNCE_DELAY 1000 -#define MDNS_ANNOUNCE_COUNT 8 -#define MDNS_DYNAMIC_QUERY_RESEND_COUNT 5 -#define MDNS_DYNAMIC_QUERY_RESEND_DELAY 5000 - - -/* - Force host domain to use only lowercase letters -*/ -//#define MDNS_FORCE_LOWERCASE_HOSTNAME - -/* - Enable/disable the usage of the F() macro in debug trace printf calls. - There needs to be an PGM comptible printf function to use this. - - USE_PGM_PRINTF and F -*/ -#define USE_PGM_PRINTF - -#ifdef USE_PGM_PRINTF -#else -#ifdef F -#undef F -#endif -#define F(A) A -#endif - -} // namespace MDNSImplementation - -} // namespace esp8266 - -// Include the main header, so the submodlues only need to include this header -#include "LEAmDNS.h" - - -#endif // MDNS_PRIV_H diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Structs.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Structs.cpp deleted file mode 100644 index ce475de3ba..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Structs.cpp +++ /dev/null @@ -1,2476 +0,0 @@ -/* - LEAmDNS_Structs.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#include "LEAmDNS_Priv.h" -#include "LEAmDNS_lwIPdefs.h" - -namespace esp8266 -{ - -/* - LEAmDNS -*/ -namespace MDNSImplementation -{ - -/** - STRUCTS -*/ - -/** - MDNSResponder::stcMDNSServiceTxt - - One MDNS TXT item. - m_pcValue may be '\0'. - Objects can be chained together (list, m_pNext). - A 'm_bTemp' flag differentiates between static and dynamic items. - Output as byte array 'c#=1' is supported. -*/ - -/* - MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt constructor -*/ -MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt(const char* p_pcKey /*= 0*/, - const char* p_pcValue /*= 0*/, - bool p_bTemp /*= false*/) - : m_pNext(0), - m_pcKey(0), - m_pcValue(0), - m_bTemp(p_bTemp) -{ - - setKey(p_pcKey); - setValue(p_pcValue); -} - -/* - MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt copy-constructor -*/ -MDNSResponder::stcMDNSServiceTxt::stcMDNSServiceTxt(const MDNSResponder::stcMDNSServiceTxt& p_Other) - : m_pNext(0), - m_pcKey(0), - m_pcValue(0), - m_bTemp(false) -{ - - operator=(p_Other); -} - -/* - MDNSResponder::stcMDNSServiceTxt::~stcMDNSServiceTxt destructor -*/ -MDNSResponder::stcMDNSServiceTxt::~stcMDNSServiceTxt(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSServiceTxt::operator= -*/ -MDNSResponder::stcMDNSServiceTxt& MDNSResponder::stcMDNSServiceTxt::operator=(const MDNSResponder::stcMDNSServiceTxt& p_Other) -{ - - if (&p_Other != this) - { - clear(); - set(p_Other.m_pcKey, p_Other.m_pcValue, p_Other.m_bTemp); - } - return *this; -} - -/* - MDNSResponder::stcMDNSServiceTxt::clear -*/ -bool MDNSResponder::stcMDNSServiceTxt::clear(void) -{ - - releaseKey(); - releaseValue(); - return true; -} - -/* - MDNSResponder::stcMDNSServiceTxt::allocKey -*/ -char* MDNSResponder::stcMDNSServiceTxt::allocKey(size_t p_stLength) -{ - - releaseKey(); - if (p_stLength) - { - m_pcKey = new char[p_stLength + 1]; - } - return m_pcKey; -} - -/* - MDNSResponder::stcMDNSServiceTxt::setKey -*/ -bool MDNSResponder::stcMDNSServiceTxt::setKey(const char* p_pcKey, - size_t p_stLength) -{ - - bool bResult = false; - - releaseKey(); - if (p_stLength) - { - if (allocKey(p_stLength)) - { - strncpy(m_pcKey, p_pcKey, p_stLength); - m_pcKey[p_stLength] = 0; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxt::setKey -*/ -bool MDNSResponder::stcMDNSServiceTxt::setKey(const char* p_pcKey) -{ - - return setKey(p_pcKey, (p_pcKey ? strlen(p_pcKey) : 0)); -} - -/* - MDNSResponder::stcMDNSServiceTxt::releaseKey -*/ -bool MDNSResponder::stcMDNSServiceTxt::releaseKey(void) -{ - - if (m_pcKey) - { - delete[] m_pcKey; - m_pcKey = 0; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceTxt::allocValue -*/ -char* MDNSResponder::stcMDNSServiceTxt::allocValue(size_t p_stLength) -{ - - releaseValue(); - if (p_stLength) - { - m_pcValue = new char[p_stLength + 1]; - } - return m_pcValue; -} - -/* - MDNSResponder::stcMDNSServiceTxt::setValue -*/ -bool MDNSResponder::stcMDNSServiceTxt::setValue(const char* p_pcValue, - size_t p_stLength) -{ - - bool bResult = false; - - releaseValue(); - if (p_stLength) - { - if (allocValue(p_stLength)) - { - strncpy(m_pcValue, p_pcValue, p_stLength); - m_pcValue[p_stLength] = 0; - bResult = true; - } - } - else // No value -> also OK - { - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxt::setValue -*/ -bool MDNSResponder::stcMDNSServiceTxt::setValue(const char* p_pcValue) -{ - - return setValue(p_pcValue, (p_pcValue ? strlen(p_pcValue) : 0)); -} - -/* - MDNSResponder::stcMDNSServiceTxt::releaseValue -*/ -bool MDNSResponder::stcMDNSServiceTxt::releaseValue(void) -{ - - if (m_pcValue) - { - delete[] m_pcValue; - m_pcValue = 0; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceTxt::set -*/ -bool MDNSResponder::stcMDNSServiceTxt::set(const char* p_pcKey, - const char* p_pcValue, - bool p_bTemp /*= false*/) -{ - - m_bTemp = p_bTemp; - return ((setKey(p_pcKey)) && - (setValue(p_pcValue))); -} - -/* - MDNSResponder::stcMDNSServiceTxt::update -*/ -bool MDNSResponder::stcMDNSServiceTxt::update(const char* p_pcValue) -{ - - return setValue(p_pcValue); -} - -/* - MDNSResponder::stcMDNSServiceTxt::length - - length of eg. 'c#=1' without any closing '\0' -*/ -size_t MDNSResponder::stcMDNSServiceTxt::length(void) const -{ - - size_t stLength = 0; - if (m_pcKey) - { - stLength += strlen(m_pcKey); // Key - stLength += 1; // '=' - stLength += (m_pcValue ? strlen(m_pcValue) : 0); // Value - } - return stLength; -} - - -/** - MDNSResponder::stcMDNSServiceTxts - - A list of zero or more MDNS TXT items. - Dynamic TXT items can be removed by 'removeTempTxts'. - A TXT item can be looke up by its 'key' member. - Export as ';'-separated byte array is supported. - Export as 'length byte coded' byte array is supported. - Comparision ((all A TXT items in B and equal) AND (all B TXT items in A and equal)) is supported. - -*/ - -/* - MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts contructor -*/ -MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts(void) - : m_pTxts(0) -{ - -} - -/* - MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts copy-constructor -*/ -MDNSResponder::stcMDNSServiceTxts::stcMDNSServiceTxts(const stcMDNSServiceTxts& p_Other) - : m_pTxts(0) -{ - - operator=(p_Other); -} - -/* - MDNSResponder::stcMDNSServiceTxts::~stcMDNSServiceTxts destructor -*/ -MDNSResponder::stcMDNSServiceTxts::~stcMDNSServiceTxts(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSServiceTxts::operator= -*/ -MDNSResponder::stcMDNSServiceTxts& MDNSResponder::stcMDNSServiceTxts::operator=(const stcMDNSServiceTxts& p_Other) -{ - - if (this != &p_Other) - { - clear(); - - for (stcMDNSServiceTxt* pOtherTxt = p_Other.m_pTxts; pOtherTxt; pOtherTxt = pOtherTxt->m_pNext) - { - add(new stcMDNSServiceTxt(*pOtherTxt)); - } - } - return *this; -} - -/* - MDNSResponder::stcMDNSServiceTxts::clear -*/ -bool MDNSResponder::stcMDNSServiceTxts::clear(void) -{ - - while (m_pTxts) - { - stcMDNSServiceTxt* pNext = m_pTxts->m_pNext; - delete m_pTxts; - m_pTxts = pNext; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceTxts::add -*/ -bool MDNSResponder::stcMDNSServiceTxts::add(MDNSResponder::stcMDNSServiceTxt* p_pTxt) -{ - - bool bResult = false; - - if (p_pTxt) - { - p_pTxt->m_pNext = m_pTxts; - m_pTxts = p_pTxt; - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::remove -*/ -bool MDNSResponder::stcMDNSServiceTxts::remove(stcMDNSServiceTxt* p_pTxt) -{ - - bool bResult = false; - - if (p_pTxt) - { - stcMDNSServiceTxt* pPred = m_pTxts; - while ((pPred) && - (pPred->m_pNext != p_pTxt)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pTxt->m_pNext; - delete p_pTxt; - bResult = true; - } - else if (m_pTxts == p_pTxt) // No predecesor, but first item - { - m_pTxts = p_pTxt->m_pNext; - delete p_pTxt; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::removeTempTxts -*/ -bool MDNSResponder::stcMDNSServiceTxts::removeTempTxts(void) -{ - - bool bResult = true; - - stcMDNSServiceTxt* pTxt = m_pTxts; - while ((bResult) && - (pTxt)) - { - stcMDNSServiceTxt* pNext = pTxt->m_pNext; - if (pTxt->m_bTemp) - { - bResult = remove(pTxt); - } - pTxt = pNext; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::find -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::stcMDNSServiceTxts::find(const char* p_pcKey) -{ - - stcMDNSServiceTxt* pResult = 0; - - for (stcMDNSServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) - { - if ((p_pcKey) && - (0 == strcmp(pTxt->m_pcKey, p_pcKey))) - { - pResult = pTxt; - break; - } - } - return pResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::find -*/ -const MDNSResponder::stcMDNSServiceTxt* MDNSResponder::stcMDNSServiceTxts::find(const char* p_pcKey) const -{ - - const stcMDNSServiceTxt* pResult = 0; - - for (const stcMDNSServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) - { - if ((p_pcKey) && - (0 == strcmp(pTxt->m_pcKey, p_pcKey))) - { - - pResult = pTxt; - break; - } - } - return pResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::find -*/ -MDNSResponder::stcMDNSServiceTxt* MDNSResponder::stcMDNSServiceTxts::find(const stcMDNSServiceTxt* p_pTxt) -{ - - stcMDNSServiceTxt* pResult = 0; - - for (stcMDNSServiceTxt* pTxt = m_pTxts; pTxt; pTxt = pTxt->m_pNext) - { - if (p_pTxt == pTxt) - { - pResult = pTxt; - break; - } - } - return pResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::length -*/ -uint16_t MDNSResponder::stcMDNSServiceTxts::length(void) const -{ - - uint16_t u16Length = 0; - - stcMDNSServiceTxt* pTxt = m_pTxts; - while (pTxt) - { - u16Length += 1; // Length byte - u16Length += pTxt->length(); // Text - pTxt = pTxt->m_pNext; - } - return u16Length; -} - -/* - MDNSResponder::stcMDNSServiceTxts::c_strLength - - (incl. closing '\0'). Length bytes place is used for delimiting ';' and closing '\0' -*/ -size_t MDNSResponder::stcMDNSServiceTxts::c_strLength(void) const -{ - - return length(); -} - -/* - MDNSResponder::stcMDNSServiceTxts::c_str -*/ -bool MDNSResponder::stcMDNSServiceTxts::c_str(char* p_pcBuffer) -{ - - bool bResult = false; - - if (p_pcBuffer) - { - bResult = true; - - *p_pcBuffer = 0; - for (stcMDNSServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) - { - size_t stLength; - if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) - { - if (pTxt != m_pTxts) - { - *p_pcBuffer++ = ';'; - } - strncpy(p_pcBuffer, pTxt->m_pcKey, stLength); p_pcBuffer[stLength] = 0; - p_pcBuffer += stLength; - *p_pcBuffer++ = '='; - if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) - { - strncpy(p_pcBuffer, pTxt->m_pcValue, stLength); p_pcBuffer[stLength] = 0; - p_pcBuffer += stLength; - } - } - } - *p_pcBuffer++ = 0; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::bufferLength - - (incl. closing '\0'). -*/ -size_t MDNSResponder::stcMDNSServiceTxts::bufferLength(void) const -{ - - return (length() + 1); -} - -/* - MDNSResponder::stcMDNSServiceTxts::toBuffer -*/ -bool MDNSResponder::stcMDNSServiceTxts::buffer(char* p_pcBuffer) -{ - - bool bResult = false; - - if (p_pcBuffer) - { - bResult = true; - - *p_pcBuffer = 0; - for (stcMDNSServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) - { - *(unsigned char*)p_pcBuffer++ = pTxt->length(); - size_t stLength; - if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) - { - memcpy(p_pcBuffer, pTxt->m_pcKey, stLength); - p_pcBuffer += stLength; - *p_pcBuffer++ = '='; - if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) - { - memcpy(p_pcBuffer, pTxt->m_pcValue, stLength); - p_pcBuffer += stLength; - } - } - } - *p_pcBuffer++ = 0; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::compare -*/ -bool MDNSResponder::stcMDNSServiceTxts::compare(const MDNSResponder::stcMDNSServiceTxts& p_Other) const -{ - - bool bResult = false; - - if ((bResult = (length() == p_Other.length()))) - { - // Compare A->B - for (const stcMDNSServiceTxt* pTxt = m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) - { - const stcMDNSServiceTxt* pOtherTxt = p_Other.find(pTxt->m_pcKey); - bResult = ((pOtherTxt) && - (pTxt->m_pcValue) && - (pOtherTxt->m_pcValue) && - (strlen(pTxt->m_pcValue) == strlen(pOtherTxt->m_pcValue)) && - (0 == strcmp(pTxt->m_pcValue, pOtherTxt->m_pcValue))); - } - // Compare B->A - for (const stcMDNSServiceTxt* pOtherTxt = p_Other.m_pTxts; ((bResult) && (pOtherTxt)); pOtherTxt = pOtherTxt->m_pNext) - { - const stcMDNSServiceTxt* pTxt = find(pOtherTxt->m_pcKey); - bResult = ((pTxt) && - (pOtherTxt->m_pcValue) && - (pTxt->m_pcValue) && - (strlen(pOtherTxt->m_pcValue) == strlen(pTxt->m_pcValue)) && - (0 == strcmp(pOtherTxt->m_pcValue, pTxt->m_pcValue))); - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceTxts::operator== -*/ -bool MDNSResponder::stcMDNSServiceTxts::operator==(const stcMDNSServiceTxts& p_Other) const -{ - - return compare(p_Other); -} - -/* - MDNSResponder::stcMDNSServiceTxts::operator!= -*/ -bool MDNSResponder::stcMDNSServiceTxts::operator!=(const stcMDNSServiceTxts& p_Other) const -{ - - return !compare(p_Other); -} - - -/** - MDNSResponder::stcMDNS_MsgHeader - - A MDNS message haeder. - -*/ - -/* - MDNSResponder::stcMDNS_MsgHeader::stcMDNS_MsgHeader -*/ -MDNSResponder::stcMDNS_MsgHeader::stcMDNS_MsgHeader(uint16_t p_u16ID /*= 0*/, - bool p_bQR /*= false*/, - unsigned char p_ucOpcode /*= 0*/, - bool p_bAA /*= false*/, - bool p_bTC /*= false*/, - bool p_bRD /*= false*/, - bool p_bRA /*= false*/, - unsigned char p_ucRCode /*= 0*/, - uint16_t p_u16QDCount /*= 0*/, - uint16_t p_u16ANCount /*= 0*/, - uint16_t p_u16NSCount /*= 0*/, - uint16_t p_u16ARCount /*= 0*/) - : m_u16ID(p_u16ID), - m_1bQR(p_bQR), m_4bOpcode(p_ucOpcode), m_1bAA(p_bAA), m_1bTC(p_bTC), m_1bRD(p_bRD), - m_1bRA(p_bRA), m_3bZ(0), m_4bRCode(p_ucRCode), - m_u16QDCount(p_u16QDCount), - m_u16ANCount(p_u16ANCount), - m_u16NSCount(p_u16NSCount), - m_u16ARCount(p_u16ARCount) -{ - -} - - -/** - MDNSResponder::stcMDNS_RRDomain - - A MDNS domain object. - The labels of the domain are stored (DNS-like encoded) in 'm_acName': - [length byte]varlength label[length byte]varlength label[0] - 'm_u16NameLength' stores the used length of 'm_acName'. - Dynamic label addition is supported. - Comparison is supported. - Export as byte array 'esp8266.local' is supported. - -*/ - -/* - MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain constructor -*/ -MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain(void) - : m_u16NameLength(0) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain copy-constructor -*/ -MDNSResponder::stcMDNS_RRDomain::stcMDNS_RRDomain(const stcMDNS_RRDomain& p_Other) - : m_u16NameLength(0) -{ - - operator=(p_Other); -} - -/* - MDNSResponder::stcMDNS_RRDomain::operator = -*/ -MDNSResponder::stcMDNS_RRDomain& MDNSResponder::stcMDNS_RRDomain::operator=(const stcMDNS_RRDomain& p_Other) -{ - - if (&p_Other != this) - { - memcpy(m_acName, p_Other.m_acName, sizeof(m_acName)); - m_u16NameLength = p_Other.m_u16NameLength; - } - return *this; -} - -/* - MDNSResponder::stcMDNS_RRDomain::clear -*/ -bool MDNSResponder::stcMDNS_RRDomain::clear(void) -{ - - memset(m_acName, 0, sizeof(m_acName)); - m_u16NameLength = 0; - return true; -} - -/* - MDNSResponder::stcMDNS_RRDomain::addLabel -*/ -bool MDNSResponder::stcMDNS_RRDomain::addLabel(const char* p_pcLabel, - bool p_bPrependUnderline /*= false*/) -{ - - bool bResult = false; - - size_t stLength = (p_pcLabel - ? (strlen(p_pcLabel) + (p_bPrependUnderline ? 1 : 0)) - : 0); - if ((MDNS_DOMAIN_LABEL_MAXLENGTH >= stLength) && - (MDNS_DOMAIN_MAXLENGTH >= (m_u16NameLength + (1 + stLength)))) - { - // Length byte - m_acName[m_u16NameLength] = (unsigned char)stLength; // Might be 0! - ++m_u16NameLength; - // Label - if (stLength) - { - if (p_bPrependUnderline) - { - m_acName[m_u16NameLength++] = '_'; - --stLength; - } - strncpy(&(m_acName[m_u16NameLength]), p_pcLabel, stLength); m_acName[m_u16NameLength + stLength] = 0; - m_u16NameLength += stLength; - } - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNS_RRDomain::compare -*/ -bool MDNSResponder::stcMDNS_RRDomain::compare(const stcMDNS_RRDomain& p_Other) const -{ - - bool bResult = false; - - if (m_u16NameLength == p_Other.m_u16NameLength) - { - const char* pT = m_acName; - const char* pO = p_Other.m_acName; - while ((pT) && - (pO) && - (*((unsigned char*)pT) == *((unsigned char*)pO)) && // Same length AND - (0 == strncasecmp((pT + 1), (pO + 1), *((unsigned char*)pT)))) // Same content - { - if (*((unsigned char*)pT)) // Not 0 - { - pT += (1 + * ((unsigned char*)pT)); // Shift by length byte and lenght - pO += (1 + * ((unsigned char*)pO)); - } - else // Is 0 -> Successfully reached the end - { - bResult = true; - break; - } - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNS_RRDomain::operator == -*/ -bool MDNSResponder::stcMDNS_RRDomain::operator==(const stcMDNS_RRDomain& p_Other) const -{ - - return compare(p_Other); -} - -/* - MDNSResponder::stcMDNS_RRDomain::operator != -*/ -bool MDNSResponder::stcMDNS_RRDomain::operator!=(const stcMDNS_RRDomain& p_Other) const -{ - - return !compare(p_Other); -} - -/* - MDNSResponder::stcMDNS_RRDomain::operator > -*/ -bool MDNSResponder::stcMDNS_RRDomain::operator>(const stcMDNS_RRDomain& p_Other) const -{ - - // TODO: Check, if this is a good idea... - return !compare(p_Other); -} - -/* - MDNSResponder::stcMDNS_RRDomain::c_strLength -*/ -size_t MDNSResponder::stcMDNS_RRDomain::c_strLength(void) const -{ - - size_t stLength = 0; - - unsigned char* pucLabelLength = (unsigned char*)m_acName; - while (*pucLabelLength) - { - stLength += (*pucLabelLength + 1 /* +1 for '.' or '\0'*/); - pucLabelLength += (*pucLabelLength + 1); - } - return stLength; -} - -/* - MDNSResponder::stcMDNS_RRDomain::c_str -*/ -bool MDNSResponder::stcMDNS_RRDomain::c_str(char* p_pcBuffer) -{ - - bool bResult = false; - - if (p_pcBuffer) - { - *p_pcBuffer = 0; - unsigned char* pucLabelLength = (unsigned char*)m_acName; - while (*pucLabelLength) - { - memcpy(p_pcBuffer, (const char*)(pucLabelLength + 1), *pucLabelLength); - p_pcBuffer += *pucLabelLength; - pucLabelLength += (*pucLabelLength + 1); - *p_pcBuffer++ = (*pucLabelLength ? '.' : '\0'); - } - bResult = true; - } - return bResult; -} - - -/** - MDNSResponder::stcMDNS_RRAttributes - - A MDNS attributes object. - -*/ - -/* - MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes constructor -*/ -MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes(uint16_t p_u16Type /*= 0*/, - uint16_t p_u16Class /*= 1 DNS_RRCLASS_IN Internet*/) - : m_u16Type(p_u16Type), - m_u16Class(p_u16Class) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes copy-constructor -*/ -MDNSResponder::stcMDNS_RRAttributes::stcMDNS_RRAttributes(const MDNSResponder::stcMDNS_RRAttributes& p_Other) -{ - - operator=(p_Other); -} - -/* - MDNSResponder::stcMDNS_RRAttributes::operator = -*/ -MDNSResponder::stcMDNS_RRAttributes& MDNSResponder::stcMDNS_RRAttributes::operator=(const MDNSResponder::stcMDNS_RRAttributes& p_Other) -{ - - if (&p_Other != this) - { - m_u16Type = p_Other.m_u16Type; - m_u16Class = p_Other.m_u16Class; - } - return *this; -} - - -/** - MDNSResponder::stcMDNS_RRHeader - - A MDNS record header (domain and attributes) object. - -*/ - -/* - MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader constructor -*/ -MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader(void) -{ - -} - -/* - MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader copy-constructor -*/ -MDNSResponder::stcMDNS_RRHeader::stcMDNS_RRHeader(const stcMDNS_RRHeader& p_Other) -{ - - operator=(p_Other); -} - -/* - MDNSResponder::stcMDNS_RRHeader::operator = -*/ -MDNSResponder::stcMDNS_RRHeader& MDNSResponder::stcMDNS_RRHeader::operator=(const MDNSResponder::stcMDNS_RRHeader& p_Other) -{ - - if (&p_Other != this) - { - m_Domain = p_Other.m_Domain; - m_Attributes = p_Other.m_Attributes; - } - return *this; -} - -/* - MDNSResponder::stcMDNS_RRHeader::clear -*/ -bool MDNSResponder::stcMDNS_RRHeader::clear(void) -{ - - m_Domain.clear(); - return true; -} - - -/** - MDNSResponder::stcMDNS_RRQuestion - - A MDNS question record object (header + question flags) - -*/ - -/* - MDNSResponder::stcMDNS_RRQuestion::stcMDNS_RRQuestion constructor -*/ -MDNSResponder::stcMDNS_RRQuestion::stcMDNS_RRQuestion(void) - : m_pNext(0), - m_bUnicast(false) -{ - -} - - -/** - MDNSResponder::stcMDNS_RRAnswer - - A MDNS answer record object (header + answer content). - This is a 'virtual' base class for all other MDNS answer classes. - -*/ - -/* - MDNSResponder::stcMDNS_RRAnswer::stcMDNS_RRAnswer constructor -*/ -MDNSResponder::stcMDNS_RRAnswer::stcMDNS_RRAnswer(enuAnswerType p_AnswerType, - const MDNSResponder::stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : m_pNext(0), - m_AnswerType(p_AnswerType), - m_Header(p_Header), - m_u32TTL(p_u32TTL) -{ - - // Extract 'cache flush'-bit - m_bCacheFlush = (m_Header.m_Attributes.m_u16Class & 0x8000); - m_Header.m_Attributes.m_u16Class &= (~0x8000); -} - -/* - MDNSResponder::stcMDNS_RRAnswer::~stcMDNS_RRAnswer destructor -*/ -MDNSResponder::stcMDNS_RRAnswer::~stcMDNS_RRAnswer(void) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswer::answerType -*/ -MDNSResponder::enuAnswerType MDNSResponder::stcMDNS_RRAnswer::answerType(void) const -{ - - return m_AnswerType; -} - -/* - MDNSResponder::stcMDNS_RRAnswer::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswer::clear(void) -{ - - m_pNext = 0; - m_Header.clear(); - return true; -} - - -/** - MDNSResponder::stcMDNS_RRAnswerA - - A MDNS A answer object. - Extends the base class by an IP4 address member. - -*/ - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::stcMDNS_RRAnswerA::stcMDNS_RRAnswerA constructor -*/ -MDNSResponder::stcMDNS_RRAnswerA::stcMDNS_RRAnswerA(const MDNSResponder::stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : stcMDNS_RRAnswer(AnswerType_A, p_Header, p_u32TTL), - m_IPAddress(0, 0, 0, 0) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswerA::stcMDNS_RRAnswerA destructor -*/ -MDNSResponder::stcMDNS_RRAnswerA::~stcMDNS_RRAnswerA(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRAnswerA::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswerA::clear(void) -{ - - m_IPAddress = IPAddress(0, 0, 0, 0); - return true; -} -#endif - - -/** - MDNSResponder::stcMDNS_RRAnswerPTR - - A MDNS PTR answer object. - Extends the base class by a MDNS domain member. - -*/ - -/* - MDNSResponder::stcMDNS_RRAnswerPTR::stcMDNS_RRAnswerPTR constructor -*/ -MDNSResponder::stcMDNS_RRAnswerPTR::stcMDNS_RRAnswerPTR(const MDNSResponder::stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : stcMDNS_RRAnswer(AnswerType_PTR, p_Header, p_u32TTL) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswerPTR::~stcMDNS_RRAnswerPTR destructor -*/ -MDNSResponder::stcMDNS_RRAnswerPTR::~stcMDNS_RRAnswerPTR(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRAnswerPTR::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswerPTR::clear(void) -{ - - m_PTRDomain.clear(); - return true; -} - - -/** - MDNSResponder::stcMDNS_RRAnswerTXT - - A MDNS TXT answer object. - Extends the base class by a MDNS TXT items list member. - -*/ - -/* - MDNSResponder::stcMDNS_RRAnswerTXT::stcMDNS_RRAnswerTXT constructor -*/ -MDNSResponder::stcMDNS_RRAnswerTXT::stcMDNS_RRAnswerTXT(const MDNSResponder::stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : stcMDNS_RRAnswer(AnswerType_TXT, p_Header, p_u32TTL) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswerTXT::~stcMDNS_RRAnswerTXT destructor -*/ -MDNSResponder::stcMDNS_RRAnswerTXT::~stcMDNS_RRAnswerTXT(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRAnswerTXT::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswerTXT::clear(void) -{ - - m_Txts.clear(); - return true; -} - - -/** - MDNSResponder::stcMDNS_RRAnswerAAAA - - A MDNS AAAA answer object. - (Should) extend the base class by an IP6 address member. - -*/ - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::stcMDNS_RRAnswerAAAA::stcMDNS_RRAnswerAAAA constructor -*/ -MDNSResponder::stcMDNS_RRAnswerAAAA::stcMDNS_RRAnswerAAAA(const MDNSResponder::stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : stcMDNS_RRAnswer(AnswerType_AAAA, p_Header, p_u32TTL) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswerAAAA::~stcMDNS_RRAnswerAAAA destructor -*/ -MDNSResponder::stcMDNS_RRAnswerAAAA::~stcMDNS_RRAnswerAAAA(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRAnswerAAAA::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswerAAAA::clear(void) -{ - - return true; -} -#endif - - -/** - MDNSResponder::stcMDNS_RRAnswerSRV - - A MDNS SRV answer object. - Extends the base class by a port member. - -*/ - -/* - MDNSResponder::stcMDNS_RRAnswerSRV::stcMDNS_RRAnswerSRV constructor -*/ -MDNSResponder::stcMDNS_RRAnswerSRV::stcMDNS_RRAnswerSRV(const MDNSResponder::stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : stcMDNS_RRAnswer(AnswerType_SRV, p_Header, p_u32TTL), - m_u16Priority(0), - m_u16Weight(0), - m_u16Port(0) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswerSRV::~stcMDNS_RRAnswerSRV destructor -*/ -MDNSResponder::stcMDNS_RRAnswerSRV::~stcMDNS_RRAnswerSRV(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRAnswerSRV::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswerSRV::clear(void) -{ - - m_u16Priority = 0; - m_u16Weight = 0; - m_u16Port = 0; - m_SRVDomain.clear(); - return true; -} - - -/** - MDNSResponder::stcMDNS_RRAnswerGeneric - - An unknown (generic) MDNS answer object. - Extends the base class by a RDATA buffer member. - -*/ - -/* - MDNSResponder::stcMDNS_RRAnswerGeneric::stcMDNS_RRAnswerGeneric constructor -*/ -MDNSResponder::stcMDNS_RRAnswerGeneric::stcMDNS_RRAnswerGeneric(const stcMDNS_RRHeader& p_Header, - uint32_t p_u32TTL) - : stcMDNS_RRAnswer(AnswerType_Generic, p_Header, p_u32TTL), - m_u16RDLength(0), - m_pu8RDData(0) -{ - -} - -/* - MDNSResponder::stcMDNS_RRAnswerGeneric::~stcMDNS_RRAnswerGeneric destructor -*/ -MDNSResponder::stcMDNS_RRAnswerGeneric::~stcMDNS_RRAnswerGeneric(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNS_RRAnswerGeneric::clear -*/ -bool MDNSResponder::stcMDNS_RRAnswerGeneric::clear(void) -{ - - if (m_pu8RDData) - { - delete[] m_pu8RDData; - m_pu8RDData = 0; - } - m_u16RDLength = 0; - - return true; -} - - -/** - MDNSResponder::stcProbeInformation - - Probing status information for a host or service domain - -*/ - -/* - MDNSResponder::stcProbeInformation::stcProbeInformation constructor -*/ -MDNSResponder::stcProbeInformation::stcProbeInformation(void) - : m_ProbingStatus(ProbingStatus_WaitingForData), - m_u8SentCount(0), - m_Timeout(esp8266::polledTimeout::oneShotMs::neverExpires), - m_bConflict(false), - m_bTiebreakNeeded(false), - m_fnHostProbeResultCallback(0), - m_fnServiceProbeResultCallback(0) -{ -} - -/* - MDNSResponder::stcProbeInformation::clear -*/ -bool MDNSResponder::stcProbeInformation::clear(bool p_bClearUserdata /*= false*/) -{ - - m_ProbingStatus = ProbingStatus_WaitingForData; - m_u8SentCount = 0; - m_Timeout.resetToNeverExpires(); - m_bConflict = false; - m_bTiebreakNeeded = false; - if (p_bClearUserdata) - { - m_fnHostProbeResultCallback = 0; - m_fnServiceProbeResultCallback = 0; - } - return true; -} - -/** - MDNSResponder::stcMDNSService - - A MDNS service object (to be announced by the MDNS responder) - The service instance may be '\0'; in this case the hostname is used - and the flag m_bAutoName is set. If the hostname changes, all 'auto- - named' services are renamed also. - m_u8Replymask is used while preparing a response to a MDNS query. It is - resetted in '_sendMDNSMessage' afterwards. -*/ - -/* - MDNSResponder::stcMDNSService::stcMDNSService constructor -*/ -MDNSResponder::stcMDNSService::stcMDNSService(const char* p_pcName /*= 0*/, - const char* p_pcService /*= 0*/, - const char* p_pcProtocol /*= 0*/) - : m_pNext(0), - m_pcName(0), - m_bAutoName(false), - m_pcService(0), - m_pcProtocol(0), - m_u16Port(0), - m_u8ReplyMask(0), - m_fnTxtCallback(0) -{ - - setName(p_pcName); - setService(p_pcService); - setProtocol(p_pcProtocol); -} - -/* - MDNSResponder::stcMDNSService::~stcMDNSService destructor -*/ -MDNSResponder::stcMDNSService::~stcMDNSService(void) -{ - - releaseName(); - releaseService(); - releaseProtocol(); -} - -/* - MDNSResponder::stcMDNSService::setName -*/ -bool MDNSResponder::stcMDNSService::setName(const char* p_pcName) -{ - - bool bResult = false; - - releaseName(); - size_t stLength = (p_pcName ? strlen(p_pcName) : 0); - if (stLength) - { - if ((bResult = (0 != (m_pcName = new char[stLength + 1])))) - { - strncpy(m_pcName, p_pcName, stLength); - m_pcName[stLength] = 0; - } - } - else - { - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSService::releaseName -*/ -bool MDNSResponder::stcMDNSService::releaseName(void) -{ - - if (m_pcName) - { - delete[] m_pcName; - m_pcName = 0; - } - return true; -} - -/* - MDNSResponder::stcMDNSService::setService -*/ -bool MDNSResponder::stcMDNSService::setService(const char* p_pcService) -{ - - bool bResult = false; - - releaseService(); - size_t stLength = (p_pcService ? strlen(p_pcService) : 0); - if (stLength) - { - if ((bResult = (0 != (m_pcService = new char[stLength + 1])))) - { - strncpy(m_pcService, p_pcService, stLength); - m_pcService[stLength] = 0; - } - } - else - { - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSService::releaseService -*/ -bool MDNSResponder::stcMDNSService::releaseService(void) -{ - - if (m_pcService) - { - delete[] m_pcService; - m_pcService = 0; - } - return true; -} - -/* - MDNSResponder::stcMDNSService::setProtocol -*/ -bool MDNSResponder::stcMDNSService::setProtocol(const char* p_pcProtocol) -{ - - bool bResult = false; - - releaseProtocol(); - size_t stLength = (p_pcProtocol ? strlen(p_pcProtocol) : 0); - if (stLength) - { - if ((bResult = (0 != (m_pcProtocol = new char[stLength + 1])))) - { - strncpy(m_pcProtocol, p_pcProtocol, stLength); - m_pcProtocol[stLength] = 0; - } - } - else - { - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSService::releaseProtocol -*/ -bool MDNSResponder::stcMDNSService::releaseProtocol(void) -{ - - if (m_pcProtocol) - { - delete[] m_pcProtocol; - m_pcProtocol = 0; - } - return true; -} - - -/** - MDNSResponder::stcMDNSServiceQuery - - A MDNS service query object. - Service queries may be static or dynamic. - As the static service query is processed in the blocking function 'queryService', - only one static service service may exist. The processing of the answers is done - on the WiFi-stack side of the ESP stack structure (via 'UDPContext.onRx(_update)'). - -*/ - -/** - MDNSResponder::stcMDNSServiceQuery::stcAnswer - - One answer for a service query. - Every answer must contain - - a service instance entry (pivot), - and may contain - - a host domain, - - a port - - an IP4 address - (- an IP6 address) - - a MDNS TXTs - The existance of a component is flaged in 'm_u32ContentFlags'. - For every answer component a TTL value is maintained. - Answer objects can be connected to a linked list. - - For the host domain, service domain and TXTs components, a char array - representation can be retrieved (which is created on demand). - -*/ - -/** - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL - - The TTL (Time-To-Live) for an specific answer content. - The 80% and outdated states are calculated based on the current time (millis) - and the 'set' time (also millis). - If the answer is scheduled for an update, the corresponding flag should be set. - - / - - / * - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL constructor - / - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL(uint32_t p_u32TTL / *= 0* /) - : m_bUpdateScheduled(false) { - - set(p_u32TTL * 1000); - } - - / * - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set - / - bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set(uint32_t p_u32TTL) { - - m_TTLTimeFlag.restart(p_u32TTL * 1000); - m_bUpdateScheduled = false; - - return true; - } - - / * - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::has80Percent - / - bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::has80Percent(void) const { - - return ((m_TTLTimeFlag.getTimeout()) && - (!m_bUpdateScheduled) && - (m_TTLTimeFlag.hypotheticalTimeout((m_TTLTimeFlag.getTimeout() * 800) / 1000))); - } - - / * - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::isOutdated - / - bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::isOutdated(void) const { - - return ((m_TTLTimeFlag.getTimeout()) && - (m_TTLTimeFlag.flagged())); - }*/ - - -/** - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL - - The TTL (Time-To-Live) for an specific answer content. - The 80% and outdated states are calculated based on the current time (millis) - and the 'set' time (also millis). - If the answer is scheduled for an update, the corresponding flag should be set. - -*/ - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL constructor -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL(void) - : m_u32TTL(0), - m_TTLTimeout(esp8266::polledTimeout::oneShotMs::neverExpires), - m_timeoutLevel(TIMEOUTLEVEL_UNSET) -{ - -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set(uint32_t p_u32TTL) -{ - - m_u32TTL = p_u32TTL; - if (m_u32TTL) - { - m_timeoutLevel = TIMEOUTLEVEL_BASE; // Set to 80% - m_TTLTimeout.reset(timeout()); - } - else - { - m_timeoutLevel = TIMEOUTLEVEL_UNSET; // undef - m_TTLTimeout.resetToNeverExpires(); - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged(void) -{ - - return ((m_u32TTL) && - (TIMEOUTLEVEL_UNSET != m_timeoutLevel) && - (m_TTLTimeout.expired())); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::restart -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::restart(void) -{ - - bool bResult = true; - - if ((TIMEOUTLEVEL_BASE <= m_timeoutLevel) && // >= 80% AND - (TIMEOUTLEVEL_FINAL > m_timeoutLevel)) // < 100% - { - - m_timeoutLevel += TIMEOUTLEVEL_INTERVAL; // increment by 5% - m_TTLTimeout.reset(timeout()); - } - else - { - bResult = false; - m_TTLTimeout.resetToNeverExpires(); - m_timeoutLevel = TIMEOUTLEVEL_UNSET; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::prepareDeletion -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::prepareDeletion(void) -{ - - m_timeoutLevel = TIMEOUTLEVEL_FINAL; - m_TTLTimeout.reset(1 * 1000); // See RFC 6762, 10.1 - - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::finalTimeoutLevel -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::finalTimeoutLevel(void) const -{ - - return (TIMEOUTLEVEL_FINAL == m_timeoutLevel); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::timeout -*/ -unsigned long MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::timeout(void) const -{ - - uint32_t u32Timeout = esp8266::polledTimeout::oneShotMs::neverExpires; - - if (TIMEOUTLEVEL_BASE == m_timeoutLevel) // 80% - { - u32Timeout = (m_u32TTL * 800); // to milliseconds - } - else if ((TIMEOUTLEVEL_BASE < m_timeoutLevel) && // >80% AND - (TIMEOUTLEVEL_FINAL >= m_timeoutLevel)) // <= 100% - { - - u32Timeout = (m_u32TTL * 50); - } // else: invalid - return u32Timeout; -} - - -#ifdef MDNS_IP4_SUPPORT -/** - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address - -*/ - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address::stcIP4Address constructor -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address::stcIP4Address(IPAddress p_IPAddress, - uint32_t p_u32TTL /*= 0*/) - : m_pNext(0), - m_IPAddress(p_IPAddress) -{ - - m_TTL.set(p_u32TTL); -} -#endif - - -/** - MDNSResponder::stcMDNSServiceQuery::stcAnswer -*/ - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcAnswer constructor -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcAnswer(void) - : m_pNext(0), - m_pcServiceDomain(0), - m_pcHostDomain(0), - m_u16Port(0), - m_pcTxts(0), -#ifdef MDNS_IP4_SUPPORT - m_pIP4Addresses(0), -#endif -#ifdef MDNS_IP6_SUPPORT - m_pIP6Addresses(0), -#endif - m_u32ContentFlags(0) -{ -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::~stcAnswer destructor -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::~stcAnswer(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::clear -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::clear(void) -{ - - return ((releaseTxts()) && -#ifdef MDNS_IP4_SUPPORT - (releaseIP4Addresses()) && -#endif -#ifdef MDNS_IP6_SUPPORT - (releaseIP6Addresses()) -#endif - (releaseHostDomain()) && - (releaseServiceDomain())); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocServiceDomain - - Alloc memory for the char array representation of the service domain. - -*/ -char* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocServiceDomain(size_t p_stLength) -{ - - releaseServiceDomain(); - if (p_stLength) - { - m_pcServiceDomain = new char[p_stLength]; - } - return m_pcServiceDomain; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseServiceDomain -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseServiceDomain(void) -{ - - if (m_pcServiceDomain) - { - delete[] m_pcServiceDomain; - m_pcServiceDomain = 0; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocHostDomain - - Alloc memory for the char array representation of the host domain. - -*/ -char* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocHostDomain(size_t p_stLength) -{ - - releaseHostDomain(); - if (p_stLength) - { - m_pcHostDomain = new char[p_stLength]; - } - return m_pcHostDomain; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseHostDomain -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseHostDomain(void) -{ - - if (m_pcHostDomain) - { - delete[] m_pcHostDomain; - m_pcHostDomain = 0; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocTxts - - Alloc memory for the char array representation of the TXT items. - -*/ -char* MDNSResponder::stcMDNSServiceQuery::stcAnswer::allocTxts(size_t p_stLength) -{ - - releaseTxts(); - if (p_stLength) - { - m_pcTxts = new char[p_stLength]; - } - return m_pcTxts; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseTxts -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseTxts(void) -{ - - if (m_pcTxts) - { - delete[] m_pcTxts; - m_pcTxts = 0; - } - return true; -} - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP4Addresses -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP4Addresses(void) -{ - - while (m_pIP4Addresses) - { - stcIP4Address* pNext = m_pIP4Addresses->m_pNext; - delete m_pIP4Addresses; - m_pIP4Addresses = pNext; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP4Address -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP4Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* p_pIP4Address) -{ - - bool bResult = false; - - if (p_pIP4Address) - { - p_pIP4Address->m_pNext = m_pIP4Addresses; - m_pIP4Addresses = p_pIP4Address; - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP4Address -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP4Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* p_pIP4Address) -{ - - bool bResult = false; - - if (p_pIP4Address) - { - stcIP4Address* pPred = m_pIP4Addresses; - while ((pPred) && - (pPred->m_pNext != p_pIP4Address)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pIP4Address->m_pNext; - delete p_pIP4Address; - bResult = true; - } - else if (m_pIP4Addresses == p_pIP4Address) // No predecesor, but first item - { - m_pIP4Addresses = p_pIP4Address->m_pNext; - delete p_pIP4Address; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address (const) -*/ -const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address(const IPAddress& p_IPAddress) const -{ - - return (stcIP4Address*)(((const stcAnswer*)this)->findIP4Address(p_IPAddress)); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP4Address(const IPAddress& p_IPAddress) -{ - - stcIP4Address* pIP4Address = m_pIP4Addresses; - while (pIP4Address) - { - if (pIP4Address->m_IPAddress == p_IPAddress) - { - break; - } - pIP4Address = pIP4Address->m_pNext; - } - return pIP4Address; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressCount -*/ -uint32_t MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressCount(void) const -{ - - uint32_t u32Count = 0; - - stcIP4Address* pIP4Address = m_pIP4Addresses; - while (pIP4Address) - { - ++u32Count; - pIP4Address = pIP4Address->m_pNext; - } - return u32Count; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex(uint32_t p_u32Index) -{ - - return (stcIP4Address*)(((const stcAnswer*)this)->IP4AddressAtIndex(p_u32Index)); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex (const) -*/ -const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP4AddressAtIndex(uint32_t p_u32Index) const -{ - - const stcIP4Address* pIP4Address = 0; - - if (((uint32_t)(-1) != p_u32Index) && - (m_pIP4Addresses)) - { - - uint32_t u32Index; - for (pIP4Address = m_pIP4Addresses, u32Index = 0; ((pIP4Address) && (u32Index < p_u32Index)); pIP4Address = pIP4Address->m_pNext, ++u32Index); - } - return pIP4Address; -} -#endif - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP6Addresses -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::releaseIP6Addresses(void) -{ - - while (m_pIP6Addresses) - { - stcIP6Address* pNext = m_pIP6Addresses->m_pNext; - delete m_pIP6Addresses; - m_pIP6Addresses = pNext; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP6Address -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::addIP6Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* p_pIP6Address) -{ - - bool bResult = false; - - if (p_pIP6Address) - { - p_pIP6Address->m_pNext = m_pIP6Addresses; - m_pIP6Addresses = p_pIP6Address; - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP6Address -*/ -bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::removeIP6Address(MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* p_pIP6Address) -{ - - bool bResult = false; - - if (p_pIP6Address) - { - stcIP6Address* pPred = m_pIP6Addresses; - while ((pPred) && - (pPred->m_pNext != p_pIP6Address)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pIP6Address->m_pNext; - delete p_pIP6Address; - bResult = true; - } - else if (m_pIP6Addresses == p_pIP6Address) // No predecesor, but first item - { - m_pIP6Addresses = p_pIP6Address->m_pNext; - delete p_pIP6Address; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address(const IP6Address& p_IPAddress) -{ - - return (stcIP6Address*)(((const stcAnswer*)this)->findIP6Address(p_IPAddress)); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address (const) -*/ -const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::findIP6Address(const IPAddress& p_IPAddress) const -{ - - const stcIP6Address* pIP6Address = m_pIP6Addresses; - while (pIP6Address) - { - if (p_IP6Address->m_IPAddress == p_IPAddress) - { - break; - } - pIP6Address = pIP6Address->m_pNext; - } - return pIP6Address; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressCount -*/ -uint32_t MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressCount(void) const -{ - - uint32_t u32Count = 0; - - stcIP6Address* pIP6Address = m_pIP6Addresses; - while (pIP6Address) - { - ++u32Count; - pIP6Address = pIP6Address->m_pNext; - } - return u32Count; -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex (const) -*/ -const MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex(uint32_t p_u32Index) const -{ - - return (stcIP6Address*)(((const stcAnswer*)this)->IP6AddressAtIndex(p_u32Index)); -} - -/* - MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP6Address* MDNSResponder::stcMDNSServiceQuery::stcAnswer::IP6AddressAtIndex(uint32_t p_u32Index) -{ - - stcIP6Address* pIP6Address = 0; - - if (((uint32_t)(-1) != p_u32Index) && - (m_pIP6Addresses)) - { - - uint32_t u32Index; - for (pIP6Address = m_pIP6Addresses, u32Index = 0; ((pIP6Address) && (u32Index < p_u32Index)); pIP6Address = pIP6Address->m_pNext, ++u32Index); - } - return pIP6Address; -} -#endif - - -/** - MDNSResponder::stcMDNSServiceQuery - - A service query object. - A static query is flaged via 'm_bLegacyQuery'; while the function 'queryService' - is waiting for answers, the internal flag 'm_bAwaitingAnswers' is set. When the - timeout is reached, the flag is removed. These two flags are only used for static - service queries. - All answers to the service query are stored in 'm_pAnswers' list. - Individual answers may be addressed by index (in the list of answers). - Every time a answer component is added (or changes) in a dynamic service query, - the callback 'm_fnCallback' is called. - The answer list may be searched by service and host domain. - - Service query object may be connected to a linked list. -*/ - -/* - MDNSResponder::stcMDNSServiceQuery::stcMDNSServiceQuery constructor -*/ -MDNSResponder::stcMDNSServiceQuery::stcMDNSServiceQuery(void) - : m_pNext(0), - m_fnCallback(0), - m_bLegacyQuery(false), - m_u8SentCount(0), - m_ResendTimeout(esp8266::polledTimeout::oneShotMs::neverExpires), - m_bAwaitingAnswers(true), - m_pAnswers(0) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSServiceQuery::~stcMDNSServiceQuery destructor -*/ -MDNSResponder::stcMDNSServiceQuery::~stcMDNSServiceQuery(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSServiceQuery::clear -*/ -bool MDNSResponder::stcMDNSServiceQuery::clear(void) -{ - - m_fnCallback = 0; - m_bLegacyQuery = false; - m_u8SentCount = 0; - m_ResendTimeout.resetToNeverExpires(); - m_bAwaitingAnswers = true; - while (m_pAnswers) - { - stcAnswer* pNext = m_pAnswers->m_pNext; - delete m_pAnswers; - m_pAnswers = pNext; - } - return true; -} - -/* - MDNSResponder::stcMDNSServiceQuery::answerCount -*/ -uint32_t MDNSResponder::stcMDNSServiceQuery::answerCount(void) const -{ - - uint32_t u32Count = 0; - - stcAnswer* pAnswer = m_pAnswers; - while (pAnswer) - { - ++u32Count; - pAnswer = pAnswer->m_pNext; - } - return u32Count; -} - -/* - MDNSResponder::stcMDNSServiceQuery::answerAtIndex -*/ -const MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::answerAtIndex(uint32_t p_u32Index) const -{ - - const stcAnswer* pAnswer = 0; - - if (((uint32_t)(-1) != p_u32Index) && - (m_pAnswers)) - { - - uint32_t u32Index; - for (pAnswer = m_pAnswers, u32Index = 0; ((pAnswer) && (u32Index < p_u32Index)); pAnswer = pAnswer->m_pNext, ++u32Index); - } - return pAnswer; -} - -/* - MDNSResponder::stcMDNSServiceQuery::answerAtIndex -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::answerAtIndex(uint32_t p_u32Index) -{ - - return (stcAnswer*)(((const stcMDNSServiceQuery*)this)->answerAtIndex(p_u32Index)); -} - -/* - MDNSResponder::stcMDNSServiceQuery::indexOfAnswer -*/ -uint32_t MDNSResponder::stcMDNSServiceQuery::indexOfAnswer(const MDNSResponder::stcMDNSServiceQuery::stcAnswer* p_pAnswer) const -{ - - uint32_t u32Index = 0; - - for (const stcAnswer* pAnswer = m_pAnswers; pAnswer; pAnswer = pAnswer->m_pNext, ++u32Index) - { - if (pAnswer == p_pAnswer) - { - return u32Index; - } - } - return ((uint32_t)(-1)); -} - -/* - MDNSResponder::stcMDNSServiceQuery::addAnswer -*/ -bool MDNSResponder::stcMDNSServiceQuery::addAnswer(MDNSResponder::stcMDNSServiceQuery::stcAnswer* p_pAnswer) -{ - - bool bResult = false; - - if (p_pAnswer) - { - p_pAnswer->m_pNext = m_pAnswers; - m_pAnswers = p_pAnswer; - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::removeAnswer -*/ -bool MDNSResponder::stcMDNSServiceQuery::removeAnswer(MDNSResponder::stcMDNSServiceQuery::stcAnswer* p_pAnswer) -{ - - bool bResult = false; - - if (p_pAnswer) - { - stcAnswer* pPred = m_pAnswers; - while ((pPred) && - (pPred->m_pNext != p_pAnswer)) - { - pPred = pPred->m_pNext; - } - if (pPred) - { - pPred->m_pNext = p_pAnswer->m_pNext; - delete p_pAnswer; - bResult = true; - } - else if (m_pAnswers == p_pAnswer) // No predecesor, but first item - { - m_pAnswers = p_pAnswer->m_pNext; - delete p_pAnswer; - bResult = true; - } - } - return bResult; -} - -/* - MDNSResponder::stcMDNSServiceQuery::findAnswerForServiceDomain -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::findAnswerForServiceDomain(const MDNSResponder::stcMDNS_RRDomain& p_ServiceDomain) -{ - - stcAnswer* pAnswer = m_pAnswers; - while (pAnswer) - { - if (pAnswer->m_ServiceDomain == p_ServiceDomain) - { - break; - } - pAnswer = pAnswer->m_pNext; - } - return pAnswer; -} - -/* - MDNSResponder::stcMDNSServiceQuery::findAnswerForHostDomain -*/ -MDNSResponder::stcMDNSServiceQuery::stcAnswer* MDNSResponder::stcMDNSServiceQuery::findAnswerForHostDomain(const MDNSResponder::stcMDNS_RRDomain& p_HostDomain) -{ - - stcAnswer* pAnswer = m_pAnswers; - while (pAnswer) - { - if (pAnswer->m_HostDomain == p_HostDomain) - { - break; - } - pAnswer = pAnswer->m_pNext; - } - return pAnswer; -} - - -/** - MDNSResponder::stcMDNSSendParameter - - A 'collection' of properties and flags for one MDNS query or response. - Mainly managed by the 'Control' functions. - The current offset in the UPD output buffer is tracked to be able to do - a simple host or service domain compression. - -*/ - -/** - MDNSResponder::stcMDNSSendParameter::stcDomainCacheItem - - A cached host or service domain, incl. the offset in the UDP output buffer. - -*/ - -/* - MDNSResponder::stcMDNSSendParameter::stcDomainCacheItem::stcDomainCacheItem constructor -*/ -MDNSResponder::stcMDNSSendParameter::stcDomainCacheItem::stcDomainCacheItem(const void* p_pHostnameOrService, - bool p_bAdditionalData, - uint32_t p_u16Offset) - : m_pNext(0), - m_pHostnameOrService(p_pHostnameOrService), - m_bAdditionalData(p_bAdditionalData), - m_u16Offset(p_u16Offset) -{ - -} - -/** - MDNSResponder::stcMDNSSendParameter -*/ - -/* - MDNSResponder::stcMDNSSendParameter::stcMDNSSendParameter constructor -*/ -MDNSResponder::stcMDNSSendParameter::stcMDNSSendParameter(void) - : m_pQuestions(0), - m_pDomainCacheItems(0) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSSendParameter::~stcMDNSSendParameter destructor -*/ -MDNSResponder::stcMDNSSendParameter::~stcMDNSSendParameter(void) -{ - - clear(); -} - -/* - MDNSResponder::stcMDNSSendParameter::clear -*/ -bool MDNSResponder::stcMDNSSendParameter::clear(void) -{ - - m_u16ID = 0; - m_u8HostReplyMask = 0; - m_u16Offset = 0; - - m_bLegacyQuery = false; - m_bResponse = false; - m_bAuthorative = false; - m_bUnicast = false; - m_bUnannounce = false; - - m_bCacheFlush = true; - - while (m_pQuestions) - { - stcMDNS_RRQuestion* pNext = m_pQuestions->m_pNext; - delete m_pQuestions; - m_pQuestions = pNext; - } - while (m_pDomainCacheItems) - { - stcDomainCacheItem* pNext = m_pDomainCacheItems->m_pNext; - delete m_pDomainCacheItems; - m_pDomainCacheItems = pNext; - } - return true; -} - -/* - MDNSResponder::stcMDNSSendParameter::shiftOffset -*/ -bool MDNSResponder::stcMDNSSendParameter::shiftOffset(uint16_t p_u16Shift) -{ - - m_u16Offset += p_u16Shift; - return true; -} - -/* - MDNSResponder::stcMDNSSendParameter::addDomainCacheItem -*/ -bool MDNSResponder::stcMDNSSendParameter::addDomainCacheItem(const void* p_pHostnameOrService, - bool p_bAdditionalData, - uint16_t p_u16Offset) -{ - - bool bResult = false; - - stcDomainCacheItem* pNewItem = 0; - if ((p_pHostnameOrService) && - (p_u16Offset) && - ((pNewItem = new stcDomainCacheItem(p_pHostnameOrService, p_bAdditionalData, p_u16Offset)))) - { - - pNewItem->m_pNext = m_pDomainCacheItems; - bResult = ((m_pDomainCacheItems = pNewItem)); - } - return bResult; -} - -/* - MDNSResponder::stcMDNSSendParameter::findCachedDomainOffset -*/ -uint16_t MDNSResponder::stcMDNSSendParameter::findCachedDomainOffset(const void* p_pHostnameOrService, - bool p_bAdditionalData) const -{ - - const stcDomainCacheItem* pCacheItem = m_pDomainCacheItems; - - for (; pCacheItem; pCacheItem = pCacheItem->m_pNext) - { - if ((pCacheItem->m_pHostnameOrService == p_pHostnameOrService) && - (pCacheItem->m_bAdditionalData == p_bAdditionalData)) // Found cache item - { - break; - } - } - return (pCacheItem ? pCacheItem->m_u16Offset : 0); -} - -} // namespace MDNSImplementation - -} // namespace esp8266 - - - diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Transfer.cpp b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Transfer.cpp deleted file mode 100644 index 7400abec42..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_Transfer.cpp +++ /dev/null @@ -1,1779 +0,0 @@ -/* - LEAmDNS_Transfer.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -extern "C" { -#include "user_interface.h" -} - -#include "LEAmDNS_lwIPdefs.h" -#include "LEAmDNS_Priv.h" - - -namespace esp8266 -{ - -/* - LEAmDNS -*/ -namespace MDNSImplementation -{ - -/** - CONST STRINGS -*/ -static const char* scpcLocal = "local"; -static const char* scpcServices = "services"; -static const char* scpcDNSSD = "dns-sd"; -static const char* scpcUDP = "udp"; -//static const char* scpcTCP = "tcp"; - -#ifdef MDNS_IP4_SUPPORT -static const char* scpcReverseIP4Domain = "in-addr"; -#endif -#ifdef MDNS_IP6_SUPPORT -static const char* scpcReverseIP6Domain = "ip6"; -#endif -static const char* scpcReverseTopDomain = "arpa"; - -/** - TRANSFER -*/ - - -/** - SENDING -*/ - -/* - MDNSResponder::_sendMDNSMessage - - Unicast responses are prepared and sent directly to the querier. - Multicast responses or queries are transferred to _sendMDNSMessage_Multicast - - Any reply flags in installed services are removed at the end! - -*/ -bool MDNSResponder::_sendMDNSMessage(MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - bool bResult = true; - - if (p_rSendParameter.m_bResponse && - p_rSendParameter.m_bUnicast) // Unicast response -> Send to querier - { - DEBUG_EX_ERR(if (!m_pUDPContext->getRemoteAddress()) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage: MISSING remote address for response!\n")); - }); - IPAddress ipRemote; - ipRemote = m_pUDPContext->getRemoteAddress(); - bResult = ((_prepareMDNSMessage(p_rSendParameter, _getResponseMulticastInterface())) && - (m_pUDPContext->send(ipRemote, m_pUDPContext->getRemotePort()))); - } - else // Multicast response - { - bResult = _sendMDNSMessage_Multicast(p_rSendParameter); - } - - // Finally clear service reply masks - for (stcMDNSService* pService = m_pServices; pService; pService = pService->m_pNext) - { - pService->m_u8ReplyMask = 0; - } - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_sendMDNSMessage_Multicast - - Fills the UDP output buffer (via _prepareMDNSMessage) and sends the buffer - via the selected WiFi interface (Station or AP) -*/ -bool MDNSResponder::_sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - bool bResult = false; - - IPAddress fromIPAddress; - fromIPAddress = _getResponseMulticastInterface(); - m_pUDPContext->setMulticastInterface(fromIPAddress); - -#ifdef MDNS_IP4_SUPPORT - IPAddress toMulticastAddress(DNS_MQUERY_IPV4_GROUP_INIT); -#endif -#ifdef MDNS_IP6_SUPPORT - //TODO: set multicast address - IPAddress toMulticastAddress(DNS_MQUERY_IPV6_GROUP_INIT); -#endif - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage_Multicast: Will send to '%s'.\n"), toMulticastAddress.toString().c_str());); - bResult = ((_prepareMDNSMessage(p_rSendParameter, fromIPAddress)) && - (m_pUDPContext->send(toMulticastAddress, DNS_MQUERY_PORT))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage_Multicast: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_prepareMDNSMessage - - The MDNS message is composed in a two-step process. - In the first loop 'only' the header informations (mainly number of answers) are collected, - while in the seconds loop, the header and all queries and answers are written to the UDP - output buffer. - -*/ -bool MDNSResponder::_prepareMDNSMessage(MDNSResponder::stcMDNSSendParameter& p_rSendParameter, - IPAddress p_IPAddress) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage\n"));); - bool bResult = true; - - // Prepare header; count answers - stcMDNS_MsgHeader msgHeader(p_rSendParameter.m_u16ID, p_rSendParameter.m_bResponse, 0, p_rSendParameter.m_bAuthorative); - // If this is a response, the answers are anwers, - // else this is a query or probe and the answers go into auth section - uint16_t& ru16Answers = (p_rSendParameter.m_bResponse - ? msgHeader.m_u16ANCount - : msgHeader.m_u16NSCount); - - /** - enuSequence - */ - enum enuSequence - { - Sequence_Count = 0, - Sequence_Send = 1 - }; - - // Two step sequence: 'Count' and 'Send' - for (uint32_t sequence = Sequence_Count; ((bResult) && (sequence <= Sequence_Send)); ++sequence) - { - DEBUG_EX_INFO( - if (Sequence_Send == sequence) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), - (unsigned)msgHeader.m_u16ID, - (unsigned)msgHeader.m_1bQR, (unsigned)msgHeader.m_4bOpcode, (unsigned)msgHeader.m_1bAA, (unsigned)msgHeader.m_1bTC, (unsigned)msgHeader.m_1bRD, - (unsigned)msgHeader.m_1bRA, (unsigned)msgHeader.m_4bRCode, - (unsigned)msgHeader.m_u16QDCount, - (unsigned)msgHeader.m_u16ANCount, - (unsigned)msgHeader.m_u16NSCount, - (unsigned)msgHeader.m_u16ARCount); - } - ); - // Count/send - // Header - bResult = ((Sequence_Count == sequence) - ? true - : _writeMDNSMsgHeader(msgHeader, p_rSendParameter)); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSMsgHeader FAILED!\n"));); - // Questions - for (stcMDNS_RRQuestion* pQuestion = p_rSendParameter.m_pQuestions; ((bResult) && (pQuestion)); pQuestion = pQuestion->m_pNext) - { - ((Sequence_Count == sequence) - ? ++msgHeader.m_u16QDCount - : (bResult = _writeMDNSQuestion(*pQuestion, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSQuestion FAILED!\n"));); - } - - // Answers and authorative answers -#ifdef MDNS_IP4_SUPPORT - if ((bResult) && - (p_rSendParameter.m_u8HostReplyMask & ContentFlag_A)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_A(p_IPAddress, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_A(A) FAILED!\n"));); - } - if ((bResult) && - (p_rSendParameter.m_u8HostReplyMask & ContentFlag_PTR_IP4)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_PTR_IP4(p_IPAddress, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_PTR_IP4 FAILED!\n"));); - } -#endif -#ifdef MDNS_IP6_SUPPORT - if ((bResult) && - (p_rSendParameter.m_u8HostReplyMask & ContentFlag_AAAA)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_AAAA(p_IPAddress, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_AAAA(A) FAILED!\n"));); - } - if ((bResult) && - (p_rSendParameter.m_u8HostReplyMask & ContentFlag_PTR_IP6)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_PTR_IP6(p_IPAddress, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_PTR_IP6 FAILED!\n"));); - } -#endif - - for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) - { - if ((bResult) && - (pService->m_u8ReplyMask & ContentFlag_PTR_TYPE)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_PTR_TYPE(*pService, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_PTR_TYPE FAILED!\n"));); - } - if ((bResult) && - (pService->m_u8ReplyMask & ContentFlag_PTR_NAME)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_PTR_NAME(*pService, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_PTR_NAME FAILED!\n"));); - } - if ((bResult) && - (pService->m_u8ReplyMask & ContentFlag_SRV)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_SRV(*pService, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_SRV(A) FAILED!\n"));); - } - if ((bResult) && - (pService->m_u8ReplyMask & ContentFlag_TXT)) - { - ((Sequence_Count == sequence) - ? ++ru16Answers - : (bResult = _writeMDNSAnswer_TXT(*pService, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_TXT(A) FAILED!\n"));); - } - } // for services - - // Additional answers -#ifdef MDNS_IP4_SUPPORT - bool bNeedsAdditionalAnswerA = false; -#endif -#ifdef MDNS_IP6_SUPPORT - bool bNeedsAdditionalAnswerAAAA = false; -#endif - for (stcMDNSService* pService = m_pServices; ((bResult) && (pService)); pService = pService->m_pNext) - { - if ((bResult) && - (pService->m_u8ReplyMask & ContentFlag_PTR_NAME) && // If PTR_NAME is requested, AND - (!(pService->m_u8ReplyMask & ContentFlag_SRV))) // NOT SRV -> add SRV as additional answer - { - ((Sequence_Count == sequence) - ? ++msgHeader.m_u16ARCount - : (bResult = _writeMDNSAnswer_SRV(*pService, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_SRV(B) FAILED!\n"));); - } - if ((bResult) && - (pService->m_u8ReplyMask & ContentFlag_PTR_NAME) && // If PTR_NAME is requested, AND - (!(pService->m_u8ReplyMask & ContentFlag_TXT))) // NOT TXT -> add TXT as additional answer - { - ((Sequence_Count == sequence) - ? ++msgHeader.m_u16ARCount - : (bResult = _writeMDNSAnswer_TXT(*pService, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_TXT(B) FAILED!\n"));); - } - if ((pService->m_u8ReplyMask & (ContentFlag_PTR_NAME | ContentFlag_SRV)) || // If service instance name or SRV OR - (p_rSendParameter.m_u8HostReplyMask & (ContentFlag_A | ContentFlag_AAAA))) // any host IP address is requested - { -#ifdef MDNS_IP4_SUPPORT - if ((bResult) && - (!(p_rSendParameter.m_u8HostReplyMask & ContentFlag_A))) // Add IP4 address - { - bNeedsAdditionalAnswerA = true; - } -#endif -#ifdef MDNS_IP6_SUPPORT - if ((bResult) && - (!(p_rSendParameter.m_u8HostReplyMask & ContentFlag_AAAA))) // Add IP6 address - { - bNeedsAdditionalAnswerAAAA = true; - } -#endif - } - } // for services - - // Answer A needed? -#ifdef MDNS_IP4_SUPPORT - if ((bResult) && - (bNeedsAdditionalAnswerA)) - { - ((Sequence_Count == sequence) - ? ++msgHeader.m_u16ARCount - : (bResult = _writeMDNSAnswer_A(p_IPAddress, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_A(B) FAILED!\n"));); - } -#endif -#ifdef MDNS_IP6_SUPPORT - // Answer AAAA needed? - if ((bResult) && - (bNeedsAdditionalAnswerAAAA)) - { - ((Sequence_Count == sequence) - ? ++msgHeader.m_u16ARCount - : (bResult = _writeMDNSAnswer_AAAA(p_IPAddress, p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: _writeMDNSAnswer_AAAA(B) FAILED!\n"));); - } -#endif - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: Loop %i FAILED!\n"), sequence);); - } // for sequence - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _prepareMDNSMessage: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_sendMDNSServiceQuery - - Creates and sends a PTR query for the given service domain. - -*/ -bool MDNSResponder::_sendMDNSServiceQuery(const MDNSResponder::stcMDNSServiceQuery& p_ServiceQuery) -{ - - return _sendMDNSQuery(p_ServiceQuery.m_ServiceTypeDomain, DNS_RRTYPE_PTR); -} - -/* - MDNSResponder::_sendMDNSQuery - - Creates and sends a query for the given domain and query type. - -*/ -bool MDNSResponder::_sendMDNSQuery(const MDNSResponder::stcMDNS_RRDomain& p_QueryDomain, - uint16_t p_u16QueryType, - stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers /*= 0*/) -{ - - bool bResult = false; - - stcMDNSSendParameter sendParameter; - if (0 != ((sendParameter.m_pQuestions = new stcMDNS_RRQuestion))) - { - sendParameter.m_pQuestions->m_Header.m_Domain = p_QueryDomain; - - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = p_u16QueryType; - // It seems, that some mDNS implementations don't support 'unicast response' questions... - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (/*0x8000 |*/ DNS_RRCLASS_IN); // /*Unicast &*/ INternet - - // TODO: Add knwon answer to the query - (void)p_pKnownAnswers; - - bResult = _sendMDNSMessage(sendParameter); - } // else: FAILED to alloc question - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSQuery: FAILED to alloc question!\n"));); - return bResult; -} - -/** - HELPERS -*/ - -/** - RESOURCE RECORDS -*/ - -/* - MDNSResponder::_readRRQuestion - - Reads a question (eg. MyESP._http._tcp.local ANY IN) from the UPD input buffer. - -*/ -bool MDNSResponder::_readRRQuestion(MDNSResponder::stcMDNS_RRQuestion& p_rRRQuestion) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRQuestion\n"));); - - bool bResult = false; - - if ((bResult = _readRRHeader(p_rRRQuestion.m_Header))) - { - // Extract unicast flag from class field - p_rRRQuestion.m_bUnicast = (p_rRRQuestion.m_Header.m_Attributes.m_u16Class & 0x8000); - p_rRRQuestion.m_Header.m_Attributes.m_u16Class &= (~0x8000); - - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRQuestion ")); - _printRRDomain(p_rRRQuestion.m_Header.m_Domain); - DEBUG_OUTPUT.printf_P(PSTR(" Type:0x%04X Class:0x%04X %s\n"), (unsigned)p_rRRQuestion.m_Header.m_Attributes.m_u16Type, (unsigned)p_rRRQuestion.m_Header.m_Attributes.m_u16Class, (p_rRRQuestion.m_bUnicast ? "Unicast" : "Multicast")); - ); - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRQuestion: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_readRRAnswer - - Reads an answer (eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local) - from the UDP input buffer. - After reading the domain and type info, the further processing of the answer - is transferred the answer specific reading functions. - Unknown answer types are processed by the generic answer reader (to remove them - from the input buffer). - -*/ -bool MDNSResponder::_readRRAnswer(MDNSResponder::stcMDNS_RRAnswer*& p_rpRRAnswer) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer\n"));); - - bool bResult = false; - - stcMDNS_RRHeader header; - uint32_t u32TTL; - uint16_t u16RDLength; - if ((_readRRHeader(header)) && - (_udpRead32(u32TTL)) && - (_udpRead16(u16RDLength))) - { - - /* DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer: Reading 0x%04X answer (class:0x%04X, TTL:%u, RDLength:%u) for "), header.m_Attributes.m_u16Type, header.m_Attributes.m_u16Class, u32TTL, u16RDLength); - _printRRDomain(header.m_Domain); - DEBUG_OUTPUT.printf_P(PSTR("\n")); - );*/ - - switch (header.m_Attributes.m_u16Type & (~0x8000)) // Topmost bit might carry 'cache flush' flag - { -#ifdef MDNS_IP4_SUPPORT - case DNS_RRTYPE_A: - p_rpRRAnswer = new stcMDNS_RRAnswerA(header, u32TTL); - bResult = _readRRAnswerA(*(stcMDNS_RRAnswerA*&)p_rpRRAnswer, u16RDLength); - break; -#endif - case DNS_RRTYPE_PTR: - p_rpRRAnswer = new stcMDNS_RRAnswerPTR(header, u32TTL); - bResult = _readRRAnswerPTR(*(stcMDNS_RRAnswerPTR*&)p_rpRRAnswer, u16RDLength); - break; - case DNS_RRTYPE_TXT: - p_rpRRAnswer = new stcMDNS_RRAnswerTXT(header, u32TTL); - bResult = _readRRAnswerTXT(*(stcMDNS_RRAnswerTXT*&)p_rpRRAnswer, u16RDLength); - break; -#ifdef MDNS_IP6_SUPPORT - case DNS_RRTYPE_AAAA: - p_rpRRAnswer = new stcMDNS_RRAnswerAAAA(header, u32TTL); - bResult = _readRRAnswerAAAA(*(stcMDNS_RRAnswerAAAA*&)p_rpRRAnswer, u16RDLength); - break; -#endif - case DNS_RRTYPE_SRV: - p_rpRRAnswer = new stcMDNS_RRAnswerSRV(header, u32TTL); - bResult = _readRRAnswerSRV(*(stcMDNS_RRAnswerSRV*&)p_rpRRAnswer, u16RDLength); - break; - default: - p_rpRRAnswer = new stcMDNS_RRAnswerGeneric(header, u32TTL); - bResult = _readRRAnswerGeneric(*(stcMDNS_RRAnswerGeneric*&)p_rpRRAnswer, u16RDLength); - break; - } - DEBUG_EX_INFO( - if ((bResult) && - (p_rpRRAnswer)) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer: ")); - _printRRDomain(p_rpRRAnswer->m_Header.m_Domain); - DEBUG_OUTPUT.printf_P(PSTR(" Type:0x%04X Class:0x%04X TTL:%u, RDLength:%u "), p_rpRRAnswer->m_Header.m_Attributes.m_u16Type, p_rpRRAnswer->m_Header.m_Attributes.m_u16Class, p_rpRRAnswer->m_u32TTL, u16RDLength); - switch (header.m_Attributes.m_u16Type & (~0x8000)) // Topmost bit might carry 'cache flush' flag - { -#ifdef MDNS_IP4_SUPPORT - case DNS_RRTYPE_A: - DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((stcMDNS_RRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); - break; -#endif - case DNS_RRTYPE_PTR: - DEBUG_OUTPUT.printf_P(PSTR("PTR ")); - _printRRDomain(((stcMDNS_RRAnswerPTR*&)p_rpRRAnswer)->m_PTRDomain); - break; - case DNS_RRTYPE_TXT: - { - size_t stTxtLength = ((stcMDNS_RRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_strLength(); - char* pTxts = new char[stTxtLength]; - if (pTxts) - { - ((stcMDNS_RRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_str(pTxts); - DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts); - delete[] pTxts; - } - break; - } -#ifdef MDNS_IP6_SUPPORT - case DNS_RRTYPE_AAAA: - DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((stcMDNS_RRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); - break; -#endif - case DNS_RRTYPE_SRV: - DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((stcMDNS_RRAnswerSRV*&)p_rpRRAnswer)->m_u16Port); - _printRRDomain(((stcMDNS_RRAnswerSRV*&)p_rpRRAnswer)->m_SRVDomain); - break; - default: - DEBUG_OUTPUT.printf_P(PSTR("generic ")); - break; - } - DEBUG_OUTPUT.printf_P(PSTR("\n")); - } - else - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer: FAILED to read specific answer of type 0x%04X!\n"), p_rpRRAnswer->m_Header.m_Attributes.m_u16Type); - } - ); // DEBUG_EX_INFO - } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer: FAILED!\n"));); - return bResult; -} - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::_readRRAnswerA -*/ -bool MDNSResponder::_readRRAnswerA(MDNSResponder::stcMDNS_RRAnswerA& p_rRRAnswerA, - uint16_t p_u16RDLength) -{ - - uint32_t u32IP4Address; - bool bResult = ((MDNS_IP4_SIZE == p_u16RDLength) && - (_udpReadBuffer((unsigned char*)&u32IP4Address, MDNS_IP4_SIZE)) && - ((p_rRRAnswerA.m_IPAddress = IPAddress(u32IP4Address)))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerA: FAILED!\n"));); - return bResult; -} -#endif - -/* - MDNSResponder::_readRRAnswerPTR -*/ -bool MDNSResponder::_readRRAnswerPTR(MDNSResponder::stcMDNS_RRAnswerPTR& p_rRRAnswerPTR, - uint16_t p_u16RDLength) -{ - - bool bResult = ((p_u16RDLength) && - (_readRRDomain(p_rRRAnswerPTR.m_PTRDomain))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerPTR: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_readRRAnswerTXT - - Read TXT items from a buffer like 4c#=15ff=20 -*/ -bool MDNSResponder::_readRRAnswerTXT(MDNSResponder::stcMDNS_RRAnswerTXT& p_rRRAnswerTXT, - uint16_t p_u16RDLength) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: RDLength:%u\n"), p_u16RDLength);); - bool bResult = true; - - p_rRRAnswerTXT.clear(); - if (p_u16RDLength) - { - bResult = false; - - unsigned char* pucBuffer = new unsigned char[p_u16RDLength]; - if (pucBuffer) - { - if (_udpReadBuffer(pucBuffer, p_u16RDLength)) - { - bResult = true; - - const unsigned char* pucCursor = pucBuffer; - while ((pucCursor < (pucBuffer + p_u16RDLength)) && - (bResult)) - { - bResult = false; - - stcMDNSServiceTxt* pTxt = 0; - unsigned char ucLength = *pucCursor++; // Length of the next txt item - if (ucLength) - { - DEBUG_EX_INFO( - static char sacBuffer[64]; *sacBuffer = 0; - uint8_t u8MaxLength = ((ucLength > (sizeof(sacBuffer) - 1)) ? (sizeof(sacBuffer) - 1) : ucLength); - os_strncpy(sacBuffer, (const char*)pucCursor, u8MaxLength); sacBuffer[u8MaxLength] = 0; - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: Item(%u): %s\n"), ucLength, sacBuffer); - ); - - unsigned char* pucEqualSign = (unsigned char*)os_strchr((const char*)pucCursor, '='); // Position of the '=' sign - unsigned char ucKeyLength; - if ((pucEqualSign) && - ((ucKeyLength = (pucEqualSign - pucCursor)))) - { - unsigned char ucValueLength = (ucLength - (pucEqualSign - pucCursor + 1)); - bResult = (((pTxt = new stcMDNSServiceTxt)) && - (pTxt->setKey((const char*)pucCursor, ucKeyLength)) && - (pTxt->setValue((const char*)(pucEqualSign + 1), ucValueLength))); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: INVALID TXT format (No '=')!\n"));); - } - pucCursor += ucLength; - } - else // no/zero length TXT - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: TXT answer contains no items.\n"));); - bResult = true; - } - - if ((bResult) && - (pTxt)) // Everythings fine so far - { - // Link TXT item to answer TXTs - pTxt->m_pNext = p_rRRAnswerTXT.m_Txts.m_pTxts; - p_rRRAnswerTXT.m_Txts.m_pTxts = pTxt; - } - else // At least no TXT (migth be OK, if length was 0) OR an error - { - if (!bResult) - { - DEBUG_EX_ERR( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: FAILED to read TXT item!\n")); - DEBUG_OUTPUT.printf_P(PSTR("RData dump:\n")); - _udpDump((m_pUDPContext->tell() - p_u16RDLength), p_u16RDLength); - DEBUG_OUTPUT.printf_P(PSTR("\n")); - ); - } - if (pTxt) - { - delete pTxt; - pTxt = 0; - } - p_rRRAnswerTXT.clear(); - } - } // while - - DEBUG_EX_ERR( - if (!bResult) // Some failure - { - DEBUG_OUTPUT.printf_P(PSTR("RData dump:\n")); - _udpDump((m_pUDPContext->tell() - p_u16RDLength), p_u16RDLength); - DEBUG_OUTPUT.printf_P(PSTR("\n")); - } - ); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: FAILED to read TXT content!\n"));); - } - // Clean up - delete[] pucBuffer; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: FAILED to alloc buffer for TXT content!\n"));); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: WARNING! No content!\n"));); - } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerTXT: FAILED!\n"));); - return bResult; -} - -#ifdef MDNS_IP6_SUPPORT -bool MDNSResponder::_readRRAnswerAAAA(MDNSResponder::stcMDNS_RRAnswerAAAA& p_rRRAnswerAAAA, - uint16_t p_u16RDLength) -{ - bool bResult = false; - // TODO: Implement - return bResult; -} -#endif - -/* - MDNSResponder::_readRRAnswerSRV -*/ -bool MDNSResponder::_readRRAnswerSRV(MDNSResponder::stcMDNS_RRAnswerSRV& p_rRRAnswerSRV, - uint16_t p_u16RDLength) -{ - - bool bResult = (((3 * sizeof(uint16_t)) < p_u16RDLength) && - (_udpRead16(p_rRRAnswerSRV.m_u16Priority)) && - (_udpRead16(p_rRRAnswerSRV.m_u16Weight)) && - (_udpRead16(p_rRRAnswerSRV.m_u16Port)) && - (_readRRDomain(p_rRRAnswerSRV.m_SRVDomain))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerSRV: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_readRRAnswerGeneric -*/ -bool MDNSResponder::_readRRAnswerGeneric(MDNSResponder::stcMDNS_RRAnswerGeneric& p_rRRAnswerGeneric, - uint16_t p_u16RDLength) -{ - bool bResult = (0 == p_u16RDLength); - - p_rRRAnswerGeneric.clear(); - if (((p_rRRAnswerGeneric.m_u16RDLength = p_u16RDLength)) && - ((p_rRRAnswerGeneric.m_pu8RDData = new unsigned char[p_rRRAnswerGeneric.m_u16RDLength]))) - { - - bResult = _udpReadBuffer(p_rRRAnswerGeneric.m_pu8RDData, p_rRRAnswerGeneric.m_u16RDLength); - } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswerGeneric: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_readRRHeader -*/ -bool MDNSResponder::_readRRHeader(MDNSResponder::stcMDNS_RRHeader& p_rRRHeader) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRHeader\n"));); - - bool bResult = ((_readRRDomain(p_rRRHeader.m_Domain)) && - (_readRRAttributes(p_rRRHeader.m_Attributes))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRHeader: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_readRRDomain - - Reads a (maybe multilevel compressed) domain from the UDP input buffer. - -*/ -bool MDNSResponder::_readRRDomain(MDNSResponder::stcMDNS_RRDomain& p_rRRDomain) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain\n"));); - - bool bResult = ((p_rRRDomain.clear()) && - (_readRRDomain_Loop(p_rRRDomain, 0))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_readRRDomain_Loop - - Reads a domain from the UDP input buffer. For every compression level, the functions - calls itself recursively. To avoid endless recursion because of malformed MDNS records, - the maximum recursion depth is set by MDNS_DOMAIN_MAX_REDIRCTION. - -*/ -bool MDNSResponder::_readRRDomain_Loop(MDNSResponder::stcMDNS_RRDomain& p_rRRDomain, - uint8_t p_u8Depth) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u)\n"), p_u8Depth);); - - bool bResult = false; - - if (MDNS_DOMAIN_MAX_REDIRCTION >= p_u8Depth) - { - bResult = true; - - uint8_t u8Len = 0; - do - { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): Offset:%u p0:%02x\n"), p_u8Depth, m_pUDPContext->tell(), m_pUDPContext->peek());); - _udpRead8(u8Len); - - if (u8Len & MDNS_DOMAIN_COMPRESS_MARK) - { - // Compressed label(s) - uint16_t u16Offset = ((u8Len & ~MDNS_DOMAIN_COMPRESS_MARK) << 8); // Implicit BE to LE conversion! - _udpRead8(u8Len); - u16Offset |= u8Len; - - if (m_pUDPContext->isValidOffset(u16Offset)) - { - size_t stCurrentPosition = m_pUDPContext->tell(); // Prepare return from recursion - - //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): Redirecting from %u to %u!\n"), p_u8Depth, stCurrentPosition, u16Offset);); - m_pUDPContext->seek(u16Offset); - if (_readRRDomain_Loop(p_rRRDomain, p_u8Depth + 1)) // Do recursion - { - //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): Succeeded to read redirected label! Returning to %u\n"), p_u8Depth, stCurrentPosition);); - m_pUDPContext->seek(stCurrentPosition); // Restore after recursion - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): FAILED to read redirected label!\n"), p_u8Depth);); - bResult = false; - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): INVALID offset in redirection!\n"), p_u8Depth);); - bResult = false; - } - break; - } - else - { - // Normal (uncompressed) label (maybe '\0' only) - if (MDNS_DOMAIN_MAXLENGTH > (p_rRRDomain.m_u16NameLength + u8Len)) - { - // Add length byte - p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength] = u8Len; - ++(p_rRRDomain.m_u16NameLength); - if (u8Len) // Add name - { - if ((bResult = _udpReadBuffer((unsigned char*) & (p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength]), u8Len))) - { - /* DEBUG_EX_INFO( - p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength + u8Len] = 0; // Closing '\0' for printing - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): Domain label (%u): %s\n"), p_u8Depth, (unsigned)(p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength - 1]), &(p_rRRDomain.m_acName[p_rRRDomain.m_u16NameLength])); - );*/ - - p_rRRDomain.m_u16NameLength += u8Len; - } - } - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(2) offset:%u p0:%x\n"), m_pUDPContext->tell(), m_pUDPContext->peek());); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): ERROR! Domain name too long (%u + %u)!\n"), p_u8Depth, p_rRRDomain.m_u16NameLength, u8Len);); - bResult = false; - break; - } - } - } while ((bResult) && - (0 != u8Len)); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRDomain_Loop(%u): ERROR! Too many redirections!\n"), p_u8Depth);); - } - return bResult; -} - -/* - MDNSResponder::_readRRAttributes -*/ -bool MDNSResponder::_readRRAttributes(MDNSResponder::stcMDNS_RRAttributes& p_rRRAttributes) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAttributes\n"));); - - bool bResult = ((_udpRead16(p_rRRAttributes.m_u16Type)) && - (_udpRead16(p_rRRAttributes.m_u16Class))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAttributes: FAILED!\n"));); - return bResult; -} - - -/* - DOMAIN NAMES -*/ - -/* - MDNSResponder::_buildDomainForHost - - Builds a MDNS host domain (eg. esp8266.local) for the given hostname. - -*/ -bool MDNSResponder::_buildDomainForHost(const char* p_pcHostname, - MDNSResponder::stcMDNS_RRDomain& p_rHostDomain) const -{ - - p_rHostDomain.clear(); - bool bResult = ((p_pcHostname) && - (*p_pcHostname) && - (p_rHostDomain.addLabel(p_pcHostname)) && - (p_rHostDomain.addLabel(scpcLocal)) && - (p_rHostDomain.addLabel(0))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForHost: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_buildDomainForDNSSD - - Builds the '_services._dns-sd._udp.local' domain. - Used while detecting generic service enum question (DNS-SD) and answering these questions. - -*/ -bool MDNSResponder::_buildDomainForDNSSD(MDNSResponder::stcMDNS_RRDomain& p_rDNSSDDomain) const -{ - - p_rDNSSDDomain.clear(); - bool bResult = ((p_rDNSSDDomain.addLabel(scpcServices, true)) && - (p_rDNSSDDomain.addLabel(scpcDNSSD, true)) && - (p_rDNSSDDomain.addLabel(scpcUDP, true)) && - (p_rDNSSDDomain.addLabel(scpcLocal)) && - (p_rDNSSDDomain.addLabel(0))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForDNSSD: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_buildDomainForService - - Builds the domain for the given service (eg. _http._tcp.local or - MyESP._http._tcp.local (if p_bIncludeName is set)). - -*/ -bool MDNSResponder::_buildDomainForService(const MDNSResponder::stcMDNSService& p_Service, - bool p_bIncludeName, - MDNSResponder::stcMDNS_RRDomain& p_rServiceDomain) const -{ - - p_rServiceDomain.clear(); - bool bResult = (((!p_bIncludeName) || - (p_rServiceDomain.addLabel(p_Service.m_pcName))) && - (p_rServiceDomain.addLabel(p_Service.m_pcService, true)) && - (p_rServiceDomain.addLabel(p_Service.m_pcProtocol, true)) && - (p_rServiceDomain.addLabel(scpcLocal)) && - (p_rServiceDomain.addLabel(0))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForService: FAILED!\n"));); - return bResult; -} - -/* - MDNSResponder::_buildDomainForService - - Builds the domain for the given service properties (eg. _http._tcp.local). - The usual prepended '_' are added, if missing in the input strings. - -*/ -bool MDNSResponder::_buildDomainForService(const char* p_pcService, - const char* p_pcProtocol, - MDNSResponder::stcMDNS_RRDomain& p_rServiceDomain) const -{ - - p_rServiceDomain.clear(); - bool bResult = ((p_pcService) && - (p_pcProtocol) && - (p_rServiceDomain.addLabel(p_pcService, ('_' != *p_pcService))) && - (p_rServiceDomain.addLabel(p_pcProtocol, ('_' != *p_pcProtocol))) && - (p_rServiceDomain.addLabel(scpcLocal)) && - (p_rServiceDomain.addLabel(0))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForService: FAILED for (%s.%s)!\n"), (p_pcService ? : "-"), (p_pcProtocol ? : "-"));); - return bResult; -} - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::_buildDomainForReverseIP4 - - The IP4 address is stringized by printing the four address bytes into a char buffer in reverse order - and adding 'in-addr.arpa' (eg. 012.789.456.123.in-addr.arpa). - Used while detecting reverse IP4 questions and answering these -*/ -bool MDNSResponder::_buildDomainForReverseIP4(IPAddress p_IP4Address, - MDNSResponder::stcMDNS_RRDomain& p_rReverseIP4Domain) const -{ - - bool bResult = true; - - p_rReverseIP4Domain.clear(); - - char acBuffer[32]; - for (int i = MDNS_IP4_SIZE; ((bResult) && (i >= 1)); --i) - { - itoa(p_IP4Address[i - 1], acBuffer, 10); - bResult = p_rReverseIP4Domain.addLabel(acBuffer); - } - bResult = ((bResult) && - (p_rReverseIP4Domain.addLabel(scpcReverseIP4Domain)) && - (p_rReverseIP4Domain.addLabel(scpcReverseTopDomain)) && - (p_rReverseIP4Domain.addLabel(0))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _buildDomainForReverseIP4: FAILED!\n"));); - return bResult; -} -#endif - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::_buildDomainForReverseIP6 - - Used while detecting reverse IP6 questions and answering these -*/ -bool MDNSResponder::_buildDomainForReverseIP6(IPAddress p_IP4Address, - MDNSResponder::stcMDNS_RRDomain& p_rReverseIP6Domain) const -{ - // TODO: Implement - return false; -} -#endif - - -/* - UDP -*/ - -/* - MDNSResponder::_udpReadBuffer -*/ -bool MDNSResponder::_udpReadBuffer(unsigned char* p_pBuffer, - size_t p_stLength) -{ - - bool bResult = ((m_pUDPContext) && - (true/*m_pUDPContext->getSize() > p_stLength*/) && - (p_pBuffer) && - (p_stLength) && - ((p_stLength == m_pUDPContext->read((char*)p_pBuffer, p_stLength)))); - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _udpReadBuffer: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_udpRead8 -*/ -bool MDNSResponder::_udpRead8(uint8_t& p_ru8Value) -{ - - return _udpReadBuffer((unsigned char*)&p_ru8Value, sizeof(p_ru8Value)); -} - -/* - MDNSResponder::_udpRead16 -*/ -bool MDNSResponder::_udpRead16(uint16_t& p_ru16Value) -{ - - bool bResult = false; - - if (_udpReadBuffer((unsigned char*)&p_ru16Value, sizeof(p_ru16Value))) - { - p_ru16Value = lwip_ntohs(p_ru16Value); - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::_udpRead32 -*/ -bool MDNSResponder::_udpRead32(uint32_t& p_ru32Value) -{ - - bool bResult = false; - - if (_udpReadBuffer((unsigned char*)&p_ru32Value, sizeof(p_ru32Value))) - { - p_ru32Value = lwip_ntohl(p_ru32Value); - bResult = true; - } - return bResult; -} - -/* - MDNSResponder::_udpAppendBuffer -*/ -bool MDNSResponder::_udpAppendBuffer(const unsigned char* p_pcBuffer, - size_t p_stLength) -{ - - bool bResult = ((m_pUDPContext) && - (p_pcBuffer) && - (p_stLength) && - (p_stLength == m_pUDPContext->append((const char*)p_pcBuffer, p_stLength))); - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _udpAppendBuffer: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_udpAppend8 -*/ -bool MDNSResponder::_udpAppend8(uint8_t p_u8Value) -{ - - return (_udpAppendBuffer((unsigned char*)&p_u8Value, sizeof(p_u8Value))); -} - -/* - MDNSResponder::_udpAppend16 -*/ -bool MDNSResponder::_udpAppend16(uint16_t p_u16Value) -{ - - p_u16Value = lwip_htons(p_u16Value); - return (_udpAppendBuffer((unsigned char*)&p_u16Value, sizeof(p_u16Value))); -} - -/* - MDNSResponder::_udpAppend32 -*/ -bool MDNSResponder::_udpAppend32(uint32_t p_u32Value) -{ - - p_u32Value = lwip_htonl(p_u32Value); - return (_udpAppendBuffer((unsigned char*)&p_u32Value, sizeof(p_u32Value))); -} - -#ifdef DEBUG_ESP_MDNS_RESPONDER -/* - MDNSResponder::_udpDump -*/ -bool MDNSResponder::_udpDump(bool p_bMovePointer /*= false*/) -{ - - const uint8_t cu8BytesPerLine = 16; - - uint32_t u32StartPosition = m_pUDPContext->tell(); - DEBUG_OUTPUT.println("UDP Context Dump:"); - uint32_t u32Counter = 0; - uint8_t u8Byte = 0; - - while (_udpRead8(u8Byte)) - { - DEBUG_OUTPUT.printf_P(PSTR("%02x %s"), u8Byte, ((++u32Counter % cu8BytesPerLine) ? "" : "\n")); - } - DEBUG_OUTPUT.printf_P(PSTR("%sDone: %u bytes\n"), (((u32Counter) && (u32Counter % cu8BytesPerLine)) ? "\n" : ""), u32Counter); - - if (!p_bMovePointer) // Restore - { - m_pUDPContext->seek(u32StartPosition); - } - return true; -} - -/* - MDNSResponder::_udpDump -*/ -bool MDNSResponder::_udpDump(unsigned p_uOffset, - unsigned p_uLength) -{ - - if ((m_pUDPContext) && - (m_pUDPContext->isValidOffset(p_uOffset))) - { - unsigned uCurrentPosition = m_pUDPContext->tell(); // Remember start position - - m_pUDPContext->seek(p_uOffset); - uint8_t u8Byte; - for (unsigned u = 0; ((u < p_uLength) && (_udpRead8(u8Byte))); ++u) - { - DEBUG_OUTPUT.printf_P(PSTR("%02x "), u8Byte); - } - // Return to start position - m_pUDPContext->seek(uCurrentPosition); - } - return true; -} -#endif - - -/** - READ/WRITE MDNS STRUCTS -*/ - -/* - MDNSResponder::_readMDNSMsgHeader - - Read a MDNS header from the UDP input buffer. - | 8 | 8 | 8 | 8 | - 00| Identifier | Flags & Codes | - 01| Question count | Answer count | - 02| NS answer count | Ad answer count | - - All 16-bit and 32-bit elements need to be translated form network coding to host coding (done in _udpRead16 and _udpRead32) - In addition, bitfield memory order is undefined in C standard (GCC doesn't order them in the coded direction...), so they - need some mapping here -*/ -bool MDNSResponder::_readMDNSMsgHeader(MDNSResponder::stcMDNS_MsgHeader& p_rMsgHeader) -{ - - bool bResult = false; - - uint8_t u8B1; - uint8_t u8B2; - if ((_udpRead16(p_rMsgHeader.m_u16ID)) && - (_udpRead8(u8B1)) && - (_udpRead8(u8B2)) && - (_udpRead16(p_rMsgHeader.m_u16QDCount)) && - (_udpRead16(p_rMsgHeader.m_u16ANCount)) && - (_udpRead16(p_rMsgHeader.m_u16NSCount)) && - (_udpRead16(p_rMsgHeader.m_u16ARCount))) - { - - p_rMsgHeader.m_1bQR = (u8B1 & 0x80); // Query/Responde flag - p_rMsgHeader.m_4bOpcode = (u8B1 & 0x78); // Operation code (0: Standard query, others ignored) - p_rMsgHeader.m_1bAA = (u8B1 & 0x04); // Authorative answer - p_rMsgHeader.m_1bTC = (u8B1 & 0x02); // Truncation flag - p_rMsgHeader.m_1bRD = (u8B1 & 0x01); // Recursion desired - - p_rMsgHeader.m_1bRA = (u8B2 & 0x80); // Recursion available - p_rMsgHeader.m_3bZ = (u8B2 & 0x70); // Zero - p_rMsgHeader.m_4bRCode = (u8B2 & 0x0F); // Response code - - /* DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readMDNSMsgHeader: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), - (unsigned)p_rMsgHeader.m_u16ID, - (unsigned)p_rMsgHeader.m_1bQR, (unsigned)p_rMsgHeader.m_4bOpcode, (unsigned)p_rMsgHeader.m_1bAA, (unsigned)p_rMsgHeader.m_1bTC, (unsigned)p_rMsgHeader.m_1bRD, - (unsigned)p_rMsgHeader.m_1bRA, (unsigned)p_rMsgHeader.m_4bRCode, - (unsigned)p_rMsgHeader.m_u16QDCount, - (unsigned)p_rMsgHeader.m_u16ANCount, - (unsigned)p_rMsgHeader.m_u16NSCount, - (unsigned)p_rMsgHeader.m_u16ARCount););*/ - bResult = true; - } - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readMDNSMsgHeader: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_write8 -*/ -bool MDNSResponder::_write8(uint8_t p_u8Value, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - return ((_udpAppend8(p_u8Value)) && - (p_rSendParameter.shiftOffset(sizeof(p_u8Value)))); -} - -/* - MDNSResponder::_write16 -*/ -bool MDNSResponder::_write16(uint16_t p_u16Value, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - return ((_udpAppend16(p_u16Value)) && - (p_rSendParameter.shiftOffset(sizeof(p_u16Value)))); -} - -/* - MDNSResponder::_write32 -*/ -bool MDNSResponder::_write32(uint32_t p_u32Value, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - return ((_udpAppend32(p_u32Value)) && - (p_rSendParameter.shiftOffset(sizeof(p_u32Value)))); -} - -/* - MDNSResponder::_writeMDNSMsgHeader - - Write MDNS header to the UDP output buffer. - - All 16-bit and 32-bit elements need to be translated form host coding to network coding (done in _udpAppend16 and _udpAppend32) - In addition, bitfield memory order is undefined in C standard (GCC doesn't order them in the coded direction...), so they - need some mapping here -*/ -bool MDNSResponder::_writeMDNSMsgHeader(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHeader, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - /* DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSMsgHeader: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), - (unsigned)p_MsgHeader.m_u16ID, - (unsigned)p_MsgHeader.m_1bQR, (unsigned)p_MsgHeader.m_4bOpcode, (unsigned)p_MsgHeader.m_1bAA, (unsigned)p_MsgHeader.m_1bTC, (unsigned)p_MsgHeader.m_1bRD, - (unsigned)p_MsgHeader.m_1bRA, (unsigned)p_MsgHeader.m_4bRCode, - (unsigned)p_MsgHeader.m_u16QDCount, - (unsigned)p_MsgHeader.m_u16ANCount, - (unsigned)p_MsgHeader.m_u16NSCount, - (unsigned)p_MsgHeader.m_u16ARCount););*/ - - uint8_t u8B1((p_MsgHeader.m_1bQR << 7) | (p_MsgHeader.m_4bOpcode << 3) | (p_MsgHeader.m_1bAA << 2) | (p_MsgHeader.m_1bTC << 1) | (p_MsgHeader.m_1bRD)); - uint8_t u8B2((p_MsgHeader.m_1bRA << 7) | (p_MsgHeader.m_3bZ << 4) | (p_MsgHeader.m_4bRCode)); - bool bResult = ((_write16(p_MsgHeader.m_u16ID, p_rSendParameter)) && - (_write8(u8B1, p_rSendParameter)) && - (_write8(u8B2, p_rSendParameter)) && - (_write16(p_MsgHeader.m_u16QDCount, p_rSendParameter)) && - (_write16(p_MsgHeader.m_u16ANCount, p_rSendParameter)) && - (_write16(p_MsgHeader.m_u16NSCount, p_rSendParameter)) && - (_write16(p_MsgHeader.m_u16ARCount, p_rSendParameter))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSMsgHeader: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_writeRRAttributes -*/ -bool MDNSResponder::_writeMDNSRRAttributes(const MDNSResponder::stcMDNS_RRAttributes& p_Attributes, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - bool bResult = ((_write16(p_Attributes.m_u16Type, p_rSendParameter)) && - (_write16(p_Attributes.m_u16Class, p_rSendParameter))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSRRAttributes: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_writeMDNSRRDomain -*/ -bool MDNSResponder::_writeMDNSRRDomain(const MDNSResponder::stcMDNS_RRDomain& p_Domain, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - bool bResult = ((_udpAppendBuffer((const unsigned char*)p_Domain.m_acName, p_Domain.m_u16NameLength)) && - (p_rSendParameter.shiftOffset(p_Domain.m_u16NameLength))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSRRDomain: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_writeMDNSHostDomain - - Write a host domain to the UDP output buffer. - If the domain record is part of the answer, the records length is - prepended (p_bPrependRDLength is set). - - A very simple form of name compression is applied here: - If the domain is written to the UDP output buffer, the write offset is stored - together with a domain id (the pointer) in a p_rSendParameter substructure (cache). - If the same domain (pointer) should be written to the UDP output later again, - the old offset is retrieved from the cache, marked as a compressed domain offset - and written to the output buffer. - -*/ -bool MDNSResponder::_writeMDNSHostDomain(const char* p_pcHostname, - bool p_bPrependRDLength, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - // The 'skip-compression' version is handled in '_writeMDNSAnswer_SRV' - uint16_t u16CachedDomainOffset = p_rSendParameter.findCachedDomainOffset((const void*)p_pcHostname, false); - - stcMDNS_RRDomain hostDomain; - bool bResult = (u16CachedDomainOffset - // Found cached domain -> mark as compressed domain - ? ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset - ((!p_bPrependRDLength) || - (_write16(2, p_rSendParameter))) && // Length of 'Cxxx' - (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) - (_write8((uint8_t)(u16CachedDomainOffset & 0xFF), p_rSendParameter))) - // No cached domain -> add this domain to cache and write full domain name - : ((_buildDomainForHost(p_pcHostname, hostDomain)) && // eg. esp8266.local - ((!p_bPrependRDLength) || - (_write16(hostDomain.m_u16NameLength, p_rSendParameter))) && // RDLength (if needed) - (p_rSendParameter.addDomainCacheItem((const void*)p_pcHostname, false, p_rSendParameter.m_u16Offset)) && - (_writeMDNSRRDomain(hostDomain, p_rSendParameter)))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSHostDomain: FAILED!\n")); - }); - return bResult; - -} - -/* - MDNSResponder::_writeMDNSServiceDomain - - Write a service domain to the UDP output buffer. - If the domain record is part of the answer, the records length is - prepended (p_bPrependRDLength is set). - - A very simple form of name compression is applied here: see '_writeMDNSHostDomain' - The cache differentiates of course between service domains which includes - the instance name (p_bIncludeName is set) and thoose who don't. - -*/ -bool MDNSResponder::_writeMDNSServiceDomain(const MDNSResponder::stcMDNSService& p_Service, - bool p_bIncludeName, - bool p_bPrependRDLength, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - - // The 'skip-compression' version is handled in '_writeMDNSAnswer_SRV' - uint16_t u16CachedDomainOffset = p_rSendParameter.findCachedDomainOffset((const void*)&p_Service, p_bIncludeName); - - stcMDNS_RRDomain serviceDomain; - bool bResult = (u16CachedDomainOffset - // Found cached domain -> mark as compressed domain - ? ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset - ((!p_bPrependRDLength) || - (_write16(2, p_rSendParameter))) && // Lenght of 'Cxxx' - (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) - (_write8((uint8_t)(u16CachedDomainOffset & 0xFF), p_rSendParameter))) - // No cached domain -> add this domain to cache and write full domain name - : ((_buildDomainForService(p_Service, p_bIncludeName, serviceDomain)) && // eg. MyESP._http._tcp.local - ((!p_bPrependRDLength) || - (_write16(serviceDomain.m_u16NameLength, p_rSendParameter))) && // RDLength (if needed) - (p_rSendParameter.addDomainCacheItem((const void*)&p_Service, p_bIncludeName, p_rSendParameter.m_u16Offset)) && - (_writeMDNSRRDomain(serviceDomain, p_rSendParameter)))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSServiceDomain: FAILED!\n")); - }); - return bResult; - -} - -/* - MDNSResponder::_writeMDNSQuestion - - Write a MDNS question to the UDP output buffer - - QNAME (host/service domain, eg. esp8266.local) - QTYPE (16bit, eg. ANY) - QCLASS (16bit, eg. IN) - -*/ -bool MDNSResponder::_writeMDNSQuestion(MDNSResponder::stcMDNS_RRQuestion& p_Question, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSQuestion\n"));); - - bool bResult = ((_writeMDNSRRDomain(p_Question.m_Header.m_Domain, p_rSendParameter)) && - (_writeMDNSRRAttributes(p_Question.m_Header.m_Attributes, p_rSendParameter))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSQuestion: FAILED!\n")); - }); - return bResult; - -} - - -#ifdef MDNS_IP4_SUPPORT -/* - MDNSResponder::_writeMDNSAnswer_A - - Write a MDNS A answer to the UDP output buffer. - - NAME (var, host/service domain, eg. esp8266.local - TYPE (16bit, eg. A) - CLASS (16bit, eg. IN) - TTL (32bit, eg. 120) - RDLENGTH (16bit, eg 4) - RDATA (var, eg. 123.456.789.012) - - eg. esp8266.local A 0x8001 120 4 123.456.789.012 - Ref: http://www.zytrax.com/books/dns/ch8/a.html -*/ -bool MDNSResponder::_writeMDNSAnswer_A(IPAddress p_IPAddress, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_A (%s)\n"), p_IPAddress.toString().c_str());); - - stcMDNS_RRAttributes attributes(DNS_RRTYPE_A, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - const unsigned char aucIPAddress[MDNS_IP4_SIZE] = { p_IPAddress[0], p_IPAddress[1], p_IPAddress[2], p_IPAddress[3] }; - bool bResult = ((_writeMDNSHostDomain(m_pcHostname, false, p_rSendParameter)) && - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter)) && // TTL - (_write16(MDNS_IP4_SIZE, p_rSendParameter)) && // RDLength - (_udpAppendBuffer(aucIPAddress, MDNS_IP4_SIZE)) && // RData - (p_rSendParameter.shiftOffset(MDNS_IP4_SIZE))); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_A: FAILED!\n")); - }); - return bResult; - -} - -/* - MDNSResponder::_writeMDNSAnswer_PTR_IP4 - - Write a MDNS reverse IP4 PTR answer to the UDP output buffer. - See: '_writeMDNSAnswer_A' - - eg. 012.789.456.123.in-addr.arpa PTR 0x8001 120 15 esp8266.local - Used while answering reverse IP4 questions -*/ -bool MDNSResponder::_writeMDNSAnswer_PTR_IP4(IPAddress p_IPAddress, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_IP4 (%s)\n"), p_IPAddress.toString().c_str());); - - stcMDNS_RRDomain reverseIP4Domain; - stcMDNS_RRAttributes attributes(DNS_RRTYPE_PTR, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - stcMDNS_RRDomain hostDomain; - bool bResult = ((_buildDomainForReverseIP4(p_IPAddress, reverseIP4Domain)) && // 012.789.456.123.in-addr.arpa - (_writeMDNSRRDomain(reverseIP4Domain, p_rSendParameter)) && - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter)) && // TTL - (_writeMDNSHostDomain(m_pcHostname, true, p_rSendParameter))); // RDLength & RData (host domain, eg. esp8266.local) - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_IP4: FAILED!\n")); - }); - return bResult; -} -#endif - -/* - MDNSResponder::_writeMDNSAnswer_PTR_TYPE - - Write a MDNS PTR answer to the UDP output buffer. - See: '_writeMDNSAnswer_A' - - PTR all-services -> service type - eg. _services._dns-sd._udp.local PTR 0x8001 5400 xx _http._tcp.local - http://www.zytrax.com/books/dns/ch8/ptr.html -*/ -bool MDNSResponder::_writeMDNSAnswer_PTR_TYPE(MDNSResponder::stcMDNSService& p_rService, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_TYPE\n"));); - - stcMDNS_RRDomain dnssdDomain; - stcMDNS_RRDomain serviceDomain; - stcMDNS_RRAttributes attributes(DNS_RRTYPE_PTR, DNS_RRCLASS_IN); // No cache flush! only INternet - bool bResult = ((_buildDomainForDNSSD(dnssdDomain)) && // _services._dns-sd._udp.local - (_writeMDNSRRDomain(dnssdDomain, p_rSendParameter)) && - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_SERVICE_TTL), p_rSendParameter)) && // TTL - (_writeMDNSServiceDomain(p_rService, false, true, p_rSendParameter))); // RDLength & RData (service domain, eg. _http._tcp.local) - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_TYPE: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_writeMDNSAnswer_PTR_NAME - - Write a MDNS PTR answer to the UDP output buffer. - See: '_writeMDNSAnswer_A' - - PTR service type -> service name - eg. _http.tcp.local PTR 0x8001 120 xx myESP._http._tcp.local - http://www.zytrax.com/books/dns/ch8/ptr.html -*/ -bool MDNSResponder::_writeMDNSAnswer_PTR_NAME(MDNSResponder::stcMDNSService& p_rService, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_NAME\n"));); - - stcMDNS_RRAttributes attributes(DNS_RRTYPE_PTR, DNS_RRCLASS_IN); // No cache flush! only INternet - bool bResult = ((_writeMDNSServiceDomain(p_rService, false, false, p_rSendParameter)) && // _http._tcp.local - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_SERVICE_TTL), p_rSendParameter)) && // TTL - (_writeMDNSServiceDomain(p_rService, true, true, p_rSendParameter))); // RDLength & RData (service domain, eg. MyESP._http._tcp.local) - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_NAME: FAILED!\n")); - }); - return bResult; -} - - -/* - MDNSResponder::_writeMDNSAnswer_TXT - - Write a MDNS TXT answer to the UDP output buffer. - See: '_writeMDNSAnswer_A' - - The TXT items in the RDATA block are 'length byte encoded': [len]vardata - - eg. myESP._http._tcp.local TXT 0x8001 120 4 c#=1 - http://www.zytrax.com/books/dns/ch8/txt.html -*/ -bool MDNSResponder::_writeMDNSAnswer_TXT(MDNSResponder::stcMDNSService& p_rService, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_TXT\n"));); - - bool bResult = false; - - stcMDNS_RRAttributes attributes(DNS_RRTYPE_TXT, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - - if ((_collectServiceTxts(p_rService)) && - (_writeMDNSServiceDomain(p_rService, true, false, p_rSendParameter)) && // MyESP._http._tcp.local - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_SERVICE_TTL), p_rSendParameter)) && // TTL - (_write16(p_rService.m_Txts.length(), p_rSendParameter))) // RDLength - { - - bResult = true; - // RData Txts - for (stcMDNSServiceTxt* pTxt = p_rService.m_Txts.m_pTxts; ((bResult) && (pTxt)); pTxt = pTxt->m_pNext) - { - unsigned char ucLengthByte = pTxt->length(); - bResult = ((_udpAppendBuffer((unsigned char*)&ucLengthByte, sizeof(ucLengthByte))) && // Length - (p_rSendParameter.shiftOffset(sizeof(ucLengthByte))) && - ((size_t)os_strlen(pTxt->m_pcKey) == m_pUDPContext->append(pTxt->m_pcKey, os_strlen(pTxt->m_pcKey))) && // Key - (p_rSendParameter.shiftOffset((size_t)os_strlen(pTxt->m_pcKey))) && - (1 == m_pUDPContext->append("=", 1)) && // = - (p_rSendParameter.shiftOffset(1)) && - ((!pTxt->m_pcValue) || - (((size_t)os_strlen(pTxt->m_pcValue) == m_pUDPContext->append(pTxt->m_pcValue, os_strlen(pTxt->m_pcValue))) && // Value - (p_rSendParameter.shiftOffset((size_t)os_strlen(pTxt->m_pcValue)))))); - - DEBUG_EX_ERR(if (!bResult) - { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_TXT: FAILED to write %sTxt %s=%s!\n"), (pTxt->m_bTemp ? "temp. " : ""), (pTxt->m_pcKey ? : "?"), (pTxt->m_pcValue ? : "?")); - }); - } - } - _releaseTempServiceTxts(p_rService); - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_TXT: FAILED!\n")); - }); - return bResult; -} - -#ifdef MDNS_IP6_SUPPORT -/* - MDNSResponder::_writeMDNSAnswer_AAAA - - Write a MDNS AAAA answer to the UDP output buffer. - See: '_writeMDNSAnswer_A' - - eg. esp8266.local AAAA 0x8001 120 16 xxxx::xx - http://www.zytrax.com/books/dns/ch8/aaaa.html -*/ -bool MDNSResponder::_writeMDNSAnswer_AAAA(IPAddress p_IPAddress, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_AAAA\n"));); - - stcMDNS_RRAttributes attributes(DNS_RRTYPE_AAAA, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - bool bResult = ((_writeMDNSHostDomain(m_pcHostname, false, p_rSendParameter)) && // esp8266.local - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter)) && // TTL - (_write16(MDNS_IP6_SIZE, p_rSendParameter)) && // RDLength - (false /*TODO: IP6 version of: _udpAppendBuffer((uint32_t)p_IPAddress, MDNS_IP4_SIZE)*/)); // RData - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_AAAA: FAILED!\n")); - }); - return bResult; -} - -/* - MDNSResponder::_writeMDNSAnswer_PTR_IP6 - - Write a MDNS reverse IP6 PTR answer to the UDP output buffer. - See: '_writeMDNSAnswer_A' - - eg. xxxx::xx.in6.arpa PTR 0x8001 120 15 esp8266.local - Used while answering reverse IP6 questions -*/ -bool MDNSResponder::_writeMDNSAnswer_PTR_IP6(IPAddress p_IPAddress, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_IP6\n"));); - - stcMDNS_RRDomain reverseIP6Domain; - stcMDNS_RRAttributes attributes(DNS_RRTYPE_PTR, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - bool bResult = ((_buildDomainForReverseIP6(p_IPAddress, reverseIP6Domain)) && // xxxx::xx.ip6.arpa - (_writeMDNSRRDomain(reverseIP6Domain, p_rSendParameter)) && - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_HOST_TTL), p_rSendParameter)) && // TTL - (_writeMDNSHostDomain(m_pcHostname, true, p_rSendParameter))); // RDLength & RData (host domain, eg. esp8266.local) - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_PTR_IP6: FAILED!\n")); - }); - return bResult; -} -#endif - -/* - MDNSResponder::_writeMDNSAnswer_SRV - - eg. MyESP._http.tcp.local SRV 0x8001 120 0 0 60068 esp8266.local - http://www.zytrax.com/books/dns/ch8/srv.html ???? Include instance name ???? -*/ -bool MDNSResponder::_writeMDNSAnswer_SRV(MDNSResponder::stcMDNSService& p_rService, - MDNSResponder::stcMDNSSendParameter& p_rSendParameter) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_SRV\n"));); - - uint16_t u16CachedDomainOffset = (p_rSendParameter.m_bLegacyQuery - ? 0 - : p_rSendParameter.findCachedDomainOffset((const void*)m_pcHostname, false)); - - stcMDNS_RRAttributes attributes(DNS_RRTYPE_SRV, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - stcMDNS_RRDomain hostDomain; - bool bResult = ((_writeMDNSServiceDomain(p_rService, true, false, p_rSendParameter)) && // MyESP._http._tcp.local - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce ? 0 : MDNS_SERVICE_TTL), p_rSendParameter)) && // TTL - (!u16CachedDomainOffset - // No cache for domain name (or no compression allowed) - ? ((_buildDomainForHost(m_pcHostname, hostDomain)) && - (_write16((sizeof(uint16_t /*Prio*/) + // RDLength - sizeof(uint16_t /*Weight*/) + - sizeof(uint16_t /*Port*/) + - hostDomain.m_u16NameLength), p_rSendParameter)) && // Domain length - (_write16(MDNS_SRV_PRIORITY, p_rSendParameter)) && // Priority - (_write16(MDNS_SRV_WEIGHT, p_rSendParameter)) && // Weight - (_write16(p_rService.m_u16Port, p_rSendParameter)) && // Port - (p_rSendParameter.addDomainCacheItem((const void*)m_pcHostname, false, p_rSendParameter.m_u16Offset)) && - (_writeMDNSRRDomain(hostDomain, p_rSendParameter))) // Host, eg. esp8266.local - // Cache available for domain - : ((MDNS_DOMAIN_COMPRESS_MARK > ((u16CachedDomainOffset >> 8) & ~MDNS_DOMAIN_COMPRESS_MARK)) && // Valid offset - (_write16((sizeof(uint16_t /*Prio*/) + // RDLength - sizeof(uint16_t /*Weight*/) + - sizeof(uint16_t /*Port*/) + - 2), p_rSendParameter)) && // Length of 'C0xx' - (_write16(MDNS_SRV_PRIORITY, p_rSendParameter)) && // Priority - (_write16(MDNS_SRV_WEIGHT, p_rSendParameter)) && // Weight - (_write16(p_rService.m_u16Port, p_rSendParameter)) && // Port - (_write8(((u16CachedDomainOffset >> 8) | MDNS_DOMAIN_COMPRESS_MARK), p_rSendParameter)) && // Compression mark (and offset) - (_write8((uint8_t)u16CachedDomainOffset, p_rSendParameter))))); // Offset - - DEBUG_EX_ERR(if (!bResult) -{ - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _writeMDNSAnswer_SRV: FAILED!\n")); - }); - return bResult; -} - -} // namespace MDNSImplementation - -} // namespace esp8266 - - - - - - diff --git a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_lwIPdefs.h b/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_lwIPdefs.h deleted file mode 100644 index a3bcc4b370..0000000000 --- a/libraries/ESP8266mDNS/OLDmDNS/LEAmDNS_lwIPdefs.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - LEAmDNS_Priv.h - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#ifndef MDNS_LWIPDEFS_H -#define MDNS_LWIPDEFS_H - -#include <lwip/init.h> -#if LWIP_VERSION_MAJOR == 1 - -#include <lwip/mdns.h> // DNS_RRTYPE_xxx - -// cherry pick from lwip1 dns.c/mdns.c source files: -#define DNS_MQUERY_PORT 5353 -#define DNS_MQUERY_IPV4_GROUP_INIT IPAddress(224,0,0,251) /* resolver1.opendns.com */ -#define DNS_RRCLASS_ANY 255 /* any class */ - -#else // lwIP > 1 - -#include <lwip/prot/dns.h> // DNS_RRTYPE_xxx, DNS_MQUERY_PORT - -#endif - -#endif // MDNS_LWIPDEFS_H From c6db2e52e8592ce5d9fc666ab9033848a04f11f9 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sat, 23 May 2020 13:24:27 +0200 Subject: [PATCH 011/152] wip --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 4 +-- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 17 +++------- .../ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 33 ++----------------- 3 files changed, 8 insertions(+), 46 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index c8c05082c5..ce6d2cef85 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -246,15 +246,13 @@ clsLEAMDNSHost::~clsLEAMDNSHost(void) */ bool clsLEAMDNSHost::begin(const char* p_pcHostName, - netif* p_pNetIf, clsLEAMDNSHost::fnProbeResultCallback p_fnCallback /*= 0*/) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s, netif: %u)\n"), _DH(), (p_pcHostName ? : "_"), (p_pNetIf ? netif_get_index(p_pNetIf) : 0));); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s)\n"), _DH(), (p_pcHostName ? : "_"));); bool bResult = false; if (!((bResult = ((setHostName(p_pcHostName)) && - ((m_pNetIf = p_pNetIf)) && (_joinMulticastGroups()) && (p_fnCallback ? setProbeResultCallback(p_fnCallback) : true) && ((m_pUDPContext = _allocBackbone())) && diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index bdcc05e21e..c643c9296c 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -267,7 +267,7 @@ class clsLEAMDNSHost /** list */ - using list = std::list<clsLEAMDNSHost*>; + //using list = std::list<clsLEAMDNSHost*>; // File: ..._Backbone /** @@ -291,15 +291,16 @@ class clsLEAMDNSHost UdpContext* m_pUDPContext; bool m_bDelayUDPProcessing; uint32_t m_u32DelayedDatagrams; - list m_HostList; + //list m_HostList; + clsLEAMDNSHost m_uniqueHost; bool _allocUDPContext(void); bool _releaseUDPContext(void); bool _processUDPInput(void); - const clsLEAMDNSHost* _findHost(netif* p_pNetIf) const; - clsLEAMDNSHost* _findHost(netif* p_pNetIf); + const clsLEAMDNSHost* _findHost() const { return &m_uniqueHost; } + clsLEAMDNSHost* _findHost() { return &m_uniqueHost; } const char* _DH(void) const; }; @@ -1256,12 +1257,6 @@ class clsLEAMDNSHost // Later call 'update()' in every 'loop' to run the process loop // (probing, announcing, responding, ...) // If no callback is given, the (maybe) already installed callback stays set - bool begin(const char* p_pcHostName, - netif* p_pNetIf, - fnProbeResultCallback p_fnCallback = 0); - bool begin(const char* p_pcHostName, - WiFiMode_t p_WiFiMode, - fnProbeResultCallback p_fnCallback = 0); bool begin(const char* p_pcHostName, fnProbeResultCallback p_fnCallback = 0); @@ -1640,8 +1635,6 @@ class clsLEAMDNSHost protected: - netif* m_pNetIf; - typeNetIfState m_NetIfState; UdpContext* m_pUDPContext; char* m_pcHostName; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index d3d4849a54..5bdf85d1d3 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -218,10 +218,9 @@ bool clsLEAMDNSHost::clsBackbone::_processUDPInput(void) while ((m_pUDPContext) && (m_pUDPContext->next())) { - netif* pNetIf = m_pUDPContext->getInputNetif();//ip_current_input_netif(); // Probably changed inbetween!!!! + netif* pNetIf = m_pUDPContext->getInputNetif();//ip_current_input_netif(); // Probably changed in between!!!! clsLEAMDNSHost* pHost = 0; - if ((pNetIf) && - ((pHost = _findHost(pNetIf)))) + if ((pHost = _findHost(pNetIf))) { DEBUG_EX_INFO( if (u32LoopCounter++) @@ -255,34 +254,6 @@ bool clsLEAMDNSHost::clsBackbone::_processUDPInput(void) return bResult; } -/* - clsLEAmDNS2_Host::clsBackbone::_findHost -*/ -const clsLEAMDNSHost* clsLEAMDNSHost::clsBackbone::_findHost(netif* p_pNetIf) const -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _findHost\n"), _DH());); - const clsLEAMDNSHost* pResult = 0; - for (const clsLEAMDNSHost* pHost : m_HostList) - { - if ((p_pNetIf) && - (pHost->m_pNetIf == p_pNetIf)) - { - pResult = pHost; - break; - } - } - return pResult; -} - -/* - MDNSResponder::_findHost -*/ -clsLEAMDNSHost* clsLEAMDNSHost::clsBackbone::_findHost(netif* p_pNetIf) -{ - return (clsLEAMDNSHost*)(((const clsLEAMDNSHost::clsBackbone*)this)->_findHost(p_pNetIf)); -} - - /* MISC */ From b5fefcfc2815e29c5526fe9df0d1b307dd47fb81 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sat, 23 May 2020 18:26:52 +0200 Subject: [PATCH 012/152] fix for lwIP-v1 --- cores/esp8266/IPAddress.h | 1 + libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h | 2 ++ 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cores/esp8266/IPAddress.h b/cores/esp8266/IPAddress.h index cdd4b2499f..6fcbee95fe 100644 --- a/cores/esp8266/IPAddress.h +++ b/cores/esp8266/IPAddress.h @@ -42,6 +42,7 @@ #define CONST /* nothing: lwIP-v1 does not use const */ #define ip4_addr_netcmp ip_addr_netcmp #define netif_dhcp_data(netif) ((netif)->dhcp) +#define netif_get_index(netif) ((u8_t)((netif)->num + 1)) #else // lwIP-v2+ #define CONST const #if !LWIP_IPV6 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index c8c05082c5..1553c3df4c 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -941,7 +941,7 @@ bool clsLEAMDNSHost::_leaveMulticastGroups(void) #ifdef MDNS_IPV4_SUPPORT ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; #if LWIP_VERSION_MAJOR == 1 - if (ERR_OK != igmp_leavegroup(ip_2_ip4(&m_rNetIf.ip_addr), ip_2_ip4(&multicast_addr_V4))) + if (ERR_OK != igmp_leavegroup(ip_2_ip4(&m_pNetIf->ip_addr), ip_2_ip4(&multicast_addr_V4))) #else if (ERR_OK != igmp_leavegroup_netif(m_pNetIf, ip_2_ip4(&multicast_addr_V4))) #endif diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 36b5ece554..0165d2962d 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -624,7 +624,7 @@ IPAddress clsLEAMDNSHost::_getResponderIPAddress(enuIPProtocolType p_IPProtocolT if (enuIPProtocolType::V4 == p_IPProtocolType) { #if LWIP_VERSION_MAJOR == 1 - ipResponder = ip_2_ip4(m_rNetIf.ip_addr); + ipResponder = ip_2_ip4(m_pNetIf->ip_addr); #else ipResponder = netif_ip_addr4(m_pNetIf); #endif diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h b/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h index b28ea2a26e..54d7f36f48 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h @@ -35,6 +35,8 @@ #define DNS_MQUERY_IPV4_GROUP_INIT IPAddress(224,0,0,251) /* resolver1.opendns.com */ #define DNS_RRCLASS_ANY 255 /* any class */ +struct netif* netif_get_by_index(u8_t idx); + #else // lwIP > 1 #include <lwip/prot/dns.h> // DNS_RRTYPE_xxx, DNS_MQUERY_PORT From 1272926c867415e787ad1438ea87ca7cd533712e Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sat, 23 May 2020 18:37:04 +0200 Subject: [PATCH 013/152] wip --- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 29 +++++-------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 151555d15c..ee2f4f63b0 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -50,20 +50,6 @@ clsLEAMDNSHost_Legacy::~clsLEAMDNSHost_Legacy(void) */ -/* - clsLEAMDNSHost_Legacy::begin - -*/ -bool clsLEAMDNSHost_Legacy::begin(const char* p_pcHostname) -{ - bool bResult = (((!(WIFI_STA & (WiFiMode_t)wifi_get_opmode())) - || (addHostForNetIf(p_pcHostname, netif_get_by_index(WIFI_STA)))) - && ((!(WIFI_AP & (WiFiMode_t)wifi_get_opmode())) - || (addHostForNetIf(p_pcHostname, netif_get_by_index(WIFI_AP))))); - return ((bResult) - && (0 != m_HostInformations.size())); -} - /* clsLEAMDNSHost_Legacy::begin (String) @@ -130,19 +116,18 @@ bool clsLEAMDNSHost_Legacy::end(void) NEW! */ -bool clsLEAMDNSHost_Legacy::addHostForNetIf(const char* p_pcHostname, - netif* p_pNetIf) +bool clsLEAMDNSHost_Legacy::addHostForNetIf(const char* p_pcHostname) { - clsLEAMDNSHost* pHost = 0; + bool bResult = true; - if (((pHost = new esp8266::experimental::clsLEAMDNSHost)) - && (!((pHost->begin(p_pcHostname, p_pNetIf /*, default callback*/)) + clsLEAMDNSHost* pHost = &esp8266::experimental::clsLEAMDNSHost::clsBackbone::sm_pBackbone.m_uniqueHost; + + if ((!((pHost->begin(p_pcHostname /*, default callback*/)) && (m_HostInformations.push_back(stcHostInformation(pHost)), true)))) { - delete pHost; - pHost = 0; + bResult = false; } - return (0 != pHost); + return bResult; } /* From 5ffbe293bb64b72dc2e9c1132b9a74e1a30077c6 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 24 May 2020 11:39:38 +0200 Subject: [PATCH 014/152] wip --- cores/esp8266/IPAddress.h | 4 + libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 221 +++--------------- .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 19 +- .../ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp | 17 +- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h | 3 +- 5 files changed, 46 insertions(+), 218 deletions(-) diff --git a/cores/esp8266/IPAddress.h b/cores/esp8266/IPAddress.h index 6fcbee95fe..1260db39ee 100644 --- a/cores/esp8266/IPAddress.h +++ b/cores/esp8266/IPAddress.h @@ -50,6 +50,10 @@ struct ip_addr: ipv4_addr { }; #endif // !LWIP_IPV6 #endif // lwIP-v2+ +// to display a netif id with printf: +#define NETIFID_STR "%c%c%d" +#define NETIFID_VAL(netif) (netif)->name[0], (netif)->name[1], netif_get_index(netif) + // A class to make it easier to handle and pass around IP addresses // IPv6 update: // IPAddress is now a decorator class for lwIP's ip_addr_t diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 81901dfed5..fb8aaf0c56 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -171,15 +171,14 @@ const char* clsLEAMDNSHost::indexDomainName(const char* p_pcDomainName, */ // static -bool clsLEAMDNSHost::setNetIfHostName(netif* p_pNetIf, - const char* p_pcHostName) +bool clsLEAMDNSHost::setNetIfHostName(const char* p_pcHostName) { - if ((p_pNetIf) && - (p_pcHostName)) - { - netif_set_hostname(p_pNetIf, (char*)p_pcHostName); // LWIP 1.x forces 'char*' instead of 'const char*' - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[mDNS] setNetIfHostName host name: %s!\n"), p_pcHostName);); - } + if (p_pcHostName) + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) + { + netif_set_hostname(pNetIf, p_pcHostName); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[mDNS] setNetIfHostName host name: %s on " NETIFID_STR "!\n"), p_pcHostName, NETIFID_VAL(pNetIf));); + } return true; } @@ -214,9 +213,7 @@ const char* clsLEAMDNSHost::clsConsts::pcReverseTopDomain = "arpa"; */ clsLEAMDNSHost::clsLEAMDNSHost(void) - : m_pNetIf(0), - m_NetIfState(static_cast<typeNetIfState>(enuNetIfState::None)), - m_pUDPContext(0), + : m_pUDPContext(0), m_pcHostName(0), m_pcDefaultInstanceName(0), m_ProbeInformation() @@ -239,9 +236,9 @@ clsLEAMDNSHost::~clsLEAMDNSHost(void) */ /* - clsLEAmDNS2_Host::begin (hostname, netif, probe_callback) + clsLEAmDNS2_Host::begin (hostname, probe_callback) - Creates a new mDNS host (adding the netif to the multicast groups), + setup global mDNS (adding all netif to the multicast groups), sets up the instance data (hostname, ...) and starts the probing process */ @@ -264,46 +261,6 @@ bool clsLEAMDNSHost::begin(const char* p_pcHostName, return bResult; } -/* - clsLEAmDNS2_Host::begin (hostname, probe_callback) - -*/ -bool clsLEAMDNSHost::begin(const char* p_pcHostName, - clsLEAMDNSHost::fnProbeResultCallback p_fnCallback /*= 0*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s)\n"), _DH(), (p_pcHostName ? : "_"));); - - return begin(p_pcHostName, (WiFiMode_t)wifi_get_opmode(), p_fnCallback); -} - -/* - clsLEAmDNS2_Host::begin (hostname, WiFiMode, probe_callback) - -*/ -bool clsLEAMDNSHost::begin(const char* p_pcHostName, - WiFiMode_t p_WiFiMode, - clsLEAMDNSHost::fnProbeResultCallback p_fnCallback /*= 0*/) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin(%s, opmode: %u)\n"), _DH(), (p_pcHostName ? : "_"), (uint32_t)p_WiFiMode);); - - bool bResult = false; - - if (p_WiFiMode == WIFI_STA) - { - bResult = begin(p_pcHostName, netif_get_by_index(WIFI_STA), p_fnCallback); - } - else if (p_WiFiMode == WIFI_AP) - { - bResult = begin(p_pcHostName, netif_get_by_index(WIFI_AP), p_fnCallback); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s begin: FAILED for WiFi mode '%u'! Only 'WIFI_STA' or 'WIFI_AP' is allowed (HostName: %s)!\n"), _DH(), (bResult ? "Succeeded" : "FAILED"), p_WiFiMode, (p_pcHostName ? : "-"));); - } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin: %s for WiFi mode '%u' (HostName: %s)!\n"), _DH(), (bResult ? "Succeeded" : "FAILED"), p_WiFiMode, (p_pcHostName ? : "-"));); - return bResult; -} - /* clsLEAmDNS2_Host::close @@ -747,8 +704,7 @@ bool clsLEAMDNSHost::update(void) //if (clsBackbone::sm_pBackbone->setDelayUDPProcessing(true)) //{ - bResult = ((_checkNetIfState()) && // Any changes in the netif state? - (_updateProbeStatus()) && // Probing and announcing + bResult = ((_updateProbeStatus()) && // Probing and announcing (_checkQueryCache())); // clsBackbone::sm_pBackbone->setDelayUDPProcessing(false); @@ -883,10 +839,8 @@ bool clsLEAMDNSHost::_joinMulticastGroups(void) bool bResult = false; // Join multicast group(s) - if (m_pNetIf) + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) { - bResult = true; - #ifdef MDNS_IPV4_SUPPORT ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; if (!(m_pNetIf->flags & NETIF_FLAG_IGMP)) @@ -900,20 +854,29 @@ bool clsLEAMDNSHost::_joinMulticastGroups(void) } } - bResult = ((bResult) && + if ( #if LWIP_VERSION_MAJOR == 1 - (ERR_OK == igmp_joingroup(ip_2_ip4(&m_pNetIf->ip_addr), ip_2_ip4(&multicast_addr_V4)))); + (ERR_OK == igmp_joingroup(&pNetIf->ip_addr, &multicast_addr_V4)) #else - (ERR_OK == igmp_joingroup_netif(m_pNetIf, ip_2_ip4(&multicast_addr_V4)))); + (ERR_OK == igmp_joingroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4))) #endif - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: igmp_joingroup_netif(%s) FAILED!\n"), _DH(), IPAddress(multicast_addr_V4).toString().c_str());); + ) + { + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: igmp_joingroup_netif(" NETIFID_STR ": %s) FAILED!\n"), + _DH(), NETIFID_VAL(pNetIf), IPAddress(multicast_addr_V4).toString().c_str());); + } #endif #ifdef MDNS_IPV6_SUPPORT ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; bResult = ((bResult) && - (ERR_OK == mld6_joingroup_netif(m_pNetIf, ip_2_ip6(&multicast_addr_V6)))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: mld6_joingroup_netif FAILED!\n"), _DH());); + (ERR_OK == mld6_joingroup_netif(pNetIf, ip_2_ip6(&multicast_addr_V6)))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: mld6_joingroup_netif (" NETIFID_STR ") FAILED!\n"), + _DH(), NETIFID_VAL(pNetIf));); #endif } return bResult; @@ -922,15 +885,14 @@ bool clsLEAMDNSHost::_joinMulticastGroups(void) /* clsLEAmDNS2_Host::_leaveMulticastGroups */ -bool clsLEAMDNSHost::_leaveMulticastGroups(void) +bool clsLEAMDNSHost::_leaveMulticastGroups() { bool bResult = false; - if (m_pNetIf) + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) { bResult = true; /* _resetProbeStatus(false); // Stop probing - _releaseQueries(); _releaseServices(); _releaseHostName();*/ @@ -939,9 +901,9 @@ bool clsLEAMDNSHost::_leaveMulticastGroups(void) #ifdef MDNS_IPV4_SUPPORT ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; #if LWIP_VERSION_MAJOR == 1 - if (ERR_OK != igmp_leavegroup(ip_2_ip4(&m_pNetIf->ip_addr), ip_2_ip4(&multicast_addr_V4))) + if (ERR_OK != igmp_leavegroup(ip_2_ip4(pNetIf->ip_addr), ip_2_ip4(&multicast_addr_V4))) #else - if (ERR_OK != igmp_leavegroup_netif(m_pNetIf, ip_2_ip4(&multicast_addr_V4))) + if (ERR_OK != igmp_leavegroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4))) #endif { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); @@ -949,7 +911,7 @@ bool clsLEAMDNSHost::_leaveMulticastGroups(void) #endif #ifdef MDNS_IPV6_SUPPORT ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; - if (ERR_OK != mld6_leavegroup_netif(m_pNetIf, ip_2_ip6(&multicast_addr_V6)/*&(multicast_addr_V6.u_addr.ip6)*/)) + if (ERR_OK != mld6_leavegroup_netif(pNetIf, ip_2_ip6(&multicast_addr_V6)/*&(multicast_addr_V6.u_addr.ip6)*/)) { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); } @@ -959,123 +921,6 @@ bool clsLEAMDNSHost::_leaveMulticastGroups(void) } -/* - NETIF -*/ - -/* - clsLEAmDNS2_Host::_getNetIfState - - Returns the current netif state. - -*/ -clsLEAMDNSHost::typeNetIfState clsLEAMDNSHost::_getNetIfState(void) const -{ - typeNetIfState curNetIfState = static_cast<typeNetIfState>(enuNetIfState::None); - - if ((m_pNetIf) && - (netif_is_up(m_pNetIf))) - { - curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::IsUp); - - // Check if netif link is up - if ((netif_is_link_up(m_pNetIf)) && - ((m_pNetIf != netif_get_by_index(WIFI_STA)) || - (STATION_GOT_IP == wifi_station_get_connect_status()))) - { - curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::LinkIsUp); - } - -#ifdef MDNS_IPV4_SUPPORT - // Check for IPv4 address - if (_getResponderIPAddress(enuIPProtocolType::V4).isSet()) - { - curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::IPv4); - } -#endif -#ifdef MDNS_IPV6_SUPPORT - // Check for IPv6 address - if (_getResponderIPAddress(enuIPProtocolType::V6).isSet()) - { - curNetIfState |= static_cast<typeNetIfState>(enuNetIfState::IPv6); - } -#endif - } - return curNetIfState; -} - -/* - clsLEAmDNS2_Host::_checkNetIfState - - Checks the netif state. - If eg. a new address appears, the announcing is restarted. - -*/ -bool clsLEAMDNSHost::_checkNetIfState(void) -{ - typeNetIfState curNetIfState; - if (m_NetIfState != ((curNetIfState = _getNetIfState()))) - { - // Some state change happened - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: DID CHANGE NETIF STATE\n\n"), _DH());); - DEBUG_EX_INFO( - if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IsUp)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IsUp))) DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Netif is up: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IsUp)) ? "YES" : "NO")); - if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp))) DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Netif link is up: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp)) ? "YES" : "NO")); -#ifdef MDNS_IPV4_SUPPORT - if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4))) - { - DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv4 address is set: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4)) ? "YES" : "NO")); - if (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv4)) - { - DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv4 address: %s\n"), _DH(), _getResponderIPAddress(enuIPProtocolType::V4).toString().c_str()); - } - } -#endif -#ifdef MDNS_IPV6_SUPPORT - if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6))) - { - DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv6 address is set: %s\n"), _DH(), ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6)) ? "YES" : "NO")); - if (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPv6)) - { - DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IPv6 address: %s\n"), _DH(), _getResponderIPAddress(enuIPProtocolType::V6).toString().c_str()); - } - } -#endif - ); - if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask))) - { - // Link came up or down - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Link state changed -> restarting\n"), _DH());); - restart(); - } - else if (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkIsUp)) - { - // Link is up (unchanged) - if ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask)) != (m_NetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask))) - { - // IP state changed - // TODO: If just a new IP address was added, a simple re-announcement should be enough - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: IP state changed -> restarting\n"), _DH());); - restart(); - } - } - /* if (enuProbingStatus::Done == m_HostProbeInformation.m_ProbingStatus) { - // Probing is done, prepare to (re)announce host - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Preparing to (re)announce host.\n"));); - //m_HostProbeInformation.m_ProbingStatus = enuProbingStatus::Done; - m_HostProbeInformation.m_u8SentCount = 0; - m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); - }*/ - m_NetIfState = curNetIfState; - } - - bool bResult = ((curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask)) && // Continue if Link is UP - (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask))); // AND has any IP - DEBUG_EX_INFO(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _checkNetIfState: Link is DOWN(%s) or NO IP address(%s)!\n"), _DH(), (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::LinkMask) ? "NO" : "YES"), (curNetIfState & static_cast<typeNetIfState>(enuNetIfState::IPMask) ? "NO" : "YES"));); - return bResult; -} - - /* PROCESSING */ @@ -1089,8 +934,6 @@ bool clsLEAMDNSHost::_processUDPInput(void) bool bResult = _parseMessage(); - /* bResult = ((_checkNetIfState()) && // Any changes in the netif state? - (_parseMessage()));*/ DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s processUDPInput: FAILED!\n"), _DH());); return bResult; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index a061d77da8..bab5eba3cf 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -206,15 +206,12 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader // Local host check // We're a match for this legacy query, BUT // make sure, that the query comes from a local host -#ifdef MDNS_IPV4_SUPPORT - ip_info IPInfo_Local; -#endif - if ((m_pNetIf) && - (m_pUDPContext) && + if ((m_pUDPContext) && #ifdef MDNS_IPV4_SUPPORT (m_pUDPContext->getRemoteAddress().isV4()) && - ((wifi_get_ip_info(netif_get_index(m_pNetIf), &IPInfo_Local))) && - (ip4_addr_netcmp(ip_2_ip4((const ip_addr_t*)m_pUDPContext->getRemoteAddress()), &IPInfo_Local.ip, &IPInfo_Local.netmask)) + (ip4_addr_netcmp(ip_2_ip4(m_pUDPContext->getRemoteAddress()), + ip_2_ip4(m_pUDPContext->getInputNetif()->ip_addr), + ip_2_ip4(m_pUDPContext->getInputNetif()->netmask)) #else (true) #endif @@ -227,14 +224,6 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader #endif ) { - /* ip_info IPInfo_Local; - ip_info IPInfo_Remote; - if (((IPInfo_Remote.ip.addr = m_pUDPContext->getRemoteAddress())) && - (((wifi_get_ip_info(SOFTAP_IF, &IPInfo_Local)) && - (ip4_addr_netcmp(&IPInfo_Remote.ip, &IPInfo_Local.ip, &IPInfo_Local.netmask))) || // Remote IP in SOFTAP's subnet OR - ((wifi_get_ip_info(STATION_IF, &IPInfo_Local)) && - (ip4_addr_netcmp(&IPInfo_Remote.ip, &IPInfo_Local.ip, &IPInfo_Local.netmask))))) // Remote IP in STATION's subnet - {*/ Serial.println("\n\n\nUNICAST QUERY\n\n"); DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Legacy DNS query from local host %s!\n"), _DH(), m_pUDPContext->getRemoteAddress().toString().c_str());); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp index bc7316be88..94855d2ab5 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp @@ -40,23 +40,16 @@ namespace experimental clsLEAmDNS2_Host::_DH */ -const char* clsLEAMDNSHost::_DH(const clsLEAMDNSHost::clsService* p_pService /*= 0*/) const +xxxxx const char* clsLEAMDNSHost::_DH(const clsLEAMDNSHost::clsService* p_pService /*= 0*/) const { static char acBuffer[16 + 64]; *acBuffer = 0; - if (m_pNetIf) - { - sprintf_P(acBuffer, PSTR("[mDNS %c%c%u]"), m_pNetIf->name[0], m_pNetIf->name[1], m_pNetIf->num); - if (p_pService) - { - strcat_P(acBuffer, PSTR(">")); - strcat(acBuffer, _service2String(p_pService)); - } - } - else + sprintf_P(acBuffer, PSTR("[mDNS]"); + if (p_pService) { - strcpy_P(acBuffer, PSTR("[mDNS]")); + strcat_P(acBuffer, PSTR(">")); + strcat(acBuffer, _service2String(p_pService)); } return acBuffer; } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h index 9ab1f14d0c..c574cfee08 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h @@ -154,8 +154,7 @@ class clsLEAMDNSHost_Legacy // NEW! The ESP-default network interfaces are 'auto-added' via 'begin' when active // Additional netifs may be added, but if done so after calling 'update' for the // first time, 'notifyAPChange' should be called to restart the probing/announcing process - bool addHostForNetIf(const char* p_pcHostname, - netif* p_pNetIf); + bool addHostForNetIf(const char* p_pcHostname); // Change hostname (probing is restarted) // Caution! The final hostname (after probing) may be different for every host From ad6b4260013639a2cabdf27bda75590464e3c91c Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 24 May 2020 11:50:48 +0200 Subject: [PATCH 015/152] fix for lwIP-1.4 --- libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 1 + libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index d3d4849a54..4eb45918f9 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -311,6 +311,7 @@ const char* clsLEAMDNSHost::clsBackbone::_DH(void) const Extracted (and slightly changed) from: https://github.com/yarrick/lwip/blob/master/src/core/netif.c */ +extern "C" struct netif* netif_get_by_index(u8_t idx) { struct netif *netif; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h b/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h index 54d7f36f48..0aa1712a81 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h @@ -35,6 +35,9 @@ #define DNS_MQUERY_IPV4_GROUP_INIT IPAddress(224,0,0,251) /* resolver1.opendns.com */ #define DNS_RRCLASS_ANY 255 /* any class */ +#ifdef __cplusplus +extern "C" +#endif struct netif* netif_get_by_index(u8_t idx); #else // lwIP > 1 From bae5f6655769529c38e381d4f0b298112050139c Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 24 May 2020 15:05:40 +0200 Subject: [PATCH 016/152] wip --- cores/esp8266/IPAddress.h | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 6 ++++ .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 11 +++--- .../ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 34 ++++++++++--------- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 18 +++++++--- 5 files changed, 44 insertions(+), 27 deletions(-) diff --git a/cores/esp8266/IPAddress.h b/cores/esp8266/IPAddress.h index 1260db39ee..327c61f997 100644 --- a/cores/esp8266/IPAddress.h +++ b/cores/esp8266/IPAddress.h @@ -52,7 +52,7 @@ struct ip_addr: ipv4_addr { }; // to display a netif id with printf: #define NETIFID_STR "%c%c%d" -#define NETIFID_VAL(netif) (netif)->name[0], (netif)->name[1], netif_get_index(netif) +#define NETIFID_VAL(netif) (netif)->name[0], (netif)->name[1], netif_get_index((netif)) // A class to make it easier to handle and pass around IP addresses // IPv6 update: diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index c643c9296c..d724a19ba7 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -140,18 +140,24 @@ #ifdef DEBUG_ESP_MDNS_RESPONDER #ifdef DEBUG_ESP_MDNS_INFO #define DEBUG_EX_INFO(A) A +#define DEBUG_EX_INFO_IF(C,A...) do if (C) { A; } while (0) #else #define DEBUG_EX_INFO(A) +#define DEBUG_EX_INFO_IF(C,A...) #endif #ifdef DEBUG_ESP_MDNS_INFO2 #define DEBUG_EX_INFO2(A) A +#define DEBUG_EX_INFO2_IF(C,A...) do if (C) { A; } while (0) #else #define DEBUG_EX_INFO2(A) +#define DEBUG_EX_INFO2_IF(C,A...) #endif #ifdef DEBUG_ESP_MDNS_ERR #define DEBUG_EX_ERR(A) A +#define DEBUG_EX_ERR_IF(C,A...) do if (C) { A; } while (0) #else #define DEBUG_EX_ERR(A) +#define DEBUG_EX_ERR_IF(C,A...) #endif #ifdef DEBUG_ESP_MDNS_TX #define DEBUG_EX_TX(A) A diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 0165d2962d..6ad703d4cc 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -636,15 +636,16 @@ IPAddress clsLEAMDNSHost::_getResponderIPAddress(enuIPProtocolType p_IPProtocolT bool bCheckLinkLocal = true; for (int i = 0; ((!ipResponder.isSet()) && (i < 2)); ++i) // Two loops: First with link-local check, second without { + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) for (int idx = 0; idx < LWIP_IPV6_NUM_ADDRESSES; ++idx) { - //DEBUG_EX_INFO(if ip6_addr_isvalid(netif_ip6_addr_state(&m_rNetIf, idx)) DEBUG_OUTPUT.printf_P(PSTR("%s _getResponderIPAddress: Checking IPv6 address %s (LL: %s)\n"), _DH(), IPAddress(netif_ip_addr6(m_pNetIf, idx)).toString().c_str(), (bCheckLinkLocal ? "YES" : "NO"));); - if ((ip6_addr_isvalid(netif_ip6_addr_state(m_pNetIf, idx))) && + //DEBUG_EX_INFO(if ip6_addr_isvalid(netif_ip6_addr_state(&pNetIf, idx)) DEBUG_OUTPUT.printf_P(PSTR("%s _getResponderIPAddress: Checking IPv6 address %s (LL: %s)\n"), _DH(), IPAddress(netif_ip_addr6(pNetIf, idx)).toString().c_str(), (bCheckLinkLocal ? "YES" : "NO"));); + if ((ip6_addr_isvalid(netif_ip6_addr_state(pNetIf, idx))) && (((!bCheckLinkLocal) || - (ip6_addr_islinklocal(netif_ip6_addr(m_pNetIf, idx)))))) + (ip6_addr_islinklocal(netif_ip6_addr(pNetIf, idx)))))) { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _getResponderIPAddress: Selected IPv6 address %s (LL: %s)\n"), _DH(), IPAddress(netif_ip_addr6(m_pNetIf, idx)).toString().c_str(), (bCheckLinkLocal ? "YES" : "NO"));); - ipResponder = netif_ip_addr6(m_pNetIf, idx); + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _getResponderIPAddress: Selected IPv6 address %s (LL: %s)\n"), _DH(), IPAddress(netif_ip_addr6(pNetIf, idx)).toString().c_str(), (bCheckLinkLocal ? "YES" : "NO"));); + ipResponder = netif_ip_addr6(pNetIf, idx); break; } } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index af3cb5b97c..c5c465e8ad 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -218,30 +218,32 @@ bool clsLEAMDNSHost::clsBackbone::_processUDPInput(void) while ((m_pUDPContext) && (m_pUDPContext->next())) { - netif* pNetIf = m_pUDPContext->getInputNetif();//ip_current_input_netif(); // Probably changed in between!!!! + netif* pNetIf = m_pUDPContext->getInputNetif(); clsLEAMDNSHost* pHost = 0; if ((pHost = _findHost(pNetIf))) { - DEBUG_EX_INFO( - if (u32LoopCounter++) - { - DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Multi-Loop (%u)!\n"), _DH(), u32LoopCounter); - if ((remoteIPAddr.isSet()) && - (remoteIPAddr != m_pUDPContext->getRemoteAddress())) - { - DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Changed IP address %s->%s!\n"), _DH(), remoteIPAddr.toString().c_str(), m_pUDPContext->getRemoteAddress().toString().c_str()); - } - } - remoteIPAddr = m_pUDPContext->getRemoteAddress(); - ); + DEBUG_EX_INFO_IF(u32LoopCounter++, + DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Multi-Loop (%u)!\n"), _DH(), u32LoopCounter); + DEBUG_EX_INFO_IF((remoteIPAddr.isSet()) && (remoteIPAddr != m_pUDPContext->getRemoteAddress()), + DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Changed IP address %s->%s!\n"), + _DH(), + remoteIPAddr.toString().c_str(), + m_pUDPContext->getRemoteAddress().toString().c_str()))); + DEBUG_EX_INFO(remoteIPAddr = m_pUDPContext->getRemoteAddress()); + bResult = pHost->_processUDPInput(); - DEBUG_EX_INFO2(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: FAILED to process UDP input!\n"), _DH());); - DEBUG_EX_ERR(if ((-1) != m_pUDPContext->peek()) DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: !!!! CONTENT LEFT IN UDP BUFFER !!!!\n"), _DH());); + DEBUG_EX_INFO2_IF(!bResult, + DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: FAILED to process UDP input!\n"), _DH())); + DEBUG_EX_ERR_IF((-1) != m_pUDPContext->peek(), + DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: !!!! CONTENT LEFT IN UDP BUFFER !!!!\n"), + _DH())); } else { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Received UDP datagramm for unused netif at index: %u\n"), _DH(), (pNetIf ? netif_get_index(pNetIf) : (-1)));); + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Received UDP datagramm for unused netif at index: %u\n"), + _DH(), + (pNetIf ? netif_get_index(pNetIf) : (-1)))); } m_pUDPContext->flush(); } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index ee2f4f63b0..551a754cdf 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -119,14 +119,22 @@ bool clsLEAMDNSHost_Legacy::end(void) bool clsLEAMDNSHost_Legacy::addHostForNetIf(const char* p_pcHostname) { bool bResult = true; - - clsLEAMDNSHost* pHost = &esp8266::experimental::clsLEAMDNSHost::clsBackbone::sm_pBackbone.m_uniqueHost; - - if ((!((pHost->begin(p_pcHostname /*, default callback*/)) - && (m_HostInformations.push_back(stcHostInformation(pHost)), true)))) + + if (m_HostInformations.length() > 0) { + //XXXFIXME only one pHost instance, many things can be simplified bResult = false; } + else + { + clsLEAMDNSHost* pHost = &esp8266::experimental::clsLEAMDNSHost::clsBackbone::sm_pBackbone.m_uniqueHost; + + if ((!((pHost->begin(p_pcHostname /*, default callback*/)) + && (m_HostInformations.push_back(stcHostInformation(pHost)), true)))) + { + bResult = false; + } + } return bResult; } From 52787b2a44387c89177465471b41456a255ad407 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 24 May 2020 20:33:20 +0200 Subject: [PATCH 017/152] wip --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 355 ++++++++++-------- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 56 +-- .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 37 +- .../ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp | 4 +- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 170 ++++----- .../ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 15 +- 6 files changed, 353 insertions(+), 284 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index fb8aaf0c56..58d0a6f07b 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -175,10 +175,10 @@ bool clsLEAMDNSHost::setNetIfHostName(const char* p_pcHostName) { if (p_pcHostName) for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) - { - netif_set_hostname(pNetIf, p_pcHostName); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[mDNS] setNetIfHostName host name: %s on " NETIFID_STR "!\n"), p_pcHostName, NETIFID_VAL(pNetIf));); - } + { + netif_set_hostname(pNetIf, p_pcHostName); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[mDNS] setNetIfHostName host name: %s on " NETIFID_STR "!\n"), p_pcHostName, NETIFID_VAL(pNetIf));); + } return true; } @@ -506,37 +506,55 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryService { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService '_%s._%s.local'\n"), _DH(), p_pcService, p_pcProtocol);); - clsQuery* pQuery = 0; - if ((p_pcService) && (*p_pcService) && + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector ret; + + if (_removeLegacyQuery() && + (p_pcService) && (*p_pcService) && (p_pcProtocol) && (*p_pcProtocol) && - (p_u16Timeout) && - ((pQuery = _allocQuery(clsQuery::enuQueryType::Service))) && - (_buildDomainForService(p_pcService, p_pcProtocol, pQuery->m_Domain))) + (p_u16Timeout)) { - if ((_removeLegacyQuery()) && - ((pQuery->m_bStaticQuery = true)) && - (_sendQuery(*pQuery))) + std::list<clsQuery*> queries; + + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf)) + { + clsQuery* pQuery = 0; + if (((pQuery = _allocQuery(clsQuery::enuQueryType::Service))) && + (_buildDomainForService(p_pcService, p_pcProtocol, pQuery->m_Domain))) + { + if (((pQuery->m_bStaticQuery = true)) && (_sendQuery(pNetIf, *pQuery))) + { + queries.push_back(pQuery); + } + else + { + // FAILED to send query + _removeQuery(pQuery); + } + } + } + + if (queries.size()) { // Wait for answers to arrive DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); + //XXXFIXME could this delay be ASYNC? delay(p_u16Timeout); // All answers should have arrived by now -> stop adding new answers - pQuery->m_bAwaitingAnswers = false; + for (auto& q : queries) + { + q->m_bAwaitingAnswers = false; + ret.insert(ret.end(), std::make_move_iterator(q->answerAccessors().begin()), std::make_move_iterator(q->answerAccessors().end())); + } } else { - // FAILED to send query - _removeQuery(pQuery); + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: INVALID input data!\n"), _DH());); } + } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: INVALID input data!\n"), _DH());); - } - return ((pQuery) - ? pQuery->answerAccessors() - : clsQuery::clsAnswerAccessor::vector()); + return ret; } /* @@ -546,40 +564,58 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryService clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryHost(const char* p_pcHostName, const uint16_t p_u16Timeout) { + clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector ret; + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost '%s.local'\n"), _DH(), p_pcHostName);); - clsQuery* pQuery = 0; if ((p_pcHostName) && (*p_pcHostName) && (p_u16Timeout) && - ((pQuery = _allocQuery(clsQuery::enuQueryType::Host))) && - (_buildDomainForHost(p_pcHostName, pQuery->m_Domain))) + (_removeLegacyQuery())) { - if ((_removeLegacyQuery()) && - ((pQuery->m_bStaticQuery = true)) && - (_sendQuery(*pQuery))) + std::list<clsQuery*> queries; + + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf)) + { + clsQuery* pQuery = 0; + if (((pQuery = _allocQuery(clsQuery::enuQueryType::Host))) && + (_buildDomainForHost(p_pcHostName, pQuery->m_Domain))) + { + if (((pQuery->m_bStaticQuery = true)) && (_sendQuery(pNetIf, *pQuery))) + { + queries.push_back(pQuery); + } + else + { + // FAILED to send query + _removeQuery(pQuery); + } + } + } + + if (queries.size()) { // Wait for answers to arrive DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: Waiting %u ms for answers...\n"), _DH(), p_u16Timeout);); + //XXXFIXME could this delay be ASYNC? delay(p_u16Timeout); // All answers should have arrived by now -> stop adding new answers - pQuery->m_bAwaitingAnswers = false; + + for (auto& q : queries) + { + q->m_bAwaitingAnswers = false; + ret.insert(ret.end(), std::make_move_iterator(q->answerAccessors().begin()), std::make_move_iterator(q->answerAccessors().end())); + } } else { - // FAILED to send query - _removeQuery(pQuery); + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: INVALID input data!\n"), _DH());); } } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: INVALID input data!\n"), _DH());); - } - return ((pQuery) - ? pQuery->answerAccessors() - : clsQuery::clsAnswerAccessor::vector()); -} + return ret; +} /* clsLEAmDNS2_Host::removeQuery @@ -611,84 +647,100 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::getQuery(void) clsLEAmDNS2_Host::installServiceQuery (answer) */ -clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcService, +/*clsLEAMDNSHost::clsQuery* */ bool clsLEAMDNSHost::installServiceQuery(const char* p_pcService, const char* p_pcProtocol, clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) { + bool bResult = false; clsQuery* pQuery = 0; - if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) - { - pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; - } - return pQuery; + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf) && (pQuery = _installServiceQuery(pNetIf, p_pcService, p_pcProtocol))) + { + pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; + bResult = true; + } + return bResult; } /* clsLEAmDNS2_Host::installServiceQuery (accessor) */ -clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcService, +/*clsLEAMDNSHost::clsQuery* */ bool clsLEAMDNSHost::installServiceQuery(const char* p_pcService, const char* p_pcProtocol, clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) { + bool bResult = false; clsQuery* pQuery = 0; - if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) - { - pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; - } - return pQuery; + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf) && (pQuery = _installServiceQuery(pNetIf, p_pcService, p_pcProtocol))) + { + pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; + bResult = true; + } + return bResult; } /* clsLEAmDNS2_Host::installHostQuery (answer) */ -clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, +/*clsLEAMDNSHost::clsQuery* */ bool clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) { + bool bResult = false; clsQuery* pQuery = 0; if ((p_pcHostName) && (*p_pcHostName)) - { - clsRRDomain domain; - if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) - ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) - : 0))) - { - pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; - } - } - return pQuery; + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf)) + { + clsRRDomain domain; + if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) + ? _installDomainQuery(pNetIf, domain, clsQuery::enuQueryType::Host) + : 0))) + { + pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; + bResult = true; + } + } + return bResult; } /* clsLEAmDNS2_Host::installHostQuery (accessor) */ -clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, +/*clsLEAMDNSHost::clsQuery* */ bool clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) { + bool bResult = true; clsQuery* pQuery = 0; if ((p_pcHostName) && (*p_pcHostName)) - { - clsRRDomain domain; - if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) - ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) - : 0))) - { - pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; - } - } - return pQuery; + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf)) + { + clsRRDomain domain; + if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) + ? _installDomainQuery(pNetIf, domain, clsQuery::enuQueryType::Host) + : 0))) + { + pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; + bResult = true; + } + } + return bResult; } /* clsLEAmDNS2_Host::removeQuery */ -bool clsLEAMDNSHost::removeQuery(clsLEAMDNSHost::clsQuery* p_pMDNSQuery) -{ +/* + bool clsLEAMDNSHost::removeQuery(clsLEAMDNSHost::clsQuery * p_pMDNSQuery) + { bool bResult = ((p_pMDNSQuery) && (_removeQuery(p_pMDNSQuery))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeQuery: FAILED!\n"), _DH());); return bResult; -} + } +*/ /* @@ -702,15 +754,21 @@ bool clsLEAMDNSHost::update(void) { bool bResult = false; - //if (clsBackbone::sm_pBackbone->setDelayUDPProcessing(true)) - //{ - bResult = ((_updateProbeStatus()) && // Probing and announcing - (_checkQueryCache())); + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf)) + { + //if (clsBackbone::sm_pBackbone->setDelayUDPProcessing(true)) + //{ + if ((_updateProbeStatus(pNetIf)) && // Probing and announcing + (_checkQueryCache())) + { + bResult = true; + } - // clsBackbone::sm_pBackbone->setDelayUDPProcessing(false); - //} + // clsBackbone::sm_pBackbone->setDelayUDPProcessing(false); + //} + } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s update: FAILED (Not connected?)!\n"), _DH());); - return bResult; } @@ -726,7 +784,7 @@ bool clsLEAMDNSHost::announce(bool p_bAnnounce /*= true*/, /* clsLEAmDNS2_Host::announceService */ -bool clsLEAMDNSHost::announceService(clsService* p_pService, +bool clsLEAMDNSHost::announceService(clsService * p_pService, bool p_bAnnounce /*= true*/) { return _announceService(*p_pService, p_bAnnounce); @@ -840,45 +898,45 @@ bool clsLEAMDNSHost::_joinMulticastGroups(void) // Join multicast group(s) for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) - { -#ifdef MDNS_IPV4_SUPPORT - ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; - if (!(m_pNetIf->flags & NETIF_FLAG_IGMP)) { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: Setting flag: flags & NETIF_FLAG_IGMP\n"), _DH());); - m_pNetIf->flags |= NETIF_FLAG_IGMP; - - if (ERR_OK != igmp_start(m_pNetIf)) +#ifdef MDNS_IPV4_SUPPORT + ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; + if (!(pNetIf->flags & NETIF_FLAG_IGMP)) { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: igmp_start FAILED!\n"), _DH());); + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: Setting flag: flags & NETIF_FLAG_IGMP\n"), _DH());); + pNetIf->flags |= NETIF_FLAG_IGMP; + + if (ERR_OK != igmp_start(pNetIf)) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: igmp_start FAILED!\n"), _DH());); + } } - } - if ( + if ( #if LWIP_VERSION_MAJOR == 1 - (ERR_OK == igmp_joingroup(&pNetIf->ip_addr, &multicast_addr_V4)) + (ERR_OK == igmp_joingroup(&pNetIf->ip_addr, &multicast_addr_V4)) #else - (ERR_OK == igmp_joingroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4))) + (ERR_OK == igmp_joingroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4))) #endif - ) - { - bResult = true; - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: igmp_joingroup_netif(" NETIFID_STR ": %s) FAILED!\n"), - _DH(), NETIFID_VAL(pNetIf), IPAddress(multicast_addr_V4).toString().c_str());); - } + ) + { + bResult = true; + } + else + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: igmp_joingroup_netif(" NETIFID_STR ": %s) FAILED!\n"), + _DH(), NETIFID_VAL(pNetIf), IPAddress(multicast_addr_V4).toString().c_str());); + } #endif #ifdef MDNS_IPV6_SUPPORT - ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; - bResult = ((bResult) && - (ERR_OK == mld6_joingroup_netif(pNetIf, ip_2_ip6(&multicast_addr_V6)))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: mld6_joingroup_netif (" NETIFID_STR ") FAILED!\n"), - _DH(), NETIFID_VAL(pNetIf));); + ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; + bResult = ((bResult) && + (ERR_OK == mld6_joingroup_netif(pNetIf, ip_2_ip6(&multicast_addr_V6)))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: mld6_joingroup_netif (" NETIFID_STR ") FAILED!\n"), + _DH(), NETIFID_VAL(pNetIf));); #endif - } + } return bResult; } @@ -890,33 +948,33 @@ bool clsLEAMDNSHost::_leaveMulticastGroups() bool bResult = false; for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) - { - bResult = true; - /* _resetProbeStatus(false); // Stop probing - _releaseQueries(); - _releaseServices(); - _releaseHostName();*/ + { + bResult = true; + /* _resetProbeStatus(false); // Stop probing + _releaseQueries(); + _releaseServices(); + _releaseHostName();*/ - // Leave multicast group(s) + // Leave multicast group(s) #ifdef MDNS_IPV4_SUPPORT - ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; + ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; #if LWIP_VERSION_MAJOR == 1 - if (ERR_OK != igmp_leavegroup(ip_2_ip4(pNetIf->ip_addr), ip_2_ip4(&multicast_addr_V4))) + if (ERR_OK != igmp_leavegroup(ip_2_ip4(pNetIf->ip_addr), ip_2_ip4(&multicast_addr_V4))) #else - if (ERR_OK != igmp_leavegroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4))) + if (ERR_OK != igmp_leavegroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4))) #endif - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); - } + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); + } #endif #ifdef MDNS_IPV6_SUPPORT - ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; - if (ERR_OK != mld6_leavegroup_netif(pNetIf, ip_2_ip6(&multicast_addr_V6)/*&(multicast_addr_V6.u_addr.ip6)*/)) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); - } + ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; + if (ERR_OK != mld6_leavegroup_netif(pNetIf, ip_2_ip6(&multicast_addr_V6)/*&(multicast_addr_V6.u_addr.ip6)*/)) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); + } #endif - } + } return bResult; } @@ -1041,7 +1099,7 @@ const char* clsLEAMDNSHost::_instanceName(const char* p_pcInstanceName, /* clsLEAmDNS2_Host::_collectServiceTxts */ -bool clsLEAMDNSHost::_collectServiceTxts(clsLEAMDNSHost::clsService& p_rService) +bool clsLEAMDNSHost::_collectServiceTxts(clsLEAMDNSHost::clsService & p_rService) { if (p_rService.m_fnTxtCallback) { @@ -1053,7 +1111,7 @@ bool clsLEAMDNSHost::_collectServiceTxts(clsLEAMDNSHost::clsService& p_rService) /* clsLEAmDNS2_Host::_releaseTempServiceTxts */ -bool clsLEAMDNSHost::_releaseTempServiceTxts(clsLEAMDNSHost::clsService& p_rService) +bool clsLEAMDNSHost::_releaseTempServiceTxts(clsLEAMDNSHost::clsService & p_rService) { return (p_rService.m_Txts.removeTempTxts()); } @@ -1084,7 +1142,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_allocQuery(clsLEAMDNSHost::clsQuery:: MDNSResponder:clsHost:::_removeQuery */ -bool clsLEAMDNSHost::_removeQuery(clsLEAMDNSHost::clsQuery* p_pQuery) +bool clsLEAMDNSHost::_removeQuery(clsLEAMDNSHost::clsQuery * p_pQuery) { bool bResult = false; @@ -1154,9 +1212,9 @@ bool clsLEAMDNSHost::_releaseQueries(void) clsLEAmDNS2_Host::_findNextQueryByDomain */ -clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findNextQueryByDomain(const clsLEAMDNSHost::clsRRDomain& p_Domain, +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findNextQueryByDomain(const clsLEAMDNSHost::clsRRDomain & p_Domain, const clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType, - const clsQuery* p_pPrevQuery) + const clsQuery * p_pPrevQuery) { clsQuery* pMatchingQuery = 0; @@ -1191,7 +1249,8 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findNextQueryByDomain(const clsLEAMDN clsLEAmDNS2_Host::_installServiceQuery */ -clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery(const char* p_pcService, +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery(netif* pNetIf, + const char* p_pcService, const char* p_pcProtocol) { clsQuery* pMDNSQuery = 0; @@ -1203,7 +1262,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery(const char* p_pcS { pMDNSQuery->m_bStaticQuery = false; - if (_sendQuery(*pMDNSQuery)) + if (_sendQuery(pNetIf, *pMDNSQuery)) { pMDNSQuery->m_u8SentCount = 1; pMDNSQuery->m_ResendTimeout.reset(clsConsts::u32DynamicQueryResendDelay); @@ -1221,7 +1280,8 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery(const char* p_pcS /* clsLEAmDNS2_Host::_installDomainQuery */ -clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installDomainQuery(clsLEAMDNSHost::clsRRDomain& p_Domain, +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installDomainQuery(netif* pNetIf, + clsLEAMDNSHost::clsRRDomain & p_Domain, clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType) { clsQuery* pQuery = 0; @@ -1231,7 +1291,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installDomainQuery(clsLEAMDNSHost::cl pQuery->m_Domain = p_Domain; pQuery->m_bStaticQuery = false; - if (_sendQuery(*pQuery)) + if (_sendQuery(pNetIf, *pQuery)) { pQuery->m_u8SentCount = 1; pQuery->m_ResendTimeout.reset(clsConsts::u32DynamicQueryResendDelay); @@ -1246,13 +1306,10 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installDomainQuery(clsLEAMDNSHost::cl _printRRDomain(p_Domain); DEBUG_OUTPUT.println(); ); - DEBUG_EX_ERR(if (!pQuery) -{ - DEBUG_OUTPUT.printf_P(PSTR("%s _installDomainQuery: FAILED for "), _DH()); - _printRRDomain(p_Domain); - DEBUG_OUTPUT.println(); - } - ); + DEBUG_EX_ERR_IF(!pQuery, + DEBUG_OUTPUT.printf_P(PSTR("%s _installDomainQuery: FAILED for "), _DH()); + _printRRDomain(p_Domain); + DEBUG_OUTPUT.println()); return pQuery; } @@ -1277,8 +1334,8 @@ bool clsLEAMDNSHost::_hasQueriesWaitingForAnswers(void) const /* clsLEAmDNS2_Host::_executeQueryCallback */ -bool clsLEAMDNSHost::_executeQueryCallback(const clsQuery& p_Query, - const clsQuery::clsAnswer& p_Answer, +bool clsLEAMDNSHost::_executeQueryCallback(const clsQuery & p_Query, + const clsQuery::clsAnswer & p_Answer, clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, bool p_bSetContent) { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index d724a19ba7..d5bdffcb09 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -298,15 +298,15 @@ class clsLEAMDNSHost bool m_bDelayUDPProcessing; uint32_t m_u32DelayedDatagrams; //list m_HostList; - clsLEAMDNSHost m_uniqueHost; + clsLEAMDNSHost* m_uniqueHost; bool _allocUDPContext(void); bool _releaseUDPContext(void); bool _processUDPInput(void); - const clsLEAMDNSHost* _findHost() const { return &m_uniqueHost; } - clsLEAMDNSHost* _findHost() { return &m_uniqueHost; } + const clsLEAMDNSHost* _findHost() const { return m_uniqueHost; } + clsLEAMDNSHost* _findHost() { return m_uniqueHost; } const char* _DH(void) const; }; @@ -1252,8 +1252,7 @@ class clsLEAMDNSHost static const char* indexDomainName(const char* p_pcDomainName, const char* p_pcDivider = "-", const char* p_pcDefaultDomainName = 0); - static bool setNetIfHostName(netif* p_pNetIf, - const char* p_pcHostName); + static bool setNetIfHostName(const char* p_pcHostName); clsLEAMDNSHost(void); ~clsLEAMDNSHost(void); @@ -1328,18 +1327,23 @@ class clsLEAMDNSHost // - hasAnswerIPv6Address/answerIPv6Address service/host // - hasAnswerPort/answerPort service // - hasAnswerTxts/answerTxts service - clsQuery* installServiceQuery(const char* p_pcServiceType, + + /* + install*Query() creates several queries on the interfaces. + it no more returns a single query but a boolean until the API is adapted + */ + /*clsQuery**/bool installServiceQuery(const char* p_pcServiceType, const char* p_pcProtocol, clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); - clsQuery* installServiceQuery(const char* p_pcServiceType, + /*clsQuery**/bool installServiceQuery(const char* p_pcServiceType, const char* p_pcProtocol, clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); - clsQuery* installHostQuery(const char* p_pcHostName, + /*clsQuery**/bool installHostQuery(const char* p_pcHostName, clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); - clsQuery* installHostQuery(const char* p_pcHostName, + /*clsQuery**/bool installHostQuery(const char* p_pcHostName, clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); // Remove a dynamic service query - bool removeQuery(clsQuery* p_pQuery); + /*bool removeQuery(clsQuery* p_pQuery);*/ // PROCESSING bool update(void); @@ -1419,9 +1423,11 @@ class clsLEAMDNSHost clsQuery* _findNextQueryByDomain(const clsRRDomain& p_Domain, const clsQuery::enuQueryType p_QueryType, const clsQuery* p_pPrevQuery); - clsQuery* _installServiceQuery(const char* p_pcService, + clsQuery* _installServiceQuery(netif* pNetIf, + const char* p_pcService, const char* p_pcProtocol); - clsQuery* _installDomainQuery(clsRRDomain& p_Domain, + clsQuery* _installDomainQuery(netif *pNetIf, + clsRRDomain& p_Domain, clsQuery::enuQueryType p_QueryType); bool _hasQueriesWaitingForAnswers(void) const; bool _executeQueryCallback(const clsQuery& p_Query, @@ -1433,7 +1439,8 @@ class clsLEAMDNSHost // File: ..._Host_Control // RECEIVING bool _parseMessage(void); - bool _parseQuery(const clsMsgHeader& p_Header); + bool _parseQuery(netif* pNetIf, + const clsMsgHeader& p_Header); bool _parseResponse(const clsMsgHeader& p_Header); bool _processAnswers(const clsRRAnswer* p_pPTRAnswers); @@ -1450,11 +1457,11 @@ class clsLEAMDNSHost #endif // PROBING - bool _updateProbeStatus(void); + bool _updateProbeStatus(netif* pNetIf); bool _resetProbeStatus(bool p_bRestart = true); bool _hasProbesWaitingForAnswers(void) const; - bool _sendHostProbe(void); - bool _sendServiceProbe(clsService& p_rService); + bool _sendHostProbe(netif* pNetIf); + bool _sendServiceProbe(netif* pNetIf, clsService& p_rService); bool _cancelProbingForHost(void); bool _cancelProbingForService(clsService& p_rService); bool _callHostProbeResultCallback(bool p_bResult); @@ -1462,9 +1469,11 @@ class clsLEAMDNSHost bool p_bResult); // ANNOUNCE - bool _announce(bool p_bAnnounce, + bool _announce(netif* pNetIf, + bool p_bAnnounce, bool p_bIncludeServices); - bool _announceService(clsService& p_pService, + bool _announceService(netif* pNetIf, + clsService& p_pService, bool p_bAnnounce = true); // QUERY CACHE @@ -1479,16 +1488,19 @@ class clsLEAMDNSHost // File: ..._Host_Transfer // SENDING - bool _sendMessage(clsSendParameter& p_SendParameter); - bool _sendMessage_Multicast(clsSendParameter& p_rSendParameter, + bool _sendMessage(netif* pNetIf, clsSendParameter& p_SendParameter); + bool _sendMessage_Multicast(netif* pNetIf, + clsSendParameter& p_rSendParameter, uint8_t p_IPProtocolTypes); bool _prepareMessage(clsSendParameter& p_SendParameter); bool _addQueryRecord(clsSendParameter& p_rSendParameter, const clsRRDomain& p_QueryDomain, uint16_t p_u16QueryType); - bool _sendQuery(const clsQuery& p_Query, + bool _sendQuery(netif* netif, + const clsQuery& p_Query, clsQuery::clsAnswer::list* p_pKnownAnswers = 0); - bool _sendQuery(const clsRRDomain& p_QueryDomain, + bool _sendQuery(netif* netif, + const clsRRDomain& p_QueryDomain, uint16_t p_u16RecordType, clsQuery::clsAnswer::list* p_pKnownAnswers = 0); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index bab5eba3cf..48eba00b0d 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -82,7 +82,7 @@ bool clsLEAMDNSHost::_parseMessage(void) { // Received a query (Questions) //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: Reading query: ID:%u, Q:%u, A:%u, NS:%u, AR:%u\n"), _DH(), header.m_u16ID, header.m_u16QDCount, header.m_u16ANCount, header.m_u16NSCount, header.m_u16ARCount);); - bResult = _parseQuery(header); + bResult = _parseQuery(m_pUDPContext->getInputNetif(), header); } } else @@ -119,7 +119,8 @@ bool clsLEAMDNSHost::_parseMessage(void) Legacy queries have got only one (unicast) question and are directed to the local DNS port (not the multicast port). */ -bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader) +bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, + const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader) { bool bResult = true; @@ -209,9 +210,9 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader if ((m_pUDPContext) && #ifdef MDNS_IPV4_SUPPORT (m_pUDPContext->getRemoteAddress().isV4()) && - (ip4_addr_netcmp(ip_2_ip4(m_pUDPContext->getRemoteAddress()), - ip_2_ip4(m_pUDPContext->getInputNetif()->ip_addr), - ip_2_ip4(m_pUDPContext->getInputNetif()->netmask)) + (ip4_addr_netcmp(ip_2_ip4((const ip_addr_t*)m_pUDPContext->getRemoteAddress()), + ip_2_ip4(&m_pUDPContext->getInputNetif()->ip_addr), + ip_2_ip4(&m_pUDPContext->getInputNetif()->netmask))) #else (true) #endif @@ -548,7 +549,7 @@ bool clsLEAMDNSHost::_parseQuery(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader sendParameter.m_Response = clsSendParameter::enuResponseType::Response; sendParameter.m_bAuthorative = true; - bResult = _sendMessage(sendParameter); + bResult = _sendMessage(pNetIf, sendParameter); } DEBUG_EX_INFO(else { @@ -1281,7 +1282,7 @@ bool clsLEAMDNSHost::_processAAAAAnswer(const clsLEAMDNSHost::clsRRAnswerAAAA* p Conflict management is handled in '_parseResponse ff.' Tiebraking is handled in 'parseQuery ff.' */ -bool clsLEAMDNSHost::_updateProbeStatus(void) +bool clsLEAMDNSHost::_updateProbeStatus(netif* pNetIf) { bool bResult = true; @@ -1314,7 +1315,7 @@ bool clsLEAMDNSHost::_updateProbeStatus(void) if (clsConsts::u32ProbeCount > m_ProbeInformation.m_u8SentCount) { // Send next probe - if ((bResult = _sendHostProbe())) + if ((bResult = _sendHostProbe(pNetIf))) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Did sent host probe for '%s.local'\n\n"), _DH(), (m_pcHostName ? : ""));); m_ProbeInformation.m_Timeout.reset(clsConsts::u32ProbeDelay); @@ -1378,7 +1379,7 @@ bool clsLEAMDNSHost::_updateProbeStatus(void) if (clsConsts::u32ProbeCount > pService->m_ProbeInformation.m_u8SentCount) { // Send next probe - if ((bResult = _sendServiceProbe(*pService))) + if ((bResult = _sendServiceProbe(pNetIf, *pService))) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Did sent service probe for '%s' (%u)\n\n"), _DH(), _service2String(pService), (pService->m_ProbeInformation.m_u8SentCount + 1));); pService->m_ProbeInformation.m_Timeout.reset(clsConsts::u32ProbeDelay); @@ -1482,7 +1483,7 @@ bool clsLEAMDNSHost::_hasProbesWaitingForAnswers(void) const - A/AAAA (eg. esp8266.esp -> 192.168.2.120) */ -bool clsLEAMDNSHost::_sendHostProbe(void) +bool clsLEAMDNSHost::_sendHostProbe(netif* pNetIf) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendHostProbe (%s.local, %lu)\n"), _DH(), m_pcHostName, millis());); @@ -1521,7 +1522,7 @@ bool clsLEAMDNSHost::_sendHostProbe(void) } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendHostProbe: FAILED!\n"), _DH());); return ((bResult) && - (_sendMessage(sendParameter))); + (_sendMessage(pNetIf, sendParameter))); } /* @@ -1537,7 +1538,7 @@ bool clsLEAMDNSHost::_sendHostProbe(void) - PTR NAME (eg. _http._tcp.local -> MyESP._http._tcp.local) (TODO: Check if needed, maybe TXT is better) */ -bool clsLEAMDNSHost::_sendServiceProbe(clsService& p_rService) +bool clsLEAMDNSHost::_sendServiceProbe(netif* pNetIf, clsService& p_rService) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendServiceProbe (%s, %lu)\n"), _DH(), _service2String(&p_rService), millis());); @@ -1571,7 +1572,7 @@ bool clsLEAMDNSHost::_sendServiceProbe(clsService& p_rService) } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendServiceProbe: FAILED!\n"), _DH());); return ((bResult) && - (_sendMessage(sendParameter))); + (_sendMessage(pNetIf, sendParameter))); } /* @@ -1670,7 +1671,8 @@ bool clsLEAMDNSHost::_callServiceProbeResultCallback(clsLEAMDNSHost::clsService& inside the '_writeXXXAnswer' procs via 'sendParameter.m_bUnannounce = true' */ -bool clsLEAMDNSHost::_announce(bool p_bAnnounce, +bool clsLEAMDNSHost::_announce(netif* pNetIf, + bool p_bAnnounce, bool p_bIncludeServices) { bool bResult = false; @@ -1716,14 +1718,15 @@ bool clsLEAMDNSHost::_announce(bool p_bAnnounce, } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _announce: FAILED!\n"), _DH());); return ((bResult) && - (_sendMessage(sendParameter))); + (_sendMessage(pNetIf, sendParameter))); } /* clsLEAmDNS2_Host::_announceService */ -bool clsLEAMDNSHost::_announceService(clsLEAMDNSHost::clsService& p_rService, +bool clsLEAMDNSHost::_announceService(netif* pNetIf, + clsLEAMDNSHost::clsService& p_rService, bool p_bAnnounce /*= true*/) { bool bResult = false; @@ -1749,7 +1752,7 @@ bool clsLEAMDNSHost::_announceService(clsLEAMDNSHost::clsService& p_rService, } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _announceService: FAILED!\n"), _DH());); return ((bResult) && - (_sendMessage(sendParameter))); + (_sendMessage(pNetIf, sendParameter))); } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp index 94855d2ab5..f0edcd4232 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp @@ -40,12 +40,12 @@ namespace experimental clsLEAmDNS2_Host::_DH */ -xxxxx const char* clsLEAMDNSHost::_DH(const clsLEAMDNSHost::clsService* p_pService /*= 0*/) const +const char* clsLEAMDNSHost::_DH(const clsLEAMDNSHost::clsService* p_pService /*= 0*/) const { static char acBuffer[16 + 64]; *acBuffer = 0; - sprintf_P(acBuffer, PSTR("[mDNS]"); + sprintf_P(acBuffer, PSTR("[mDNS]")); if (p_pService) { strcat_P(acBuffer, PSTR(">")); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 6ad703d4cc..1d1a4df1b1 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -50,14 +50,14 @@ namespace experimental Any reply flags in installed services are removed at the end! */ -bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_sendMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { bool bResult = false; uint8_t u8AvailableProtocols = 0; #ifdef MDNS_IPV4_SUPPORT // Only send out IPv4 messages, if we've got an IPv4 address - if (_getResponderIPAddress(enuIPProtocolType::V4).isSet()) + if (_getResponderIPAddress(pNetIf, enuIPProtocolType::V4).isSet()) { u8AvailableProtocols |= static_cast<uint8_t>(enuIPProtocolType::V4); } @@ -68,7 +68,7 @@ bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParam #endif #ifdef MDNS_IPV6_SUPPORT // Only send out IPv6 messages, if we've got an IPv6 address - if (_getResponderIPAddress(enuIPProtocolType::V6).isSet()) + if (_getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet()) { u8AvailableProtocols |= static_cast<uint8_t>(enuIPProtocolType::V6); } @@ -113,7 +113,7 @@ bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParam (ipRemote.isV4())) && // OR IPv4 (u8AvailableProtocols & static_cast<uint8_t>(enuIPProtocolType::V4))) // AND IPv4 protocol available { - bResult = _sendMessage_Multicast(p_rSendParameter, static_cast<uint8_t>(enuIPProtocolType::V4)); + bResult = _sendMessage_Multicast(pNetIf, p_rSendParameter, static_cast<uint8_t>(enuIPProtocolType::V4)); } #endif #ifdef MDNS_IPV6_SUPPORT @@ -121,7 +121,7 @@ bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParam (ipRemote.isV6())) && // OR IPv6 (u8AvailableProtocols & static_cast<uint8_t>(enuIPProtocolType::V6))) // AND IPv6 protocol available { - bResult = _sendMessage_Multicast(p_rSendParameter, static_cast<uint8_t>(enuIPProtocolType::V6)); + bResult = _sendMessage_Multicast(pNetIf, p_rSendParameter, static_cast<uint8_t>(enuIPProtocolType::V6)); } #endif } @@ -130,7 +130,7 @@ bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParam { // Multicast query -> Send by all available protocols bResult = ((u8AvailableProtocols) && - (_sendMessage_Multicast(p_rSendParameter, u8AvailableProtocols))); + (_sendMessage_Multicast(pNetIf, p_rSendParameter, u8AvailableProtocols))); } // Finally clear service reply masks @@ -152,7 +152,7 @@ bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParam Fills the UDP output buffer (via _prepareMessage) and sends the buffer via the selected WiFi protocols */ -bool clsLEAMDNSHost::_sendMessage_Multicast(clsLEAMDNSHost::clsSendParameter& p_rSendParameter, +bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSendParameter& p_rSendParameter, uint8_t p_IPProtocolTypes) { bool bIPv4Result = true; @@ -164,9 +164,9 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(clsLEAMDNSHost::clsSendParameter& p_ IPAddress ip4MulticastAddress(DNS_MQUERY_IPV4_GROUP_INIT); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast IPv4: Will send to '%s'.\n"), _DH(), ip4MulticastAddress.toString().c_str());); - DEBUG_EX_INFO(if (!_getResponderIPAddress(enuIPProtocolType::V4)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast IPv4: NO IPv4 address!.\n"), _DH());); + DEBUG_EX_INFO(if (!_getResponderIPAddress(pNetIf, enuIPProtocolType::V4)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast IPv4: NO IPv4 address!.\n"), _DH());); bIPv4Result = ((_prepareMessage(p_rSendParameter)) && - (m_pUDPContext->setMulticastInterface(m_pNetIf), true) && + (m_pUDPContext->setMulticastInterface(pNetIf), true) && (m_pUDPContext->send(ip4MulticastAddress, DNS_MQUERY_PORT)) && (m_pUDPContext->setMulticastInterface(0), true) /*&& (Serial.println("Did send MC V4"), true)*/); @@ -186,17 +186,17 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(clsLEAMDNSHost::clsSendParameter& p_ IPAddress ip6MulticastAddress(DNS_MQUERY_IPV6_GROUP_INIT); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast IPv6: Will send to '%s'.\n"), _DH(), ip6MulticastAddress.toString().c_str());); - DEBUG_EX_INFO(if (!_getResponderIPAddress(enuIPProtocolType::V6)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast IPv6: NO IPv6 address!.\n"), _DH());); + DEBUG_EX_INFO(if (!_getResponderIPAddress(pNetIf, enuIPProtocolType::V6)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast IPv6: NO IPv6 address!.\n"), _DH());); DEBUG_EX_ERR( bool bPrepareMessage = false; bool bUDPContextSend = false; ); bIPv6Result = ((DEBUG_EX_ERR(bPrepareMessage =)_prepareMessage(p_rSendParameter)) && - (m_pUDPContext->setMulticastInterface(m_pNetIf), true) && + (m_pUDPContext->setMulticastInterface(pNetIf), true) && (DEBUG_EX_ERR(bUDPContextSend =)m_pUDPContext->send(ip6MulticastAddress, DNS_MQUERY_PORT)) && (m_pUDPContext->setMulticastInterface(0), true) /*&& (Serial.println("Did send MC V6"), true)*/); - DEBUG_EX_ERR(if (!bIPv6Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (IPv6): FAILED! (%s, %s, %s)\n"), _DH(), (_getResponderIPAddress(enuIPProtocolType::V6).isSet() ? "1" : "0"), (bPrepareMessage ? "1" : "0"), (bUDPContextSend ? "1" : "0"));); + DEBUG_EX_ERR(if (!bIPv6Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (IPv6): FAILED! (%s, %s, %s)\n"), _DH(), (_getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet() ? "1" : "0"), (bPrepareMessage ? "1" : "0"), (bUDPContextSend ? "1" : "0"));); if ((clsConsts::u32SendCooldown) && (can_yield())) @@ -288,25 +288,25 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa // A if ((bResult) && (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::A)) && - (_getResponderIPAddress(enuIPProtocolType::V4).isSet())) + (_getResponderIPAddress(pNetIf, enuIPProtocolType::V4).isSet())) { u32NSECContent |= static_cast<uint32_t>(enuContentFlag::A); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16Answers - : (bResult = _writeMDNSAnswer_A(_getResponderIPAddress(enuIPProtocolType::V4), p_rSendParameter))); + : (bResult = _writeMDNSAnswer_A(_getResponderIPAddress(pNetIf, enuIPProtocolType::V4), p_rSendParameter))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_A(A) FAILED!\n"), _DH());); } // PTR_IPv4 if ((bResult) && (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)) && - (_getResponderIPAddress(enuIPProtocolType::V4).isSet())) + (_getResponderIPAddress(pNetIf, enuIPProtocolType::V4).isSet())) { u32NSECContent |= static_cast<uint32_t>(enuContentFlag::PTR_IPv4); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16Answers - : (bResult = _writeMDNSAnswer_PTR_IPv4(_getResponderIPAddress(enuIPProtocolType::V4), p_rSendParameter))); + : (bResult = _writeMDNSAnswer_PTR_IPv4(_getResponderIPAddress(pNetIf, enuIPProtocolType::V4), p_rSendParameter))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_PTR_IPv4 FAILED!\n"), _DH());); } #endif @@ -314,35 +314,35 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa // AAAA if ((bResult) && (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::AAAA)) && - (_getResponderIPAddress(enuIPProtocolType::V6).isSet())) - { + (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6).isSet())) + { - u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16Answers - : (bResult = _writeMDNSAnswer_AAAA(_getResponderIPAddress(enuIPProtocolType::V6), p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_AAAA(A) FAILED!\n"), _DH());); + : (bResult = _writeMDNSAnswer_AAAA(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6), p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_AAAA(A) FAILED!\n"), _DH());); } - // PTR_IPv6 - if ((bResult) && + // PTR_IPv6 + if ((bResult) && (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv6)) && - (_getResponderIPAddress(enuIPProtocolType::V6).isSet())) - { + (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6).isSet())) + { - u32NSECContent |= static_cast<uint32_t>(enuContentFlag::PTR_IPv6); + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::PTR_IPv6); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16Answers - : (bResult = _writeMDNSAnswer_PTR_IPv6(_getResponderIPAddress(enuIPProtocolType::V6), p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_PTR_IPv6 FAILED!\n"), _DH());); + : (bResult = _writeMDNSAnswer_PTR_IPv6(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6), p_rSendParameter))); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_PTR_IPv6 FAILED!\n"), _DH());); } #endif - for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) - { - clsService* pService = *it; + for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) + { + clsService* pService = *it; - // PTR_TYPE - if ((bResult) && + // PTR_TYPE + if ((bResult) && (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_TYPE))) { ((static_cast<typeSequence>(enuSequence::Count) == sequence) @@ -383,16 +383,16 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa uint16_t& ru16AdditionalAnswers = msgHeader.m_u16ARCount; #ifdef MDNS_IPV4_SUPPORT - bool bNeedsAdditionalAnswerA = false; + bool bNeedsAdditionalAnswerA = false; #endif #ifdef MDNS_IPV6_SUPPORT - bool bNeedsAdditionalAnswerAAAA = false; + bool bNeedsAdditionalAnswerAAAA = false; #endif - for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) - { - clsService* pService = *it; + for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) + { + clsService* pService = *it; - if ((bResult) && + if ((bResult) && (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_NAME)) && // If PTR_NAME is requested, AND (!(pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::SRV)))) // NOT SRV -> add SRV as additional answer { @@ -446,41 +446,41 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa // Answer A needed? if ((bResult) && (bNeedsAdditionalAnswerA) && - (_getResponderIPAddress(enuIPProtocolType::V4).isSet())) - { - // Additional A - u32NSECContent |= static_cast<uint32_t>(enuContentFlag::A); + (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4).isSet())) + { + // Additional A + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::A); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16AdditionalAnswers - : (bResult = _writeMDNSAnswer_A(_getResponderIPAddress(enuIPProtocolType::V4), p_rSendParameter))); + : (bResult = _writeMDNSAnswer_A(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4), p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_A(B) FAILED!\n"), _DH());); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_A(B) FAILED!\n"), _DH());); } #endif #ifdef MDNS_IPV6_SUPPORT - // Answer AAAA needed? - if ((bResult) && + // Answer AAAA needed? + if ((bResult) && (bNeedsAdditionalAnswerAAAA) && - (_getResponderIPAddress(enuIPProtocolType::V6).isSet())) - { - // Additional AAAA - u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); + (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6).isSet())) + { + // Additional AAAA + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16AdditionalAnswers - : (bResult = _writeMDNSAnswer_AAAA(_getResponderIPAddress(enuIPProtocolType::V6), p_rSendParameter))); + : (bResult = _writeMDNSAnswer_AAAA(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6), p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_AAAA(B) FAILED!\n"), _DH());); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_AAAA(B) FAILED!\n"), _DH());); } #endif - // NSEC host (part 2) - if ((bResult) && + // NSEC host (part 2) + if ((bResult) && ((clsSendParameter::enuResponseType::None != p_rSendParameter.m_Response)) && (u32NSECContent)) - { - // NSEC PTR IPv4/IPv6 are separate answers; make sure, that this is counted for + { + // NSEC PTR IPv4/IPv6 are separate answers; make sure, that this is counted for #ifdef MDNS_IPV4_SUPPORT - uint32_t u32NSECContent_PTR_IPv4 = (u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)); + uint32_t u32NSECContent_PTR_IPv4 = (u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)); u32NSECContent &= ~static_cast<uint32_t>(enuContentFlag::PTR_IPv4); #endif #ifdef MDNS_IPV6_SUPPORT @@ -503,35 +503,35 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa #ifdef MDNS_IPV4_SUPPORT // Write separate answer for host PTR IPv4 && ((!u32NSECContent_PTR_IPv4) || - ((!_getResponderIPAddress(enuIPProtocolType::V4).isSet()) || - (_writeMDNSAnswer_NSEC_PTR_IPv4(_getResponderIPAddress(enuIPProtocolType::V4), p_rSendParameter)))) + ((!_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4).isSet()) || + (_writeMDNSAnswer_NSEC_PTR_IPv4(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4), p_rSendParameter)))) #endif #ifdef MDNS_IPV6_SUPPORT - // Write separate answer for host PTR IPv6 - && ((!u32NSECContent_PTR_IPv6) || - ((!_getResponderIPAddress(enuIPProtocolType::V6).isSet()) || - (_writeMDNSAnswer_NSEC_PTR_IPv6(_getResponderIPAddress(enuIPProtocolType::V6), p_rSendParameter)))) + // Write separate answer for host PTR IPv6 + && ((!u32NSECContent_PTR_IPv6) || + ((!_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6).isSet()) || + (_writeMDNSAnswer_NSEC_PTR_IPv6(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6), p_rSendParameter)))) #endif - ))); + ))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_NSEC(Host) FAILED!\n"), _DH());); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_NSEC(Host) FAILED!\n"), _DH());); } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: Loop %i FAILED!\n"), _DH(), sequence);); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: Loop %i FAILED!\n"), _DH(), sequence);); } // for sequence - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: FAILED!\n"), _DH());); - return bResult; + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: FAILED!\n"), _DH());); + return bResult; } -/* - MDNSResponder::_addQueryRecord + /* + MDNSResponder::_addQueryRecord - Adds a query for the given domain and query type. + Adds a query for the given domain and query type. -*/ -bool clsLEAMDNSHost::_addQueryRecord(clsLEAMDNSHost::clsSendParameter& p_rSendParameter, - const clsLEAMDNSHost::clsRRDomain& p_QueryDomain, - uint16_t p_u16RecordType) + */ + bool clsLEAMDNSHost::_addQueryRecord(clsLEAMDNSHost::clsSendParameter& p_rSendParameter, + const clsLEAMDNSHost::clsRRDomain& p_QueryDomain, + uint16_t p_u16RecordType) { bool bResult = false; @@ -556,7 +556,8 @@ bool clsLEAMDNSHost::_addQueryRecord(clsLEAMDNSHost::clsSendParameter& p_rSendPa Creates and sends a query for the given domain and query type. */ -bool clsLEAMDNSHost::_sendQuery(const clsLEAMDNSHost::clsQuery& p_Query, +bool clsLEAMDNSHost::_sendQuery(netif* pNetIf, + const clsLEAMDNSHost::clsQuery& p_Query, clsLEAMDNSHost::clsQuery::clsAnswer::list* p_pKnownAnswers /*= 0*/) { bool bResult = false; @@ -584,9 +585,8 @@ bool clsLEAMDNSHost::_sendQuery(const clsLEAMDNSHost::clsQuery& p_Query, // TODO: Add known answers to query (void)p_pKnownAnswers; - bResult = ((bResult) && - (_sendMessage(sendParameter))); + (_sendMessage(pNetIf, sendParameter))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendQuery: FAILED!\n"), _DH());); return bResult; } @@ -597,7 +597,8 @@ bool clsLEAMDNSHost::_sendQuery(const clsLEAMDNSHost::clsQuery& p_Query, Creates and sends a query for the given domain and record type. */ -bool clsLEAMDNSHost::_sendQuery(const clsLEAMDNSHost::clsRRDomain& p_QueryDomain, +bool clsLEAMDNSHost::_sendQuery(netif* pNetIf, + const clsLEAMDNSHost::clsRRDomain& p_QueryDomain, uint16_t p_u16RecordType, clsLEAMDNSHost::clsQuery::clsAnswer::list* p_pKnownAnswers /*= 0*/) { @@ -605,7 +606,7 @@ bool clsLEAMDNSHost::_sendQuery(const clsLEAMDNSHost::clsRRDomain& p_QueryDomain clsSendParameter sendParameter; bResult = ((_addQueryRecord(sendParameter, p_QueryDomain, p_u16RecordType)) && - (_sendMessage(sendParameter))); + (_sendMessage(pNetIf, sendParameter))); // TODO: Add known answer records (void) p_pKnownAnswers; @@ -617,16 +618,16 @@ bool clsLEAMDNSHost::_sendQuery(const clsLEAMDNSHost::clsRRDomain& p_QueryDomain /* MDNSResponder::_getResponderIPAddress */ -IPAddress clsLEAMDNSHost::_getResponderIPAddress(enuIPProtocolType p_IPProtocolType) const +IPAddress clsLEAMDNSHost::_getResponderIPAddress(netif* pNetIf, enuIPProtocolType p_IPProtocolType) const { IPAddress ipResponder; #ifdef MDNS_IPV4_SUPPORT if (enuIPProtocolType::V4 == p_IPProtocolType) { #if LWIP_VERSION_MAJOR == 1 - ipResponder = ip_2_ip4(m_pNetIf->ip_addr); + ipResponder = ip_2_ip4(pNetIf->ip_addr); #else - ipResponder = netif_ip_addr4(m_pNetIf); + ipResponder = netif_ip_addr4(pNetIf); #endif } #endif @@ -636,7 +637,6 @@ IPAddress clsLEAMDNSHost::_getResponderIPAddress(enuIPProtocolType p_IPProtocolT bool bCheckLinkLocal = true; for (int i = 0; ((!ipResponder.isSet()) && (i < 2)); ++i) // Two loops: First with link-local check, second without { - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) for (int idx = 0; idx < LWIP_IPV6_NUM_ADDRESSES; ++idx) { //DEBUG_EX_INFO(if ip6_addr_isvalid(netif_ip6_addr_state(&pNetIf, idx)) DEBUG_OUTPUT.printf_P(PSTR("%s _getResponderIPAddress: Checking IPv6 address %s (LL: %s)\n"), _DH(), IPAddress(netif_ip_addr6(pNetIf, idx)).toString().c_str(), (bCheckLinkLocal ? "YES" : "NO"));); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index c5c465e8ad..2898bec218 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -71,10 +71,9 @@ UdpContext* clsLEAMDNSHost::clsBackbone::addHost(clsLEAMDNSHost* p_pHost) { UdpContext* pUDPContext = 0; - if ((m_pUDPContext) && - (p_pHost)) + if ((m_pUDPContext) && (p_pHost) && (m_uniqueHost == nullptr)) { - m_HostList.push_back(p_pHost); + m_uniqueHost = p_pHost; pUDPContext = m_pUDPContext; } DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s addHost: %s to add host!\n"), _DH(), (pUDPContext ? "Succeeded" : "FAILED"));); @@ -89,11 +88,9 @@ bool clsLEAMDNSHost::clsBackbone::removeHost(clsLEAMDNSHost* p_pHost) { bool bResult = false; - if ((p_pHost) && - (m_HostList.end() != std::find(m_HostList.begin(), m_HostList.end(), p_pHost))) + if ((p_pHost) && (m_uniqueHost == p_pHost)) { - // Remove host object - m_HostList.remove(p_pHost); + m_uniqueHost = nullptr; bResult = true; } DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s removeHost: %s to remove host!\n"), _DH(), (bResult ? "Succeeded" : "FAILED"));); @@ -107,7 +104,7 @@ bool clsLEAMDNSHost::clsBackbone::removeHost(clsLEAMDNSHost* p_pHost) */ size_t clsLEAMDNSHost::clsBackbone::hostCount(void) const { - return m_HostList.size(); + return m_uniqueHost == nullptr? 0: 1; } /* @@ -220,7 +217,7 @@ bool clsLEAMDNSHost::clsBackbone::_processUDPInput(void) { netif* pNetIf = m_pUDPContext->getInputNetif(); clsLEAMDNSHost* pHost = 0; - if ((pHost = _findHost(pNetIf))) + if ((pHost = _findHost())) { DEBUG_EX_INFO_IF(u32LoopCounter++, DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Multi-Loop (%u)!\n"), _DH(), u32LoopCounter); From b465c16eeedc0a94bf2ddf6b9f4f6ae14bad6e4f Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Mon, 25 May 2020 00:29:07 +0200 Subject: [PATCH 018/152] wip --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 29 +++++++-- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 19 +++--- .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 62 ++++++++++--------- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 38 ++++++------ libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 10 +-- 5 files changed, 91 insertions(+), 67 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 58d0a6f07b..7f53746038 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -431,9 +431,18 @@ bool clsLEAMDNSHost::removeService(clsLEAMDNSHost::clsService* p_pService) { bool bResult = false; - if ((bResult = ((p_pService) && - (m_Services.end() != std::find(m_Services.begin(), m_Services.end(), p_pService)) && - (_announceService(*p_pService, false))))) + if (p_pService && + (m_Services.end() != std::find(m_Services.begin(), m_Services.end(), p_pService))) + { + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf) && + (_announceService(pNetIf, *p_pService, false))) + { + bResult = true; + } + } + + if (bResult) { m_Services.remove(p_pService); delete p_pService; @@ -760,7 +769,7 @@ bool clsLEAMDNSHost::update(void) //if (clsBackbone::sm_pBackbone->setDelayUDPProcessing(true)) //{ if ((_updateProbeStatus(pNetIf)) && // Probing and announcing - (_checkQueryCache())) + (_checkQueryCache(pNetIf))) { bResult = true; } @@ -778,7 +787,11 @@ bool clsLEAMDNSHost::update(void) bool clsLEAMDNSHost::announce(bool p_bAnnounce /*= true*/, bool p_bIncludeServices /*= true*/) { - return _announce(p_bAnnounce, p_bIncludeServices); + bool bResult = false; + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf) && _announce(pNetIf, p_bAnnounce, p_bIncludeServices)) + bResult = true; + return bResult; } /* @@ -787,7 +800,11 @@ bool clsLEAMDNSHost::announce(bool p_bAnnounce /*= true*/, bool clsLEAMDNSHost::announceService(clsService * p_pService, bool p_bAnnounce /*= true*/) { - return _announceService(*p_pService, p_bAnnounce); + bool bResult = false; + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf) && _announceService(pNetIf, *p_pService, p_bAnnounce)) + bResult = true; + return bResult; } /* diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index d5bdffcb09..6ef6aa69da 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -278,6 +278,7 @@ class clsLEAMDNSHost // File: ..._Backbone /** clsBackbone + XXXX should be merged with holder clsLEAMDNSHost because there is no list anymore in it */ class clsBackbone { @@ -292,6 +293,8 @@ class clsLEAMDNSHost bool removeHost(clsLEAMDNSHost* p_pHost); size_t hostCount(void) const; bool setDelayUDPProcessing(bool p_bDelayProcessing); + + clsLEAMDNSHost* getUniqueHost() { return m_uniqueHost; } protected: UdpContext* m_pUDPContext; @@ -1438,12 +1441,12 @@ class clsLEAMDNSHost // File: ..._Host_Control // RECEIVING - bool _parseMessage(void); + bool _parseMessage(); bool _parseQuery(netif* pNetIf, const clsMsgHeader& p_Header); - bool _parseResponse(const clsMsgHeader& p_Header); - bool _processAnswers(const clsRRAnswer* p_pPTRAnswers); + bool _parseResponse(netif* pNetIf, const clsMsgHeader& p_Header); + bool _processAnswers(netif* pNetIf, const clsRRAnswer* p_pPTRAnswers); bool _processPTRAnswer(const clsRRAnswerPTR* p_pPTRAnswer, bool& p_rbFoundNewKeyAnswer); bool _processSRVAnswer(const clsRRAnswerSRV* p_pSRVAnswer, @@ -1477,9 +1480,10 @@ class clsLEAMDNSHost bool p_bAnnounce = true); // QUERY CACHE - bool _checkQueryCache(void); + bool _checkQueryCache(netif* pNetIf); - uint32_t _replyMaskForHost(const clsRRHeader& p_RRHeader, + uint32_t _replyMaskForHost(netif* pNetIf, + const clsRRHeader& p_RRHeader, bool* p_pbFullNameMatch = 0) const; uint32_t _replyMaskForService(const clsRRHeader& p_RRHeader, clsService& p_rService, @@ -1492,7 +1496,7 @@ class clsLEAMDNSHost bool _sendMessage_Multicast(netif* pNetIf, clsSendParameter& p_rSendParameter, uint8_t p_IPProtocolTypes); - bool _prepareMessage(clsSendParameter& p_SendParameter); + bool _prepareMessage(netif* pNetIf, clsSendParameter& p_SendParameter); bool _addQueryRecord(clsSendParameter& p_rSendParameter, const clsRRDomain& p_QueryDomain, uint16_t p_u16QueryType); @@ -1504,7 +1508,8 @@ class clsLEAMDNSHost uint16_t p_u16RecordType, clsQuery::clsAnswer::list* p_pKnownAnswers = 0); - IPAddress _getResponderIPAddress(enuIPProtocolType p_IPProtocolType) const; + IPAddress _getResponderIPAddress(netif* pNetIf, + enuIPProtocolType p_IPProtocolType) const; // RESOURCE RECORD bool _readRRQuestion(clsRRQuestion& p_rQuestion); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index 48eba00b0d..d4e592843c 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -44,7 +44,7 @@ namespace experimental clsLEAmDNS2_Host::_parseMessage */ -bool clsLEAMDNSHost::_parseMessage(void) +bool clsLEAMDNSHost::_parseMessage() { DEBUG_EX_INFO( unsigned long ulStartTime = millis(); @@ -54,6 +54,7 @@ bool clsLEAMDNSHost::_parseMessage(void) m_pUDPContext->getDestAddress().toString().c_str()); ); //DEBUG_EX_INFO(_udpDump();); + netif* pNetIf = m_pUDPContext->getInputNetif(); bool bResult = false; @@ -76,7 +77,7 @@ bool clsLEAMDNSHost::_parseMessage(void) { // Received a response -> answers to a query //DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: Reading answers: ID:%u, Q:%u, A:%u, NS:%u, AR:%u\n"), _DH(), header.m_u16ID, header.m_u16QDCount, header.m_u16ANCount, header.m_u16NSCount, header.m_u16ARCount);); - bResult = _parseResponse(header); + bResult = _parseResponse(pNetIf, header); } else { @@ -135,7 +136,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, // Define host replies, BUT only answer queries after probing is done u32HostOrServiceReplies = sendParameter.m_u32HostReplyMask |= ((probeStatus()) - ? _replyMaskForHost(questionRR.m_Header, 0) + ? _replyMaskForHost(pNetIf, questionRR.m_Header, 0) : 0); DEBUG_EX_INFO(if (u32HostOrServiceReplies) DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Host reply needed %s\n"), _DH(), _replyFlags2String(u32HostOrServiceReplies));); @@ -143,7 +144,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, if (clsProbeInformation_Base::clsProbeInformation_Base::enuProbingStatus::InProgress == m_ProbeInformation.m_ProbingStatus) { bool bFullNameMatch = false; - if ((_replyMaskForHost(questionRR.m_Header, &bFullNameMatch)) && + if ((_replyMaskForHost(pNetIf, questionRR.m_Header, &bFullNameMatch)) && (bFullNameMatch)) { // We're in 'probing' state and someone is asking for our host domain: this might be @@ -282,7 +283,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, { /* - RFC6762 7.1 Suppression only for 'Shared Records' - // Find match between planned answer (sendParameter.m_u8HostReplyMask) and this 'known answer' - uint32_t u32HostMatchMask = (sendParameter.m_u32HostReplyMask & _replyMaskForHost(pKnownRRAnswer->m_Header)); + uint32_t u32HostMatchMask = (sendParameter.m_u32HostReplyMask & _replyMaskForHost(pNetIf, pKnownRRAnswer->m_Header)); if ((u32HostMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND ((Consts::u32HostTTL / 2) <= pKnownRRAnswer->m_u32TTL)) // The TTL of the known answer is longer than half of the new host TTL (120s) { @@ -318,7 +319,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, // IPv4 address was asked for #ifdef MDNS_IPV4_SUPPORT if ((enuAnswerType::A == pKnownRRAnswer->answerType()) && - (((stcRRAnswerA*)pKnownRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V4))) + (((stcRRAnswerA*)pKnownRRAnswer)->m_IPAddress == _getResponderIPAddress(pNetIf, enuIPProtocolType::V4))) { DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: IPv4 address already known (TTL:%u)... skipping!\n"), _DH(), pKnownRRAnswer->m_u32TTL);); @@ -331,7 +332,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, // IPv6 address was asked for #ifdef MDNS_IPV6_SUPPORT if ((enuAnswerType::AAAA == pKnownRRAnswer->answerType()) && - (((stcRRAnswerAAAA*)pKnownRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V6))) + (((stcRRAnswerAAAA*)pKnownRRAnswer)->m_IPAddress == _getResponderIPAddress(pNetIf, enuIPProtocolType::V6))) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: IPv6 address already known... skipping!\n"), _DH());); @@ -355,7 +356,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, if (enuAnswerType::A == pKnownRRAnswer->answerType()) { // CHECK - IPAddress localIPAddress(_getResponderIPAddress(enuIPProtocolType::V4)); + IPAddress localIPAddress(_getResponderIPAddress(pNetIf, enuIPProtocolType::V4)); if (((clsRRAnswerA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) { // SAME IP address -> We've received an old message from ourselfs (same IP) @@ -383,7 +384,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, #ifdef MDNS_IPV6_SUPPORT if (enuAnswerType::AAAA == pKnownRRAnswer->answerType()) { - IPAddress localIPAddress(_getResponderIPAddress(enuIPProtocolType::V6)); + IPAddress localIPAddress(_getResponderIPAddress(pNetIf, enuIPProtocolType::V6)); if (((clsRRAnswerAAAA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) { // SAME IP address -> We've received an old message from ourselfs (same IP) @@ -608,7 +609,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, TXT - links the instance name to services TXTs Level 3: A/AAAA - links the host domain to an IP address */ -bool clsLEAMDNSHost::_parseResponse(const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader) +bool clsLEAMDNSHost::_parseResponse(netif* pNetIf, const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse\n"));); //DEBUG_EX_INFO(_udpDump();); @@ -665,7 +666,7 @@ bool clsLEAMDNSHost::_parseResponse(const clsLEAMDNSHost::clsMsgHeader& p_MsgHea if (bResult) { bResult = ((!pCollectedRRAnswers) || - (_processAnswers(pCollectedRRAnswers))); + (_processAnswers(pNetIf, pCollectedRRAnswers))); } else // Some failure while reading answers { @@ -726,7 +727,7 @@ bool clsLEAMDNSHost::_parseResponse(const clsLEAMDNSHost::clsMsgHeader& p_MsgHea TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 */ -bool clsLEAMDNSHost::_processAnswers(const clsLEAMDNSHost::clsRRAnswer* p_pAnswers) +bool clsLEAMDNSHost::_processAnswers(netif* pNetIf, const clsLEAMDNSHost::clsRRAnswer* p_pAnswers) { bool bResult = false; @@ -796,14 +797,14 @@ bool clsLEAMDNSHost::_processAnswers(const clsLEAMDNSHost::clsRRAnswer* p_pAnswe bool bPossibleEcho = false; #ifdef MDNS_IPV4_SUPPORT if ((enuAnswerType::A == pRRAnswer->answerType()) && - (((clsRRAnswerA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V4))) + (((clsRRAnswerA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(pNetIf, enuIPProtocolType::V4))) { bPossibleEcho = true; } #endif #ifdef MDNS_IPV6_SUPPORT if ((enuAnswerType::AAAA == pRRAnswer->answerType()) && - (((clsRRAnswerAAAA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(enuIPProtocolType::V6))) + (((clsRRAnswerAAAA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(pNetIf, enuIPProtocolType::V6))) { bPossibleEcho = true; } @@ -1291,13 +1292,13 @@ bool clsLEAMDNSHost::_updateProbeStatus(netif* pNetIf) if ((clsProbeInformation_Base::enuProbingStatus::ReadyToStart == m_ProbeInformation.m_ProbingStatus) && // Ready to get started AND (( #ifdef MDNS_IPV4_SUPPORT - _getResponderIPAddress(enuIPProtocolType::V4).isSet() // AND has IPv4 address + _getResponderIPAddress(pNetIf, enuIPProtocolType::V4).isSet() // AND has IPv4 address #else true #endif ) || ( #ifdef MDNS_IPV6_SUPPORT - _getResponderIPAddress(enuIPProtocolType::V6).isSet() // OR has IPv6 address + _getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet() // OR has IPv6 address #else true #endif @@ -1340,7 +1341,7 @@ bool clsLEAMDNSHost::_updateProbeStatus(netif* pNetIf) else if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == m_ProbeInformation.m_ProbingStatus) && (m_ProbeInformation.m_Timeout.expired())) { - if ((bResult = _announce(true, false))) + if ((bResult = _announce(pNetIf, true, false))) { // Don't announce services here ++m_ProbeInformation.m_u8SentCount; // 1.. @@ -1405,7 +1406,7 @@ bool clsLEAMDNSHost::_updateProbeStatus(netif* pNetIf) (pService->m_ProbeInformation.m_Timeout.expired())) { // Probing already finished OR waiting for next time slot - if ((bResult = _announceService(*pService))) + if ((bResult = _announceService(pNetIf, *pService))) { // Announce service ++pService->m_ProbeInformation.m_u8SentCount; // 1.. @@ -1771,7 +1772,7 @@ bool clsLEAMDNSHost::_announceService(netif* pNetIf, When no update arrived (in time), the component is removed from the answer (cache). */ -bool clsLEAMDNSHost::_checkQueryCache(void) +bool clsLEAMDNSHost::_checkQueryCache(netif* pNetIf) { bool bResult = true; @@ -1786,7 +1787,7 @@ bool clsLEAMDNSHost::_checkQueryCache(void) if ((!pQuery->m_bStaticQuery) && (pQuery->m_ResendTimeout.expired())) { - if ((bResult = _sendQuery(*pQuery))) + if ((bResult = _sendQuery(pNetIf, *pQuery))) { // The re-query rate is increased to more than one hour (RFC 6762 5.2) ++pQuery->m_u8SentCount; @@ -1819,7 +1820,7 @@ bool clsLEAMDNSHost::_checkQueryCache(void) { if (!pQAnswer->m_TTLServiceDomain.finalTimeoutLevel()) { - bResult = ((_sendQuery(*pQuery)) && + bResult = ((_sendQuery(pNetIf, *pQuery)) && (pQAnswer->m_TTLServiceDomain.restart())); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: PTR update scheduled for "), _DH()); @@ -1851,7 +1852,7 @@ bool clsLEAMDNSHost::_checkQueryCache(void) { if (!pQAnswer->m_TTLHostDomainAndPort.finalTimeoutLevel()) { - bResult = ((_sendQuery(pQAnswer->m_ServiceDomain, DNS_RRTYPE_SRV)) && + bResult = ((_sendQuery(pNetIf, pQAnswer->m_ServiceDomain, DNS_RRTYPE_SRV)) && (pQAnswer->m_TTLHostDomainAndPort.restart())); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: SRV update scheduled for "), _DH()); @@ -1897,7 +1898,7 @@ bool clsLEAMDNSHost::_checkQueryCache(void) { if (!pQAnswer->m_TTLTxts.finalTimeoutLevel()) { - bResult = ((_sendQuery(pQAnswer->m_ServiceDomain, DNS_RRTYPE_TXT)) && + bResult = ((_sendQuery(pNetIf, pQAnswer->m_ServiceDomain, DNS_RRTYPE_TXT)) && (pQAnswer->m_TTLTxts.restart())); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: TXT update scheduled for "), _DH()); @@ -1940,7 +1941,7 @@ bool clsLEAMDNSHost::_checkQueryCache(void) { // Needs update if ((bAUpdateQuerySent) || - ((bResult = _sendQuery(pQAnswer->m_HostDomain, DNS_RRTYPE_A)))) + ((bResult = _sendQuery(pNetIf, pQAnswer->m_HostDomain, DNS_RRTYPE_A)))) { pIPv4Address->m_TTL.restart(); bAUpdateQuerySent = true; @@ -1993,7 +1994,7 @@ bool clsLEAMDNSHost::_checkQueryCache(void) { // Needs update if ((bAAAAUpdateQuerySent) || - ((bResult = _sendQuery(pQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) + ((bResult = _sendQuery(pNetIf, pQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) { pIPv6Address->m_TTL.restart(); bAAAAUpdateQuerySent = true; @@ -2056,7 +2057,8 @@ bool clsLEAMDNSHost::_checkQueryCache(void) In addition, a full name match (question domain == host domain) is marked. */ -uint32_t clsLEAMDNSHost::_replyMaskForHost(const clsLEAMDNSHost::clsRRHeader& p_RRHeader, +uint32_t clsLEAMDNSHost::_replyMaskForHost(netif* pNetIf, + const clsLEAMDNSHost::clsRRHeader& p_RRHeader, bool* p_pbFullNameMatch /*= 0*/) const { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _replyMaskForHost\n"));); @@ -2074,8 +2076,8 @@ uint32_t clsLEAMDNSHost::_replyMaskForHost(const clsLEAMDNSHost::clsRRHeader& p_ // PTR request #ifdef MDNS_IPV4_SUPPORT clsRRDomain reverseIPv4Domain; - if ((_getResponderIPAddress(enuIPProtocolType::V4).isSet()) && - (_buildDomainForReverseIPv4(_getResponderIPAddress(enuIPProtocolType::V4), reverseIPv4Domain)) && + if ((_getResponderIPAddress(pNetIf, enuIPProtocolType::V4).isSet()) && + (_buildDomainForReverseIPv4(_getResponderIPAddress(pNetIf, enuIPProtocolType::V4), reverseIPv4Domain)) && (p_RRHeader.m_Domain == reverseIPv4Domain)) { // Reverse domain match @@ -2084,8 +2086,8 @@ uint32_t clsLEAMDNSHost::_replyMaskForHost(const clsLEAMDNSHost::clsRRHeader& p_ #endif #ifdef MDNS_IPV6_SUPPORT clsRRDomain reverseIPv6Domain; - if ((_getResponderIPAddress(enuIPProtocolType::V6).isSet()) && - (_buildDomainForReverseIPv6(_getResponderIPAddress(enuIPProtocolType::V6), reverseIPv6Domain)) && + if ((_getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet()) && + (_buildDomainForReverseIPv6(_getResponderIPAddress(pNetIf, enuIPProtocolType::V6), reverseIPv6Domain)) && (p_RRHeader.m_Domain == reverseIPv6Domain)) { // Reverse domain match diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 1d1a4df1b1..df34f81787 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -94,7 +94,7 @@ bool clsLEAMDNSHost::_sendMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParamete DEBUG_EX_ERR(if (!ipRemote.isSet()) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage: MISSING remote address for unicast response!\n"), _DH());); bResult = ((ipRemote.isSet()) && - (_prepareMessage(p_rSendParameter)) && + (_prepareMessage(pNetIf, p_rSendParameter)) && (m_pUDPContext->send(ipRemote, m_pUDPContext->getRemotePort())) /*&& (Serial.println("Did send UC"), true)*/); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage (V4): FAILED!\n"), _DH());); @@ -165,7 +165,7 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast IPv4: Will send to '%s'.\n"), _DH(), ip4MulticastAddress.toString().c_str());); DEBUG_EX_INFO(if (!_getResponderIPAddress(pNetIf, enuIPProtocolType::V4)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast IPv4: NO IPv4 address!.\n"), _DH());); - bIPv4Result = ((_prepareMessage(p_rSendParameter)) && + bIPv4Result = ((_prepareMessage(pNetIf, p_rSendParameter)) && (m_pUDPContext->setMulticastInterface(pNetIf), true) && (m_pUDPContext->send(ip4MulticastAddress, DNS_MQUERY_PORT)) && (m_pUDPContext->setMulticastInterface(0), true) /*&& @@ -191,7 +191,7 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe bool bPrepareMessage = false; bool bUDPContextSend = false; ); - bIPv6Result = ((DEBUG_EX_ERR(bPrepareMessage =)_prepareMessage(p_rSendParameter)) && + bIPv6Result = ((DEBUG_EX_ERR(bPrepareMessage =)_prepareMessage(pNetIf, p_rSendParameter)) && (m_pUDPContext->setMulticastInterface(pNetIf), true) && (DEBUG_EX_ERR(bUDPContextSend =)m_pUDPContext->send(ip6MulticastAddress, DNS_MQUERY_PORT)) && (m_pUDPContext->setMulticastInterface(0), true) /*&& @@ -220,7 +220,7 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe output buffer. */ -bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParameter) +bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage\n"));); bool bResult = true; @@ -314,25 +314,25 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa // AAAA if ((bResult) && (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::AAAA)) && - (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6).isSet())) + (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)).isSet())) { u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16Answers - : (bResult = _writeMDNSAnswer_AAAA(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6), p_rSendParameter))); + : (bResult = _writeMDNSAnswer_AAAA(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)), p_rSendParameter))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_AAAA(A) FAILED!\n"), _DH());); } // PTR_IPv6 if ((bResult) && (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv6)) && - (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6).isSet())) + (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)).isSet())) { u32NSECContent |= static_cast<uint32_t>(enuContentFlag::PTR_IPv6); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16Answers - : (bResult = _writeMDNSAnswer_PTR_IPv6(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6), p_rSendParameter))); + : (bResult = _writeMDNSAnswer_PTR_IPv6(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)), p_rSendParameter))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_PTR_IPv6 FAILED!\n"), _DH());); } #endif @@ -446,13 +446,13 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa // Answer A needed? if ((bResult) && (bNeedsAdditionalAnswerA) && - (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4).isSet())) + (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4)).isSet())) { // Additional A u32NSECContent |= static_cast<uint32_t>(enuContentFlag::A); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16AdditionalAnswers - : (bResult = _writeMDNSAnswer_A(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4), p_rSendParameter))); + : (bResult = _writeMDNSAnswer_A(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4)), p_rSendParameter))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_A(B) FAILED!\n"), _DH());); } @@ -461,13 +461,13 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa // Answer AAAA needed? if ((bResult) && (bNeedsAdditionalAnswerAAAA) && - (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6).isSet())) + (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)).isSet())) { // Additional AAAA u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16AdditionalAnswers - : (bResult = _writeMDNSAnswer_AAAA(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6), p_rSendParameter))); + : (bResult = _writeMDNSAnswer_AAAA(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)), p_rSendParameter))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_AAAA(B) FAILED!\n"), _DH());); } @@ -503,24 +503,24 @@ bool clsLEAMDNSHost::_prepareMessage(clsLEAMDNSHost::clsSendParameter& p_rSendPa #ifdef MDNS_IPV4_SUPPORT // Write separate answer for host PTR IPv4 && ((!u32NSECContent_PTR_IPv4) || - ((!_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4).isSet()) || - (_writeMDNSAnswer_NSEC_PTR_IPv4(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4), p_rSendParameter)))) + ((!_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4)).isSet()) || + (_writeMDNSAnswer_NSEC_PTR_IPv4(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4)), p_rSendParameter)))) #endif #ifdef MDNS_IPV6_SUPPORT // Write separate answer for host PTR IPv6 && ((!u32NSECContent_PTR_IPv6) || - ((!_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6).isSet()) || - (_writeMDNSAnswer_NSEC_PTR_IPv6(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6), p_rSendParameter)))) + ((!_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)).isSet()) || + (_writeMDNSAnswer_NSEC_PTR_IPv6(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)), p_rSendParameter)))) #endif ))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_NSEC(Host) FAILED!\n"), _DH());); } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: Loop %i FAILED!\n"), _DH(), sequence);); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: Loop %i FAILED!\n"), _DH(), sequence);); } // for sequence - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: FAILED!\n"), _DH());); - return bResult; + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: FAILED!\n"), _DH());); + return bResult; } /* diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 551a754cdf..0c0be01906 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -120,17 +120,17 @@ bool clsLEAMDNSHost_Legacy::addHostForNetIf(const char* p_pcHostname) { bool bResult = true; - if (m_HostInformations.length() > 0) + if (m_HostInformations.size() > 0) { //XXXFIXME only one pHost instance, many things can be simplified bResult = false; } else { - clsLEAMDNSHost* pHost = &esp8266::experimental::clsLEAMDNSHost::clsBackbone::sm_pBackbone.m_uniqueHost; - - if ((!((pHost->begin(p_pcHostname /*, default callback*/)) - && (m_HostInformations.push_back(stcHostInformation(pHost)), true)))) + clsLEAMDNSHost* pHost = new esp8266::experimental::clsLEAMDNSHost; + if (pHost + && (!((pHost->begin(p_pcHostname /*, default callback*/)) + && (m_HostInformations.push_back(stcHostInformation(pHost)), true)))) { bResult = false; } From 6646acba392d7f7e930f829004428bba29e7352d Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Mon, 25 May 2020 12:10:20 +0200 Subject: [PATCH 019/152] wip - compilation OK - not tested --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 24 +++-- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 46 +++++---- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 96 +++++++++---------- .../ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 46 ++++----- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 39 +++++--- 5 files changed, 137 insertions(+), 114 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 7f53746038..706cd94006 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -432,11 +432,11 @@ bool clsLEAMDNSHost::removeService(clsLEAMDNSHost::clsService* p_pService) bool bResult = false; if (p_pService && - (m_Services.end() != std::find(m_Services.begin(), m_Services.end(), p_pService))) + (m_Services.end() != std::find(m_Services.begin(), m_Services.end(), p_pService))) { for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf) && - (_announceService(pNetIf, *p_pService, false))) + (_announceService(pNetIf, *p_pService, false))) { bResult = true; } @@ -677,7 +677,8 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::getQuery(void) */ /*clsLEAMDNSHost::clsQuery* */ bool clsLEAMDNSHost::installServiceQuery(const char* p_pcService, const char* p_pcProtocol, - clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) + clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor, + std::list<clsLEAMDNSHost::clsQuery*>* ret) { bool bResult = false; clsQuery* pQuery = 0; @@ -686,6 +687,10 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::getQuery(void) { pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; bResult = true; + if (ret) + { + ret->push_back(pQuery); + } } return bResult; } @@ -741,16 +746,13 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::getQuery(void) /* clsLEAmDNS2_Host::removeQuery */ -/* - bool clsLEAMDNSHost::removeQuery(clsLEAMDNSHost::clsQuery * p_pMDNSQuery) - { +bool clsLEAMDNSHost::removeQuery(clsLEAMDNSHost::clsQuery * p_pMDNSQuery) +{ bool bResult = ((p_pMDNSQuery) && (_removeQuery(p_pMDNSQuery))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s removeQuery: FAILED!\n"), _DH());); return bResult; - } -*/ - +} /* PROCESSING @@ -790,7 +792,9 @@ bool clsLEAMDNSHost::announce(bool p_bAnnounce /*= true*/, bool bResult = false; for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf) && _announce(pNetIf, p_bAnnounce, p_bIncludeServices)) + { bResult = true; + } return bResult; } @@ -803,7 +807,9 @@ bool clsLEAMDNSHost::announceService(clsService * p_pService, bool bResult = false; for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf) && _announceService(pNetIf, *p_pService, p_bAnnounce)) + { bResult = true; + } return bResult; } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 6ef6aa69da..ab5dd4003c 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -293,8 +293,11 @@ class clsLEAMDNSHost bool removeHost(clsLEAMDNSHost* p_pHost); size_t hostCount(void) const; bool setDelayUDPProcessing(bool p_bDelayProcessing); - - clsLEAMDNSHost* getUniqueHost() { return m_uniqueHost; } + + clsLEAMDNSHost* getUniqueHost() + { + return m_uniqueHost; + } protected: UdpContext* m_pUDPContext; @@ -308,8 +311,14 @@ class clsLEAMDNSHost bool _processUDPInput(void); - const clsLEAMDNSHost* _findHost() const { return m_uniqueHost; } - clsLEAMDNSHost* _findHost() { return m_uniqueHost; } + const clsLEAMDNSHost* _findHost() const + { + return m_uniqueHost; + } + clsLEAMDNSHost* _findHost() + { + return m_uniqueHost; + } const char* _DH(void) const; }; @@ -1330,23 +1339,24 @@ class clsLEAMDNSHost // - hasAnswerIPv6Address/answerIPv6Address service/host // - hasAnswerPort/answerPort service // - hasAnswerTxts/answerTxts service - + /* - install*Query() creates several queries on the interfaces. - it no more returns a single query but a boolean until the API is adapted + install*Query() creates several queries on the interfaces. + it no more returns a single query but a boolean until the API is adapted */ - /*clsQuery**/bool installServiceQuery(const char* p_pcServiceType, - const char* p_pcProtocol, - clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); - /*clsQuery**/bool installServiceQuery(const char* p_pcServiceType, - const char* p_pcProtocol, - clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); - /*clsQuery**/bool installHostQuery(const char* p_pcHostName, - clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); - /*clsQuery**/bool installHostQuery(const char* p_pcHostName, - clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); + /*clsQuery* */bool installServiceQuery(const char* p_pcServiceType, + const char* p_pcProtocol, + clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); + /*clsQuery* */bool installServiceQuery(const char* p_pcServiceType, + const char* p_pcProtocol, + clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor, + std::list<clsQuery*>* ret = nullptr); + /*clsQuery* */bool installHostQuery(const char* p_pcHostName, + clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); + /*clsQuery* */bool installHostQuery(const char* p_pcHostName, + clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); // Remove a dynamic service query - /*bool removeQuery(clsQuery* p_pQuery);*/ + bool removeQuery(clsQuery* p_pQuery); // PROCESSING bool update(void); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index df34f81787..72fe253730 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -315,34 +315,34 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam if ((bResult) && (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::AAAA)) && (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)).isSet())) - { + { - u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16Answers : (bResult = _writeMDNSAnswer_AAAA(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)), p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_AAAA(A) FAILED!\n"), _DH());); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_AAAA(A) FAILED!\n"), _DH());); } - // PTR_IPv6 - if ((bResult) && + // PTR_IPv6 + if ((bResult) && (p_rSendParameter.m_u32HostReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_IPv6)) && (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)).isSet())) - { + { - u32NSECContent |= static_cast<uint32_t>(enuContentFlag::PTR_IPv6); + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::PTR_IPv6); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16Answers : (bResult = _writeMDNSAnswer_PTR_IPv6(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)), p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_PTR_IPv6 FAILED!\n"), _DH());); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_PTR_IPv6 FAILED!\n"), _DH());); } #endif - for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) - { - clsService* pService = *it; + for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) + { + clsService* pService = *it; - // PTR_TYPE - if ((bResult) && + // PTR_TYPE + if ((bResult) && (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_TYPE))) { ((static_cast<typeSequence>(enuSequence::Count) == sequence) @@ -383,16 +383,16 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam uint16_t& ru16AdditionalAnswers = msgHeader.m_u16ARCount; #ifdef MDNS_IPV4_SUPPORT - bool bNeedsAdditionalAnswerA = false; + bool bNeedsAdditionalAnswerA = false; #endif #ifdef MDNS_IPV6_SUPPORT - bool bNeedsAdditionalAnswerAAAA = false; + bool bNeedsAdditionalAnswerAAAA = false; #endif - for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) - { - clsService* pService = *it; + for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) + { + clsService* pService = *it; - if ((bResult) && + if ((bResult) && (pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::PTR_NAME)) && // If PTR_NAME is requested, AND (!(pService->m_u32ReplyMask & static_cast<uint32_t>(enuContentFlag::SRV)))) // NOT SRV -> add SRV as additional answer { @@ -447,40 +447,40 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam if ((bResult) && (bNeedsAdditionalAnswerA) && (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4)).isSet())) - { - // Additional A - u32NSECContent |= static_cast<uint32_t>(enuContentFlag::A); + { + // Additional A + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::A); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16AdditionalAnswers : (bResult = _writeMDNSAnswer_A(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4)), p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_A(B) FAILED!\n"), _DH());); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_A(B) FAILED!\n"), _DH());); } #endif #ifdef MDNS_IPV6_SUPPORT - // Answer AAAA needed? - if ((bResult) && + // Answer AAAA needed? + if ((bResult) && (bNeedsAdditionalAnswerAAAA) && (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)).isSet())) - { - // Additional AAAA - u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); + { + // Additional AAAA + u32NSECContent |= static_cast<uint32_t>(enuContentFlag::AAAA); ((static_cast<typeSequence>(enuSequence::Count) == sequence) ? ++ru16AdditionalAnswers : (bResult = _writeMDNSAnswer_AAAA(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)), p_rSendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_AAAA(B) FAILED!\n"), _DH());); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_AAAA(B) FAILED!\n"), _DH());); } #endif - // NSEC host (part 2) - if ((bResult) && + // NSEC host (part 2) + if ((bResult) && ((clsSendParameter::enuResponseType::None != p_rSendParameter.m_Response)) && (u32NSECContent)) - { - // NSEC PTR IPv4/IPv6 are separate answers; make sure, that this is counted for + { + // NSEC PTR IPv4/IPv6 are separate answers; make sure, that this is counted for #ifdef MDNS_IPV4_SUPPORT - uint32_t u32NSECContent_PTR_IPv4 = (u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)); + uint32_t u32NSECContent_PTR_IPv4 = (u32NSECContent & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)); u32NSECContent &= ~static_cast<uint32_t>(enuContentFlag::PTR_IPv4); #endif #ifdef MDNS_IPV6_SUPPORT @@ -504,17 +504,17 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam // Write separate answer for host PTR IPv4 && ((!u32NSECContent_PTR_IPv4) || ((!_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4)).isSet()) || - (_writeMDNSAnswer_NSEC_PTR_IPv4(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4)), p_rSendParameter)))) + (_writeMDNSAnswer_NSEC_PTR_IPv4(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4)), p_rSendParameter)))) #endif #ifdef MDNS_IPV6_SUPPORT - // Write separate answer for host PTR IPv6 - && ((!u32NSECContent_PTR_IPv6) || - ((!_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)).isSet()) || - (_writeMDNSAnswer_NSEC_PTR_IPv6(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)), p_rSendParameter)))) + // Write separate answer for host PTR IPv6 + && ((!u32NSECContent_PTR_IPv6) || + ((!_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)).isSet()) || + (_writeMDNSAnswer_NSEC_PTR_IPv6(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)), p_rSendParameter)))) #endif - ))); + ))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_NSEC(Host) FAILED!\n"), _DH());); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: _writeMDNSAnswer_NSEC(Host) FAILED!\n"), _DH());); } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: Loop %i FAILED!\n"), _DH(), sequence);); @@ -523,15 +523,15 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam return bResult; } - /* - MDNSResponder::_addQueryRecord +/* + MDNSResponder::_addQueryRecord - Adds a query for the given domain and query type. + Adds a query for the given domain and query type. - */ - bool clsLEAMDNSHost::_addQueryRecord(clsLEAMDNSHost::clsSendParameter& p_rSendParameter, - const clsLEAMDNSHost::clsRRDomain& p_QueryDomain, - uint16_t p_u16RecordType) +*/ +bool clsLEAMDNSHost::_addQueryRecord(clsLEAMDNSHost::clsSendParameter& p_rSendParameter, + const clsLEAMDNSHost::clsRRDomain& p_QueryDomain, + uint16_t p_u16RecordType) { bool bResult = false; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index 2898bec218..a382f071a1 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -104,7 +104,7 @@ bool clsLEAMDNSHost::clsBackbone::removeHost(clsLEAMDNSHost* p_pHost) */ size_t clsLEAMDNSHost::clsBackbone::hostCount(void) const { - return m_uniqueHost == nullptr? 0: 1; + return m_uniqueHost == nullptr ? 0 : 1; } /* @@ -215,33 +215,23 @@ bool clsLEAMDNSHost::clsBackbone::_processUDPInput(void) while ((m_pUDPContext) && (m_pUDPContext->next())) { - netif* pNetIf = m_pUDPContext->getInputNetif(); - clsLEAMDNSHost* pHost = 0; - if ((pHost = _findHost())) - { - DEBUG_EX_INFO_IF(u32LoopCounter++, - DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Multi-Loop (%u)!\n"), _DH(), u32LoopCounter); - DEBUG_EX_INFO_IF((remoteIPAddr.isSet()) && (remoteIPAddr != m_pUDPContext->getRemoteAddress()), - DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Changed IP address %s->%s!\n"), - _DH(), - remoteIPAddr.toString().c_str(), - m_pUDPContext->getRemoteAddress().toString().c_str()))); - DEBUG_EX_INFO(remoteIPAddr = m_pUDPContext->getRemoteAddress()); - - bResult = pHost->_processUDPInput(); - - DEBUG_EX_INFO2_IF(!bResult, - DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: FAILED to process UDP input!\n"), _DH())); - DEBUG_EX_ERR_IF((-1) != m_pUDPContext->peek(), - DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: !!!! CONTENT LEFT IN UDP BUFFER !!!!\n"), - _DH())); - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Received UDP datagramm for unused netif at index: %u\n"), - _DH(), - (pNetIf ? netif_get_index(pNetIf) : (-1)))); - } + clsLEAMDNSHost* pHost = _findHost(); + DEBUG_EX_INFO_IF(u32LoopCounter++, + DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Multi-Loop (%u)!\n"), _DH(), u32LoopCounter); + DEBUG_EX_INFO_IF((remoteIPAddr.isSet()) && (remoteIPAddr != m_pUDPContext->getRemoteAddress()), + DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Changed IP address %s->%s!\n"), + _DH(), + remoteIPAddr.toString().c_str(), + m_pUDPContext->getRemoteAddress().toString().c_str()))); + DEBUG_EX_INFO(remoteIPAddr = m_pUDPContext->getRemoteAddress()); + + bResult = pHost->_processUDPInput(); + + DEBUG_EX_INFO2_IF(!bResult, + DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: FAILED to process UDP input!\n"), _DH())); + DEBUG_EX_ERR_IF((-1) != m_pUDPContext->peek(), + DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: !!!! CONTENT LEFT IN UDP BUFFER !!!!\n"), + _DH())); m_pUDPContext->flush(); } } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 0c0be01906..ca15775eba 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -119,7 +119,7 @@ bool clsLEAMDNSHost_Legacy::end(void) bool clsLEAMDNSHost_Legacy::addHostForNetIf(const char* p_pcHostname) { bool bResult = true; - + if (m_HostInformations.size() > 0) { //XXXFIXME only one pHost instance, many things can be simplified @@ -129,8 +129,8 @@ bool clsLEAMDNSHost_Legacy::addHostForNetIf(const char* p_pcHostname) { clsLEAMDNSHost* pHost = new esp8266::experimental::clsLEAMDNSHost; if (pHost - && (!((pHost->begin(p_pcHostname /*, default callback*/)) - && (m_HostInformations.push_back(stcHostInformation(pHost)), true)))) + && (!((pHost->begin(p_pcHostname /*, default callback*/)) + && (m_HostInformations.push_back(stcHostInformation(pHost)), true)))) { bResult = false; } @@ -788,24 +788,41 @@ clsLEAMDNSHost_Legacy::hMDNSServiceQuery clsLEAMDNSHost_Legacy::installServiceQu for (stcHostInformation& hostInformation : m_HostInformations) { - clsLEAMDNSHost::clsQuery* pQuery = hostInformation.m_pHost->installServiceQuery(p_pcService, p_pcProtocol, [this, p_fnCallback](const clsLEAMDNSHost::clsQuery& /*p_Query*/, - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor & p_AnswerAccessor, - clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item - bool p_bSetContent)->void + std::list<clsLEAMDNSHost::clsQuery*> queries; + + /*clsLEAMDNSHost::clsQuery* pQuery =*/ + hostInformation.m_pHost->installServiceQuery(p_pcService, p_pcProtocol, [this, p_fnCallback](const clsLEAMDNSHost::clsQuery& /*p_Query*/, + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor & p_AnswerAccessor, + clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)->void { if (p_fnCallback) // void(const stcMDNSServiceInfo& p_MDNSServiceInfo, MDNSResponder::AnswerType p_AnswerType, bool p_bSetContent) { p_fnCallback(stcMDNSServiceInfo(p_AnswerAccessor), _answerFlagsToAnswerType(p_QueryAnswerTypeFlags), p_bSetContent); } - }); - if (pQuery) + }, &queries); + + if (queries.size()) { if (!hResult) { + // - hMDNSServiceQuery handle is 'const void*' + // used to retrieve pQuery when updating or removing. + + // - unexplained - before multi interface change: + // there is a loop, only the first is returned, why ? + // Store first query as result and key - hResult = (hMDNSServiceQuery)pQuery; + //hResult = (hMDNSServiceQuery)pQuery; <- before netif, only the first query is returned + + // - netif transformation: even more returned values (a list per loop), + // still, only the first handle is returned. + hResult = (hMDNSServiceQuery) * queries.begin(); // take the first } - hostInformation.m_HandleToPtr[hResult] = pQuery; + // this was overwritten ? + //hostInformation.m_HandleToPtr[hResult] = pQuery; + // ... overwritten with only the first query + hostInformation.m_HandleToPtr[hResult] = *queries.begin(); } } return hResult; From eae8b4d1c109d8382374ecfaeac6ac49a3386748 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Mon, 25 May 2020 15:32:14 +0200 Subject: [PATCH 020/152] wip --- cores/esp8266/IPAddress.h | 7 +++++-- libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 6 +++++- libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 3 ++- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 11 +++++++++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/cores/esp8266/IPAddress.h b/cores/esp8266/IPAddress.h index 327c61f997..abced22db4 100644 --- a/cores/esp8266/IPAddress.h +++ b/cores/esp8266/IPAddress.h @@ -51,8 +51,11 @@ struct ip_addr: ipv4_addr { }; #endif // lwIP-v2+ // to display a netif id with printf: -#define NETIFID_STR "%c%c%d" -#define NETIFID_VAL(netif) (netif)->name[0], (netif)->name[1], netif_get_index((netif)) +#define NETIFID_STR "%c%c%u" +#define NETIFID_VAL(netif) \ + ((netif)? (netif)->name[0]: '-'), \ + ((netif)? (netif)->name[1]: '-'), \ + ((netif)? netif_get_index(netif): 42) // A class to make it easier to handle and pass around IP addresses // IPv6 update: diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 72fe253730..0a3c23e2f5 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -53,8 +53,10 @@ namespace experimental bool clsLEAMDNSHost::_sendMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { bool bResult = false; - uint8_t u8AvailableProtocols = 0; + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage: if=" NETIFID_STR "\n"), _DH(), NETIFID_VAL(pNetIf))); + #ifdef MDNS_IPV4_SUPPORT // Only send out IPv4 messages, if we've got an IPv4 address if (_getResponderIPAddress(pNetIf, enuIPProtocolType::V4).isSet()) @@ -157,6 +159,8 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe { bool bIPv4Result = true; bool bIPv6Result = true; + + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast: if=" NETIFID_STR "\n"), _DH(), NETIFID_VAL(pNetIf))); #ifdef MDNS_IPV4_SUPPORT if (p_IPProtocolTypes & static_cast<uint8_t>(enuIPProtocolType::V4)) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index a382f071a1..d4ab972a30 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -41,7 +41,8 @@ namespace experimental clsLEAMDNSHost::clsBackbone::clsBackbone(void) : m_pUDPContext(0), m_bDelayUDPProcessing(false), - m_u32DelayedDatagrams(0) + m_u32DelayedDatagrams(0), + m_uniqueHost(0) { } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index ca15775eba..87ee6dc074 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -50,6 +50,17 @@ clsLEAMDNSHost_Legacy::~clsLEAMDNSHost_Legacy(void) */ +/* + clsLEAMDNSHost_Legacy::begin + +*/ +bool clsLEAMDNSHost_Legacy::begin(const char* p_pcHostname) +{ + return addHostForNetIf(p_pcHostname) + && (0 != m_HostInformations.size()); +} + + /* clsLEAMDNSHost_Legacy::begin (String) From 46f6d2b3a35acf16174d863f93bb3a5bfb45ba1f Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Mon, 25 May 2020 17:42:43 +0200 Subject: [PATCH 021/152] clockv2 example: ap + sta --- .../examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 12 +++++++++--- libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index 5c429226f4..76750ea47e 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -69,6 +69,11 @@ #define STAPSK "your-password" #endif +#ifndef APSSID +#define APSSID "ap4mdnsClock" +#define APPSK "mdnsClock" +#endif + const char* ssid = STASSID; const char* password = STAPSK; @@ -181,7 +186,8 @@ void setup(void) { Serial.begin(115200); // Connect to WiFi network - WiFi.mode(WIFI_STA); + WiFi.mode(WIFI_AP_STA); + WiFi.softAP(APSSID, APPSK); WiFi.begin(ssid, password); Serial.println(""); @@ -201,12 +207,12 @@ void setup(void) { // Setup MDNS responder // Init the (currently empty) host domain string with 'esp8266' - if (responder.begin("ESP8266", WIFI_STA, [](clsMDNSHost & p_rMDNSHost, + if (responder.begin("leamdnsv2", [](clsMDNSHost & p_rMDNSHost, const char* p_pcDomainName, bool p_bProbeResult)->void { Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); // Unattended added service - p_rMDNSHost.addService(0, "http", "tcp", 80); + p_rMDNSHost.addService(0, "espclk", "tcp", 80); })) { Serial.println("mDNS-AP started"); } else { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index d4e592843c..c8cf993ecb 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -226,7 +226,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, #endif ) { - Serial.println("\n\n\nUNICAST QUERY\n\n"); + DEBUG_EX_RX(DEBUG_OUTPUT.println("\n\n\nUNICAST QUERY\n\n")); DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Legacy DNS query from local host %s!\n"), _DH(), m_pUDPContext->getRemoteAddress().toString().c_str());); sendParameter.m_u16ID = p_MsgHeader.m_u16ID; @@ -248,7 +248,7 @@ bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, } else { - Serial.printf("\n\n\nINVALID UNICAST QUERY from %s\n\n\n", m_pUDPContext->getRemoteAddress().toString().c_str()); + DEBUG_EX_RX(DEBUG_OUTPUT.printf("\n\n\nINVALID UNICAST QUERY from %s\n\n\n", m_pUDPContext->getRemoteAddress().toString().c_str())); DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Legacy DNS query from NON-LOCAL host at %s!\n"), _DH(), m_pUDPContext->getRemoteAddress().toString().c_str());); bResult = false; } From 0a8187142caaeee33545c80ae385425ef49257ba Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Mon, 25 May 2020 18:16:05 +0200 Subject: [PATCH 022/152] style --- .../examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 4 ++-- libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index 76750ea47e..0a6ad00cfe 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -208,7 +208,7 @@ void setup(void) { // Setup MDNS responder // Init the (currently empty) host domain string with 'esp8266' if (responder.begin("leamdnsv2", [](clsMDNSHost & p_rMDNSHost, - const char* p_pcDomainName, + const char* p_pcDomainName, bool p_bProbeResult)->void { Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); // Unattended added service diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 706cd94006..f93315d8df 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -956,8 +956,8 @@ bool clsLEAMDNSHost::_joinMulticastGroups(void) ip_addr_t multicast_addr_V6 = DNS_MQUERY_IPV6_GROUP_INIT; bResult = ((bResult) && (ERR_OK == mld6_joingroup_netif(pNetIf, ip_2_ip6(&multicast_addr_V6)))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: mld6_joingroup_netif (" NETIFID_STR ") FAILED!\n"), - _DH(), NETIFID_VAL(pNetIf));); + DEBUG_EX_ERR_IF(!bResult, DEBUG_OUTPUT.printf_P(PSTR("%s _createHost: mld6_joingroup_netif (" NETIFID_STR ") FAILED!\n"), + _DH(), NETIFID_VAL(pNetIf))); #endif } return bResult; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 0a3c23e2f5..6e6f74d992 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -159,7 +159,7 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe { bool bIPv4Result = true; bool bIPv6Result = true; - + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast: if=" NETIFID_STR "\n"), _DH(), NETIFID_VAL(pNetIf))); #ifdef MDNS_IPV4_SUPPORT diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 87ee6dc074..910a8d5943 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -57,7 +57,7 @@ clsLEAMDNSHost_Legacy::~clsLEAMDNSHost_Legacy(void) bool clsLEAMDNSHost_Legacy::begin(const char* p_pcHostname) { return addHostForNetIf(p_pcHostname) - && (0 != m_HostInformations.size()); + && (0 != m_HostInformations.size()); } From b543f0312979b28c2324b4752e9ea39e28ca1176 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Mon, 25 May 2020 18:27:24 +0200 Subject: [PATCH 023/152] style --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index f93315d8df..801630e042 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -174,7 +174,8 @@ const char* clsLEAMDNSHost::indexDomainName(const char* p_pcDomainName, bool clsLEAMDNSHost::setNetIfHostName(const char* p_pcHostName) { if (p_pcHostName) - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf)) { netif_set_hostname(pNetIf, p_pcHostName); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[mDNS] setNetIfHostName host name: %s on " NETIFID_STR "!\n"), p_pcHostName, NETIFID_VAL(pNetIf));); @@ -920,7 +921,8 @@ bool clsLEAMDNSHost::_joinMulticastGroups(void) bool bResult = false; // Join multicast group(s) - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf)) { #ifdef MDNS_IPV4_SUPPORT ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; @@ -970,7 +972,8 @@ bool clsLEAMDNSHost::_leaveMulticastGroups() { bool bResult = false; - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf)) { bResult = true; /* _resetProbeStatus(false); // Stop probing From 41bd315e69efeeb07841def52be1ff613ab4aca8 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 28 May 2020 19:43:27 +0200 Subject: [PATCH 024/152] using experimental namespace for not-default v2+Legacy API --- libraries/ESP8266mDNS/src/ESP8266mDNS.h | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index 7b921817e7..54eeb42797 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -56,7 +56,7 @@ using clsMDNSHost = esp8266::experimental::clsLEAMDNSHost; // Maps the implementation to use to the global namespace type //using MDNSResponder = Legacy_MDNSResponder::MDNSResponder; // Legacy using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA -//using MDNSResponder = esp8266::MDNSImplementation::clsLEAMDNSHost_Legacy; // LEAv2Compat +//using MDNSResponder = experimental::MDNSImplementation::clsLEAMDNSHost_Legacy; // LEAv2Compat //using MDNSResponder = clsMDNSHost; // LEAv2 extern MDNSResponder MDNS; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h index 9ab1f14d0c..baab2b4a5d 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h @@ -105,7 +105,7 @@ #include "LEAmDNS2Host.h" -namespace esp8266 +namespace experimental { namespace MDNSImplementation @@ -689,7 +689,7 @@ class clsLEAMDNSHost_Legacy } // namespace MDNSImplementation -} // namespace esp8266 +} // namespace experimental #endif // __LEAMDNS2HOST_LEGACY_H__ From 92cd216d13699d397fb741b15d00b0affef204d7 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 28 May 2020 20:00:55 +0200 Subject: [PATCH 025/152] ditto --- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 151555d15c..0e3f5e6ae7 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -8,7 +8,7 @@ #include "LEAmDNS2_Legacy.h" -namespace esp8266 +namespace experimental // esp8266 { /** @@ -1487,7 +1487,7 @@ clsLEAMDNSHost_Legacy::clsLEAMDNSHost::clsQuery::clsAnswerAccessor clsLEAMDNSHos } // namespace MDNSImplementation -} // namespace esp8266 +} // namespace experimental // esp8266 From cc2af846b605ecb1563e6232c45f47aa3e12515d Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Sat, 30 May 2020 14:11:59 +0200 Subject: [PATCH 026/152] Fix HostProbeResult callback --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 3 + libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 4 +- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 66 +++++++++++-------- 3 files changed, 44 insertions(+), 29 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 1553c3df4c..ec14d08e7a 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -108,6 +108,9 @@ namespace experimental */ //static + +clsLEAMDNSHost::fnProbeResultCallback clsLEAMDNSHost::stProbeResultCallback = nullptr; + const char* clsLEAMDNSHost::indexDomainName(const char* p_pcDomainName, const char* p_pcDivider /*= "-"*/, const char* p_pcDefaultDomainName /*= 0*/) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index bdcc05e21e..502361bb80 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -471,8 +471,10 @@ class clsLEAMDNSHost const char* p_pcDomainName, bool p_bProbeResult)>; + static fnProbeResultCallback stProbeResultCallback; + protected: - /** + /** clsProbeInformation */ class clsProbeInformation : public clsProbeInformation_Base diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 0e3f5e6ae7..f92e564456 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -136,7 +136,7 @@ bool clsLEAMDNSHost_Legacy::addHostForNetIf(const char* p_pcHostname, clsLEAMDNSHost* pHost = 0; if (((pHost = new esp8266::experimental::clsLEAMDNSHost)) - && (!((pHost->begin(p_pcHostname, p_pNetIf /*, default callback*/)) + && (!((pHost->begin(p_pcHostname, p_pNetIf, clsLEAMDNSHost::stProbeResultCallback)) && (m_HostInformations.push_back(stcHostInformation(pHost)), true)))) { delete pHost; @@ -1062,17 +1062,21 @@ bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MD { bool bResult = true; + clsLEAMDNSHost::stProbeResultCallback = + [p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, + const char* p_pcDomainName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void(const char* p_pcDomainName, bool p_bProbeResult) + { + p_fnCallback(p_pcDomainName, p_bProbeResult); + } + }; + + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - bResult = (*it).m_pHost->setProbeResultCallback([p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, - const char* p_pcDomainName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void(const char* p_pcDomainName, bool p_bProbeResult) - { - p_fnCallback(p_pcDomainName, p_bProbeResult); - } - }); + bResult = (*it).m_pHost->setProbeResultCallback(clsLEAMDNSHost::stProbeResultCallback); } return bResult; } @@ -1085,17 +1089,20 @@ bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MD { bool bResult = true; + clsLEAMDNSHost::stProbeResultCallback = + [this, p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, + const char* p_pcDomainName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcDomainName, bool p_bProbeResult) + { + p_fnCallback(this, p_pcDomainName, p_bProbeResult); + } + }; + for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - bResult = (*it).m_pHost->setProbeResultCallback([this, p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, - const char* p_pcDomainName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcDomainName, bool p_bProbeResult) - { - p_fnCallback(this, p_pcDomainName, p_bProbeResult); - } - }); + bResult = (*it).m_pHost->setProbeResultCallback(clsLEAMDNSHost::stProbeResultCallback); } return bResult; } @@ -1113,15 +1120,18 @@ bool clsLEAMDNSHost_Legacy::setServiceProbeResultCallback(const clsLEAMDNSHost_L { clsLEAMDNSHost::clsService* pService = 0; bResult = (((pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService])) - && (pService->setProbeResultCallback([this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, - const char* p_pcInstanceName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void(const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) - { - p_fnCallback(p_pcInstanceName, p_hService, p_bProbeResult); - } - }))); + && (pService->setProbeResultCallback( + + [this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, + const char* p_pcInstanceName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void(const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) + { + p_fnCallback(p_pcInstanceName, p_hService, p_bProbeResult); + } + } + ))); } return bResult; } From ff3e86989e4d836da42a8b8b3954670ca280c70c Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Sun, 31 May 2020 13:38:10 +0200 Subject: [PATCH 027/152] Style --- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 56 +++++++++---------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 502361bb80..793fc76c3b 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -474,7 +474,7 @@ class clsLEAMDNSHost static fnProbeResultCallback stProbeResultCallback; protected: - /** + /** clsProbeInformation */ class clsProbeInformation : public clsProbeInformation_Base diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index f92e564456..3758d89d4f 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -1063,15 +1063,15 @@ bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MD bool bResult = true; clsLEAMDNSHost::stProbeResultCallback = - [p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, - const char* p_pcDomainName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void(const char* p_pcDomainName, bool p_bProbeResult) - { - p_fnCallback(p_pcDomainName, p_bProbeResult); - } - }; + [p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, + const char* p_pcDomainName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void(const char* p_pcDomainName, bool p_bProbeResult) + { + p_fnCallback(p_pcDomainName, p_bProbeResult); + } + }; for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) @@ -1090,15 +1090,15 @@ bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MD bool bResult = true; clsLEAMDNSHost::stProbeResultCallback = - [this, p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, - const char* p_pcDomainName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcDomainName, bool p_bProbeResult) - { - p_fnCallback(this, p_pcDomainName, p_bProbeResult); - } - }; + [this, p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, + const char* p_pcDomainName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcDomainName, bool p_bProbeResult) + { + p_fnCallback(this, p_pcDomainName, p_bProbeResult); + } + }; for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { @@ -1122,16 +1122,16 @@ bool clsLEAMDNSHost_Legacy::setServiceProbeResultCallback(const clsLEAMDNSHost_L bResult = (((pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService])) && (pService->setProbeResultCallback( - [this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, - const char* p_pcInstanceName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void(const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) - { - p_fnCallback(p_pcInstanceName, p_hService, p_bProbeResult); - } - } - ))); + [this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, + const char* p_pcInstanceName, + bool p_bProbeResult)->void + { + if (p_fnCallback) // void(const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) + { + p_fnCallback(p_pcInstanceName, p_hService, p_bProbeResult); + } + } + ))); } return bResult; } From 40262ce4aa263f629e77a7e59ae6d7c5822fdab6 Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Sun, 31 May 2020 13:39:21 +0200 Subject: [PATCH 028/152] fix copy-paste error --- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h index baab2b4a5d..4d44ac82df 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h @@ -397,7 +397,7 @@ class clsLEAMDNSHost_Legacy */ bool hostDomainAvailable(void) const { - return m_rAnswerAccessor.serviceDomainAvailable(); + return m_rAnswerAccessor.hostDomainAvailable(); } /* hostDomain From 6e186376fc928d2c5e1318ef7fefa6bf15c590cb Mon Sep 17 00:00:00 2001 From: David Gauchard <david@unixrox.net> Date: Wed, 3 Jun 2020 10:56:23 +0200 Subject: [PATCH 029/152] wip --- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 1541d98321..274d84993f 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -129,7 +129,7 @@ bool clsLEAMDNSHost_Legacy::end(void) */ bool clsLEAMDNSHost_Legacy::addHostForNetIf(const char* p_pcHostname) { - bool bResult = true; + bool bResult = true; if (m_HostInformations.size() > 0) { From e82d252d33b9fa8837bba044389b9850bc6f4993 Mon Sep 17 00:00:00 2001 From: David Gauchard <david@unixrox.net> Date: Wed, 3 Jun 2020 11:00:01 +0200 Subject: [PATCH 030/152] wip --- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 274d84993f..1541d98321 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -129,7 +129,7 @@ bool clsLEAMDNSHost_Legacy::end(void) */ bool clsLEAMDNSHost_Legacy::addHostForNetIf(const char* p_pcHostname) { - bool bResult = true; + bool bResult = true; if (m_HostInformations.size() > 0) { From 9a3a696b2f935868a753bfe5f85906c965dda724 Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Sat, 6 Jun 2020 16:58:02 +0200 Subject: [PATCH 031/152] wip. probe and service --- libraries/ESP8266mDNS/src/ESP8266mDNS.h | 4 +- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 23 +++++++---- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 19 +++++----- .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 38 +++++++++---------- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 22 ++++++++--- 5 files changed, 62 insertions(+), 44 deletions(-) diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index 54eeb42797..d5f73d75ab 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -55,9 +55,9 @@ using clsMDNSHost = esp8266::experimental::clsLEAMDNSHost; #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) // Maps the implementation to use to the global namespace type //using MDNSResponder = Legacy_MDNSResponder::MDNSResponder; // Legacy -using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA +//using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA //using MDNSResponder = experimental::MDNSImplementation::clsLEAMDNSHost_Legacy; // LEAv2Compat -//using MDNSResponder = clsMDNSHost; // LEAv2 +using MDNSResponder = clsMDNSHost; // LEAv2 extern MDNSResponder MDNS; #endif diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index cb008ae975..e17104a899 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -438,12 +438,15 @@ bool clsLEAMDNSHost::removeService(clsLEAMDNSHost::clsService* p_pService) if (p_pService && (m_Services.end() != std::find(m_Services.begin(), m_Services.end(), p_pService))) { + bResult = _announceService(*p_pService, false); + /* for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf) && (_announceService(pNetIf, *p_pService, false))) { bResult = true; } +*/ } if (bResult) @@ -769,13 +772,14 @@ bool clsLEAMDNSHost::update(void) { bool bResult = false; + bResult = _updateProbeStatus(); + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) { //if (clsBackbone::sm_pBackbone->setDelayUDPProcessing(true)) //{ - if ((_updateProbeStatus(pNetIf)) && // Probing and announcing - (_checkQueryCache(pNetIf))) + if (_checkQueryCache(pNetIf)) { bResult = true; } @@ -790,8 +794,10 @@ bool clsLEAMDNSHost::update(void) /* clsLEAmDNS2_Host::announce */ -bool clsLEAMDNSHost::announce(bool p_bAnnounce /*= true*/, - bool p_bIncludeServices /*= true*/) + +//bool clsLEAMDNSHost::announce(bool p_bAnnounce /*= true*/, +// bool p_bIncludeServices /*= true*/) +/* { bool bResult = false; for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) @@ -801,12 +807,14 @@ bool clsLEAMDNSHost::announce(bool p_bAnnounce /*= true*/, } return bResult; } - +*/ /* clsLEAmDNS2_Host::announceService */ -bool clsLEAMDNSHost::announceService(clsService * p_pService, - bool p_bAnnounce /*= true*/) + +//bool clsLEAMDNSHost::announceService(clsService * p_pService, +// bool p_bAnnounce /*= true*/) +/* { bool bResult = false; for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) @@ -816,6 +824,7 @@ bool clsLEAMDNSHost::announceService(clsService * p_pService, } return bResult; } +*/ /* clsLEAmDNS2_Host::restart diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 4eed6900b1..0616d3eb8f 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -132,9 +132,9 @@ #if defined(DEBUG_ESP_PORT) && defined(DEBUG_ESP_MDNS_RESPONDER) #define DEBUG_ESP_MDNS_INFO #define DEBUG_ESP_MDNS_INFO2 -#define DEBUG_ESP_MDNS_ERR -#define DEBUG_ESP_MDNS_TX -#define DEBUG_ESP_MDNS_RX +//#define DEBUG_ESP_MDNS_ERR +//#define DEBUG_ESP_MDNS_TX +//#define DEBUG_ESP_MDNS_RX #endif #ifdef DEBUG_ESP_MDNS_RESPONDER @@ -1472,11 +1472,11 @@ class clsLEAMDNSHost #endif // PROBING - bool _updateProbeStatus(netif* pNetIf); + bool _updateProbeStatus(); bool _resetProbeStatus(bool p_bRestart = true); bool _hasProbesWaitingForAnswers(void) const; - bool _sendHostProbe(netif* pNetIf); - bool _sendServiceProbe(netif* pNetIf, clsService& p_rService); + bool _sendHostProbe(); + bool _sendServiceProbe(clsService& p_rService); bool _cancelProbingForHost(void); bool _cancelProbingForService(clsService& p_rService); bool _callHostProbeResultCallback(bool p_bResult); @@ -1484,11 +1484,9 @@ class clsLEAMDNSHost bool p_bResult); // ANNOUNCE - bool _announce(netif* pNetIf, - bool p_bAnnounce, + bool _announce(bool p_bAnnounce, bool p_bIncludeServices); - bool _announceService(netif* pNetIf, - clsService& p_pService, + bool _announceService(clsService& p_pService, bool p_bAnnounce = true); // QUERY CACHE @@ -1505,6 +1503,7 @@ class clsLEAMDNSHost // File: ..._Host_Transfer // SENDING bool _sendMessage(netif* pNetIf, clsSendParameter& p_SendParameter); + bool _sendMessage(clsSendParameter& p_SendParameter); bool _sendMessage_Multicast(netif* pNetIf, clsSendParameter& p_rSendParameter, uint8_t p_IPProtocolTypes); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index c8cf993ecb..2517d16f61 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1283,14 +1283,15 @@ bool clsLEAMDNSHost::_processAAAAAnswer(const clsLEAMDNSHost::clsRRAnswerAAAA* p Conflict management is handled in '_parseResponse ff.' Tiebraking is handled in 'parseQuery ff.' */ -bool clsLEAMDNSHost::_updateProbeStatus(netif* pNetIf) +bool clsLEAMDNSHost::_updateProbeStatus() { bool bResult = true; // // Probe host domain - if ((clsProbeInformation_Base::enuProbingStatus::ReadyToStart == m_ProbeInformation.m_ProbingStatus) && // Ready to get started AND - (( + if ((clsProbeInformation_Base::enuProbingStatus::ReadyToStart == m_ProbeInformation.m_ProbingStatus))// && // Ready to get started AND +/* + (( #ifdef MDNS_IPV4_SUPPORT _getResponderIPAddress(pNetIf, enuIPProtocolType::V4).isSet() // AND has IPv4 address #else @@ -1303,6 +1304,7 @@ bool clsLEAMDNSHost::_updateProbeStatus(netif* pNetIf) true #endif ))) // Has IP address +*/ { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Starting host probing...\n"), _DH());); @@ -1316,7 +1318,7 @@ bool clsLEAMDNSHost::_updateProbeStatus(netif* pNetIf) if (clsConsts::u32ProbeCount > m_ProbeInformation.m_u8SentCount) { // Send next probe - if ((bResult = _sendHostProbe(pNetIf))) + if ((bResult = _sendHostProbe())) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Did sent host probe for '%s.local'\n\n"), _DH(), (m_pcHostName ? : ""));); m_ProbeInformation.m_Timeout.reset(clsConsts::u32ProbeDelay); @@ -1341,7 +1343,7 @@ bool clsLEAMDNSHost::_updateProbeStatus(netif* pNetIf) else if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == m_ProbeInformation.m_ProbingStatus) && (m_ProbeInformation.m_Timeout.expired())) { - if ((bResult = _announce(pNetIf, true, false))) + if ((bResult = _announce(true, false))) { // Don't announce services here ++m_ProbeInformation.m_u8SentCount; // 1.. @@ -1380,9 +1382,9 @@ bool clsLEAMDNSHost::_updateProbeStatus(netif* pNetIf) if (clsConsts::u32ProbeCount > pService->m_ProbeInformation.m_u8SentCount) { // Send next probe - if ((bResult = _sendServiceProbe(pNetIf, *pService))) + if ((bResult = _sendServiceProbe(*pService))) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Did sent service probe for '%s' (%u)\n\n"), _DH(), _service2String(pService), (pService->m_ProbeInformation.m_u8SentCount + 1));); + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Did sent service probe for '%s' (%u)\n\n"), _DH(), _service2String(pService), (pService->m_ProbeInformation.m_u8SentCount + 1));); pService->m_ProbeInformation.m_Timeout.reset(clsConsts::u32ProbeDelay); ++pService->m_ProbeInformation.m_u8SentCount; } @@ -1390,7 +1392,7 @@ bool clsLEAMDNSHost::_updateProbeStatus(netif* pNetIf) else { // Probing finished - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("\n%s _updateProbeStatus: Done service probing '%s'\n\n\n"), _DH(), _service2String(pService));); + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("\n%s _updateProbeStatus: Done service probing '%s'\n\n\n"), _DH(), _service2String(pService));); pService->m_ProbeInformation.m_ProbingStatus = clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce; pService->m_ProbeInformation.m_Timeout.reset(esp8266::polledTimeout::oneShot::neverExpires); @@ -1406,7 +1408,7 @@ bool clsLEAMDNSHost::_updateProbeStatus(netif* pNetIf) (pService->m_ProbeInformation.m_Timeout.expired())) { // Probing already finished OR waiting for next time slot - if ((bResult = _announceService(pNetIf, *pService))) + if ((bResult = _announceService(*pService))) { // Announce service ++pService->m_ProbeInformation.m_u8SentCount; // 1.. @@ -1484,7 +1486,7 @@ bool clsLEAMDNSHost::_hasProbesWaitingForAnswers(void) const - A/AAAA (eg. esp8266.esp -> 192.168.2.120) */ -bool clsLEAMDNSHost::_sendHostProbe(netif* pNetIf) +bool clsLEAMDNSHost::_sendHostProbe() { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendHostProbe (%s.local, %lu)\n"), _DH(), m_pcHostName, millis());); @@ -1523,7 +1525,7 @@ bool clsLEAMDNSHost::_sendHostProbe(netif* pNetIf) } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendHostProbe: FAILED!\n"), _DH());); return ((bResult) && - (_sendMessage(pNetIf, sendParameter))); + (_sendMessage(sendParameter))); } /* @@ -1539,7 +1541,7 @@ bool clsLEAMDNSHost::_sendHostProbe(netif* pNetIf) - PTR NAME (eg. _http._tcp.local -> MyESP._http._tcp.local) (TODO: Check if needed, maybe TXT is better) */ -bool clsLEAMDNSHost::_sendServiceProbe(netif* pNetIf, clsService& p_rService) +bool clsLEAMDNSHost::_sendServiceProbe(clsService& p_rService) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _sendServiceProbe (%s, %lu)\n"), _DH(), _service2String(&p_rService), millis());); @@ -1573,7 +1575,7 @@ bool clsLEAMDNSHost::_sendServiceProbe(netif* pNetIf, clsService& p_rService) } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendServiceProbe: FAILED!\n"), _DH());); return ((bResult) && - (_sendMessage(pNetIf, sendParameter))); + (_sendMessage(sendParameter))); } /* @@ -1672,8 +1674,7 @@ bool clsLEAMDNSHost::_callServiceProbeResultCallback(clsLEAMDNSHost::clsService& inside the '_writeXXXAnswer' procs via 'sendParameter.m_bUnannounce = true' */ -bool clsLEAMDNSHost::_announce(netif* pNetIf, - bool p_bAnnounce, +bool clsLEAMDNSHost::_announce(bool p_bAnnounce, bool p_bIncludeServices) { bool bResult = false; @@ -1719,15 +1720,14 @@ bool clsLEAMDNSHost::_announce(netif* pNetIf, } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _announce: FAILED!\n"), _DH());); return ((bResult) && - (_sendMessage(pNetIf, sendParameter))); + (_sendMessage(sendParameter))); } /* clsLEAmDNS2_Host::_announceService */ -bool clsLEAMDNSHost::_announceService(netif* pNetIf, - clsLEAMDNSHost::clsService& p_rService, +bool clsLEAMDNSHost::_announceService(clsLEAMDNSHost::clsService& p_rService, bool p_bAnnounce /*= true*/) { bool bResult = false; @@ -1753,7 +1753,7 @@ bool clsLEAMDNSHost::_announceService(netif* pNetIf, } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _announceService: FAILED!\n"), _DH());); return ((bResult) && - (_sendMessage(pNetIf, sendParameter))); + (_sendMessage(sendParameter))); } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 6e6f74d992..01fffe189c 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -50,6 +50,20 @@ namespace experimental Any reply flags in installed services are removed at the end! */ +bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParameter) +{ + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf)) + { + _sendMessage(pNetIf, p_rSendParameter); + } + + // Finally clear service reply masks + for (clsService* pService : m_Services) + { + pService->m_u32ReplyMask = 0; + } +} bool clsLEAMDNSHost::_sendMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { bool bResult = false; @@ -135,12 +149,6 @@ bool clsLEAMDNSHost::_sendMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParamete (_sendMessage_Multicast(pNetIf, p_rSendParameter, u8AvailableProtocols))); } - // Finally clear service reply masks - for (clsService* pService : m_Services) - { - pService->m_u32ReplyMask = 0; - } - clsBackbone::sm_pBackbone->setDelayUDPProcessing(false); } @@ -256,6 +264,7 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam // Two step sequence: 'Count' and 'Send' for (typeSequence sequence = static_cast<typeSequence>(enuSequence::Count); ((bResult) && (sequence <= static_cast<typeSequence>(enuSequence::Send))); ++sequence) { + /* DEBUG_EX_INFO( if (static_cast<typeSequence>(enuSequence::Send) == sequence) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), @@ -268,6 +277,7 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam (unsigned)msgHeader.m_u16NSCount, (unsigned)msgHeader.m_u16ARCount); ); + */ // Count/send // Header bResult = ((static_cast<typeSequence>(enuSequence::Count) == sequence) From 930339ecaf2cfd986fa06a1d96eeab22b5106adb Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Sun, 7 Jun 2020 13:39:03 +0200 Subject: [PATCH 032/152] wip query to use sendmessage() instead of sendmessage(netif) --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 36 +++++++------------ libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 11 +++--- .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 12 +++---- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 10 +++--- 4 files changed, 27 insertions(+), 42 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index e17104a899..867e8d41e7 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -531,14 +531,11 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryService { std::list<clsQuery*> queries; - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) - if (netif_is_up(pNetIf)) - { clsQuery* pQuery = 0; if (((pQuery = _allocQuery(clsQuery::enuQueryType::Service))) && (_buildDomainForService(p_pcService, p_pcProtocol, pQuery->m_Domain))) { - if (((pQuery->m_bStaticQuery = true)) && (_sendQuery(pNetIf, *pQuery))) + if (((pQuery->m_bStaticQuery = true)) && (_sendQuery(*pQuery))) { queries.push_back(pQuery); } @@ -548,7 +545,6 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryService _removeQuery(pQuery); } } - } if (queries.size()) { @@ -590,14 +586,11 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryHost(co { std::list<clsQuery*> queries; - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) - if (netif_is_up(pNetIf)) - { clsQuery* pQuery = 0; if (((pQuery = _allocQuery(clsQuery::enuQueryType::Host))) && (_buildDomainForHost(p_pcHostName, pQuery->m_Domain))) { - if (((pQuery->m_bStaticQuery = true)) && (_sendQuery(pNetIf, *pQuery))) + if (((pQuery->m_bStaticQuery = true)) && (_sendQuery(*pQuery))) { queries.push_back(pQuery); } @@ -607,7 +600,7 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryHost(co _removeQuery(pQuery); } } - } + if (queries.size()) { @@ -711,18 +704,16 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::getQuery(void) bool bResult = false; clsQuery* pQuery = 0; if ((p_pcHostName) && (*p_pcHostName)) - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) - if (netif_is_up(pNetIf)) - { + { clsRRDomain domain; if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) - ? _installDomainQuery(pNetIf, domain, clsQuery::enuQueryType::Host) + ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) : 0))) { pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; bResult = true; } - } + } return bResult; } @@ -735,12 +726,10 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::getQuery(void) bool bResult = true; clsQuery* pQuery = 0; if ((p_pcHostName) && (*p_pcHostName)) - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) - if (netif_is_up(pNetIf)) { clsRRDomain domain; if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) - ? _installDomainQuery(pNetIf, domain, clsQuery::enuQueryType::Host) + ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) : 0))) { pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; @@ -772,8 +761,8 @@ bool clsLEAMDNSHost::update(void) { bool bResult = false; - bResult = _updateProbeStatus(); - + bResult = (_updateProbeStatus() && _checkQueryCache()) +/* for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) { @@ -787,6 +776,7 @@ bool clsLEAMDNSHost::update(void) // clsBackbone::sm_pBackbone->setDelayUDPProcessing(false); //} } +*/ DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s update: FAILED (Not connected?)!\n"), _DH());); return bResult; } @@ -1300,7 +1290,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery(netif* pNetIf, { pMDNSQuery->m_bStaticQuery = false; - if (_sendQuery(pNetIf, *pMDNSQuery)) + if (_sendQuery(*pMDNSQuery)) { pMDNSQuery->m_u8SentCount = 1; pMDNSQuery->m_ResendTimeout.reset(clsConsts::u32DynamicQueryResendDelay); @@ -1318,7 +1308,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery(netif* pNetIf, /* clsLEAmDNS2_Host::_installDomainQuery */ -clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installDomainQuery(netif* pNetIf, +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installDomainQuery( clsLEAMDNSHost::clsRRDomain & p_Domain, clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType) { @@ -1329,7 +1319,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installDomainQuery(netif* pNetIf, pQuery->m_Domain = p_Domain; pQuery->m_bStaticQuery = false; - if (_sendQuery(pNetIf, *pQuery)) + if (_sendQuery(*pQuery)) { pQuery->m_u8SentCount = 1; pQuery->m_ResendTimeout.reset(clsConsts::u32DynamicQueryResendDelay); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 0616d3eb8f..c179ad454f 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -1441,8 +1441,7 @@ class clsLEAMDNSHost clsQuery* _installServiceQuery(netif* pNetIf, const char* p_pcService, const char* p_pcProtocol); - clsQuery* _installDomainQuery(netif *pNetIf, - clsRRDomain& p_Domain, + clsQuery* _installDomainQuery(clsRRDomain& p_Domain, clsQuery::enuQueryType p_QueryType); bool _hasQueriesWaitingForAnswers(void) const; bool _executeQueryCallback(const clsQuery& p_Query, @@ -1490,7 +1489,7 @@ class clsLEAMDNSHost bool p_bAnnounce = true); // QUERY CACHE - bool _checkQueryCache(netif* pNetIf); + bool _checkQueryCache(); uint32_t _replyMaskForHost(netif* pNetIf, const clsRRHeader& p_RRHeader, @@ -1511,11 +1510,9 @@ class clsLEAMDNSHost bool _addQueryRecord(clsSendParameter& p_rSendParameter, const clsRRDomain& p_QueryDomain, uint16_t p_u16QueryType); - bool _sendQuery(netif* netif, - const clsQuery& p_Query, + bool _sendQuery(const clsQuery& p_Query, clsQuery::clsAnswer::list* p_pKnownAnswers = 0); - bool _sendQuery(netif* netif, - const clsRRDomain& p_QueryDomain, + bool _sendQuery(const clsRRDomain& p_QueryDomain, uint16_t p_u16RecordType, clsQuery::clsAnswer::list* p_pKnownAnswers = 0); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index 2517d16f61..ebeaaa2e65 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1772,7 +1772,7 @@ bool clsLEAMDNSHost::_announceService(clsLEAMDNSHost::clsService& p_rService, When no update arrived (in time), the component is removed from the answer (cache). */ -bool clsLEAMDNSHost::_checkQueryCache(netif* pNetIf) +bool clsLEAMDNSHost::_checkQueryCache() { bool bResult = true; @@ -1787,7 +1787,7 @@ bool clsLEAMDNSHost::_checkQueryCache(netif* pNetIf) if ((!pQuery->m_bStaticQuery) && (pQuery->m_ResendTimeout.expired())) { - if ((bResult = _sendQuery(pNetIf, *pQuery))) + if ((bResult = _sendQuery(*pQuery))) { // The re-query rate is increased to more than one hour (RFC 6762 5.2) ++pQuery->m_u8SentCount; @@ -1820,7 +1820,7 @@ bool clsLEAMDNSHost::_checkQueryCache(netif* pNetIf) { if (!pQAnswer->m_TTLServiceDomain.finalTimeoutLevel()) { - bResult = ((_sendQuery(pNetIf, *pQuery)) && + bResult = ((_sendQuery(*pQuery)) && (pQAnswer->m_TTLServiceDomain.restart())); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: PTR update scheduled for "), _DH()); @@ -1852,7 +1852,7 @@ bool clsLEAMDNSHost::_checkQueryCache(netif* pNetIf) { if (!pQAnswer->m_TTLHostDomainAndPort.finalTimeoutLevel()) { - bResult = ((_sendQuery(pNetIf, pQAnswer->m_ServiceDomain, DNS_RRTYPE_SRV)) && + bResult = ((_sendQuery(pQAnswer->m_ServiceDomain, DNS_RRTYPE_SRV)) && (pQAnswer->m_TTLHostDomainAndPort.restart())); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: SRV update scheduled for "), _DH()); @@ -1898,7 +1898,7 @@ bool clsLEAMDNSHost::_checkQueryCache(netif* pNetIf) { if (!pQAnswer->m_TTLTxts.finalTimeoutLevel()) { - bResult = ((_sendQuery(pNetIf, pQAnswer->m_ServiceDomain, DNS_RRTYPE_TXT)) && + bResult = ((_sendQuery(pQAnswer->m_ServiceDomain, DNS_RRTYPE_TXT)) && (pQAnswer->m_TTLTxts.restart())); DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: TXT update scheduled for "), _DH()); @@ -1941,7 +1941,7 @@ bool clsLEAMDNSHost::_checkQueryCache(netif* pNetIf) { // Needs update if ((bAUpdateQuerySent) || - ((bResult = _sendQuery(pNetIf, pQAnswer->m_HostDomain, DNS_RRTYPE_A)))) + ((bResult = _sendQuery(pQAnswer->m_HostDomain, DNS_RRTYPE_A)))) { pIPv4Address->m_TTL.restart(); bAUpdateQuerySent = true; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 01fffe189c..0493afd70b 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -570,8 +570,7 @@ bool clsLEAMDNSHost::_addQueryRecord(clsLEAMDNSHost::clsSendParameter& p_rSendPa Creates and sends a query for the given domain and query type. */ -bool clsLEAMDNSHost::_sendQuery(netif* pNetIf, - const clsLEAMDNSHost::clsQuery& p_Query, +bool clsLEAMDNSHost::_sendQuery(const clsLEAMDNSHost::clsQuery& p_Query, clsLEAMDNSHost::clsQuery::clsAnswer::list* p_pKnownAnswers /*= 0*/) { bool bResult = false; @@ -600,7 +599,7 @@ bool clsLEAMDNSHost::_sendQuery(netif* pNetIf, // TODO: Add known answers to query (void)p_pKnownAnswers; bResult = ((bResult) && - (_sendMessage(pNetIf, sendParameter))); + (_sendMessage(sendParameter))); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendQuery: FAILED!\n"), _DH());); return bResult; } @@ -611,8 +610,7 @@ bool clsLEAMDNSHost::_sendQuery(netif* pNetIf, Creates and sends a query for the given domain and record type. */ -bool clsLEAMDNSHost::_sendQuery(netif* pNetIf, - const clsLEAMDNSHost::clsRRDomain& p_QueryDomain, +bool clsLEAMDNSHost::_sendQuery(const clsLEAMDNSHost::clsRRDomain& p_QueryDomain, uint16_t p_u16RecordType, clsLEAMDNSHost::clsQuery::clsAnswer::list* p_pKnownAnswers /*= 0*/) { @@ -620,7 +618,7 @@ bool clsLEAMDNSHost::_sendQuery(netif* pNetIf, clsSendParameter sendParameter; bResult = ((_addQueryRecord(sendParameter, p_QueryDomain, p_u16RecordType)) && - (_sendMessage(pNetIf, sendParameter))); + (_sendMessage(sendParameter))); // TODO: Add known answer records (void) p_pKnownAnswers; From bd3baa9bfa7e5af26afd433df9e5ba85093fb802 Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Sun, 7 Jun 2020 16:58:13 +0200 Subject: [PATCH 033/152] wip, installservicequery re-add announce() fix announce to use correct probing status --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 58 ++++++------------- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 12 ++-- .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 3 +- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 20 +++---- 4 files changed, 34 insertions(+), 59 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 867e8d41e7..f5e90953b5 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -656,43 +656,32 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::getQuery(void) clsLEAmDNS2_Host::installServiceQuery (answer) */ -/*clsLEAMDNSHost::clsQuery* */ bool clsLEAMDNSHost::installServiceQuery(const char* p_pcService, +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcService, const char* p_pcProtocol, clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) { - bool bResult = false; clsQuery* pQuery = 0; - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) - if (netif_is_up(pNetIf) && (pQuery = _installServiceQuery(pNetIf, p_pcService, p_pcProtocol))) + if (pQuery = _installServiceQuery(p_pcService, p_pcProtocol)) { pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; - bResult = true; } - return bResult; + return pQuery; } /* clsLEAmDNS2_Host::installServiceQuery (accessor) */ -/*clsLEAMDNSHost::clsQuery* */ bool clsLEAMDNSHost::installServiceQuery(const char* p_pcService, +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcService, const char* p_pcProtocol, - clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor, - std::list<clsLEAMDNSHost::clsQuery*>* ret) + clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) { - bool bResult = false; clsQuery* pQuery = 0; - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) - if (netif_is_up(pNetIf) && (pQuery = _installServiceQuery(pNetIf, p_pcService, p_pcProtocol))) + if (pQuery = _installServiceQuery(p_pcService, p_pcProtocol)) { pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; - bResult = true; - if (ret) - { - ret->push_back(pQuery); - } } - return bResult; + return pQuery; } /* @@ -785,36 +774,23 @@ bool clsLEAMDNSHost::update(void) clsLEAmDNS2_Host::announce */ -//bool clsLEAMDNSHost::announce(bool p_bAnnounce /*= true*/, -// bool p_bIncludeServices /*= true*/) -/* +bool clsLEAMDNSHost::announce(bool p_bAnnounce /*= true*/, + bool p_bIncludeServices /*= true*/) { - bool bResult = false; - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) - if (netif_is_up(pNetIf) && _announce(pNetIf, p_bAnnounce, p_bIncludeServices)) - { - bResult = true; - } - return bResult; + return _announce(p_bAnnounce, p_bIncludeServices); } -*/ + /* clsLEAmDNS2_Host::announceService */ -//bool clsLEAMDNSHost::announceService(clsService * p_pService, -// bool p_bAnnounce /*= true*/) -/* +bool clsLEAMDNSHost::announceService(clsService * p_pService, + bool p_bAnnounce /*= true*/) { - bool bResult = false; - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) - if (netif_is_up(pNetIf) && _announceService(pNetIf, *p_pService, p_bAnnounce)) - { - bResult = true; - } - return bResult; + + return _announceService(*p_pService, p_bAnnounce); } -*/ + /* clsLEAmDNS2_Host::restart @@ -1277,7 +1253,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findNextQueryByDomain(const clsLEAMDN clsLEAmDNS2_Host::_installServiceQuery */ -clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery(netif* pNetIf, +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery( const char* p_pcService, const char* p_pcProtocol) { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index c179ad454f..be72504277 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -130,7 +130,7 @@ Enable/disable debug trace macros */ #if defined(DEBUG_ESP_PORT) && defined(DEBUG_ESP_MDNS_RESPONDER) -#define DEBUG_ESP_MDNS_INFO +//#define DEBUG_ESP_MDNS_INFO #define DEBUG_ESP_MDNS_INFO2 //#define DEBUG_ESP_MDNS_ERR //#define DEBUG_ESP_MDNS_TX @@ -1346,13 +1346,12 @@ class clsLEAMDNSHost install*Query() creates several queries on the interfaces. it no more returns a single query but a boolean until the API is adapted */ - /*clsQuery* */bool installServiceQuery(const char* p_pcServiceType, + clsQuery* installServiceQuery(const char* p_pcServiceType, const char* p_pcProtocol, clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); - /*clsQuery* */bool installServiceQuery(const char* p_pcServiceType, + clsQuery* installServiceQuery(const char* p_pcServiceType, const char* p_pcProtocol, - clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor, - std::list<clsQuery*>* ret = nullptr); + clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); /*clsQuery* */bool installHostQuery(const char* p_pcHostName, clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); /*clsQuery* */bool installHostQuery(const char* p_pcHostName, @@ -1438,8 +1437,7 @@ class clsLEAMDNSHost clsQuery* _findNextQueryByDomain(const clsRRDomain& p_Domain, const clsQuery::enuQueryType p_QueryType, const clsQuery* p_pPrevQuery); - clsQuery* _installServiceQuery(netif* pNetIf, - const char* p_pcService, + clsQuery* _installServiceQuery(const char* p_pcService, const char* p_pcProtocol); clsQuery* _installDomainQuery(clsRRDomain& p_Domain, clsQuery::enuQueryType p_QueryType); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index ebeaaa2e65..8f1d7460ce 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1680,7 +1680,8 @@ bool clsLEAMDNSHost::_announce(bool p_bAnnounce, bool bResult = false; clsSendParameter sendParameter; - if (clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == m_ProbeInformation.m_ProbingStatus) + if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == m_ProbeInformation.m_ProbingStatus) || + (clsProbeInformation_Base::enuProbingStatus::DoneFinally == m_ProbeInformation.m_ProbingStatus)) { bResult = true; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 1541d98321..c910260c17 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -802,16 +802,16 @@ clsLEAMDNSHost_Legacy::hMDNSServiceQuery clsLEAMDNSHost_Legacy::installServiceQu std::list<clsLEAMDNSHost::clsQuery*> queries; /*clsLEAMDNSHost::clsQuery* pQuery =*/ - hostInformation.m_pHost->installServiceQuery(p_pcService, p_pcProtocol, [this, p_fnCallback](const clsLEAMDNSHost::clsQuery& /*p_Query*/, - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor & p_AnswerAccessor, - clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item - bool p_bSetContent)->void - { - if (p_fnCallback) // void(const stcMDNSServiceInfo& p_MDNSServiceInfo, MDNSResponder::AnswerType p_AnswerType, bool p_bSetContent) - { - p_fnCallback(stcMDNSServiceInfo(p_AnswerAccessor), _answerFlagsToAnswerType(p_QueryAnswerTypeFlags), p_bSetContent); - } - }, &queries); +// hostInformation.m_pHost->installServiceQuery(p_pcService, p_pcProtocol, [this, p_fnCallback](const clsLEAMDNSHost::clsQuery& /*p_Query*/, +// const clsLEAMDNSHost::clsQuery::clsAnswerAccessor & p_AnswerAccessor, +// clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item +// bool p_bSetContent)->void +// { +// if (p_fnCallback) // void(const stcMDNSServiceInfo& p_MDNSServiceInfo, MDNSResponder::AnswerType p_AnswerType, bool p_bSetContent) +// { +// p_fnCallback(stcMDNSServiceInfo(p_AnswerAccessor), _answerFlagsToAnswerType(p_QueryAnswerTypeFlags), p_bSetContent); +// } +// }, &queries); if (queries.size()) { From 27f275ea0ce68057fbc48bb81a43ed1323e50455 Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Sun, 7 Jun 2020 17:27:38 +0200 Subject: [PATCH 034/152] fix no retrun statement in sendmessage --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 0493afd70b..fed239e54a 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -52,10 +52,11 @@ namespace experimental */ bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { + bool bResult = true; for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) { - _sendMessage(pNetIf, p_rSendParameter); + bResult = bResult && _sendMessage(pNetIf, p_rSendParameter); } // Finally clear service reply masks @@ -63,6 +64,7 @@ bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParam { pService->m_u32ReplyMask = 0; } + return bResult; } bool clsLEAMDNSHost::_sendMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { From 5e58c73c3aafd902ac17fd449f81ecb7a7d63cd5 Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Mon, 8 Jun 2020 13:43:39 +0200 Subject: [PATCH 035/152] wip installHostQuery fix service announce --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 14 +++++--------- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 6 +++--- libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 3 ++- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index f5e90953b5..d49b2f4c2b 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -687,10 +687,9 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcSe /* clsLEAmDNS2_Host::installHostQuery (answer) */ -/*clsLEAMDNSHost::clsQuery* */ bool clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) { - bool bResult = false; clsQuery* pQuery = 0; if ((p_pcHostName) && (*p_pcHostName)) { @@ -700,19 +699,17 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcSe : 0))) { pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; - bResult = true; } } - return bResult; + return pQuery; } - /* clsLEAmDNS2_Host::installHostQuery (accessor) */ -/*clsLEAMDNSHost::clsQuery* */ bool clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, + +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) { - bool bResult = true; clsQuery* pQuery = 0; if ((p_pcHostName) && (*p_pcHostName)) { @@ -722,10 +719,9 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcSe : 0))) { pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; - bResult = true; } } - return bResult; + return pQuery; } /* diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index be72504277..ef815c7571 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -130,7 +130,7 @@ Enable/disable debug trace macros */ #if defined(DEBUG_ESP_PORT) && defined(DEBUG_ESP_MDNS_RESPONDER) -//#define DEBUG_ESP_MDNS_INFO +#define DEBUG_ESP_MDNS_INFO #define DEBUG_ESP_MDNS_INFO2 //#define DEBUG_ESP_MDNS_ERR //#define DEBUG_ESP_MDNS_TX @@ -1352,9 +1352,9 @@ class clsLEAMDNSHost clsQuery* installServiceQuery(const char* p_pcServiceType, const char* p_pcProtocol, clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); - /*clsQuery* */bool installHostQuery(const char* p_pcHostName, + clsQuery* installHostQuery(const char* p_pcHostName, clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); - /*clsQuery* */bool installHostQuery(const char* p_pcHostName, + clsQuery* installHostQuery(const char* p_pcHostName, clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); // Remove a dynamic service query bool removeQuery(clsQuery* p_pQuery); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index 8f1d7460ce..e6e44b72ff 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1708,7 +1708,8 @@ bool clsLEAMDNSHost::_announce(bool p_bAnnounce, // Announce services (service type, name, SRV (location) and TXTs) for (clsService* pService : m_Services) { - if (clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == pService->m_ProbeInformation.m_ProbingStatus) + if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == pService->m_ProbeInformation.m_ProbingStatus) || + (clsProbeInformation_Base::enuProbingStatus::DoneFinally == pService->m_ProbeInformation.m_ProbingStatus)) { pService->m_u32ReplyMask = (static_cast<uint32_t>(enuContentFlag::PTR_TYPE) | static_cast<uint32_t>(enuContentFlag::PTR_NAME) | From 352a39afce6034983d06d9d7e0c1cb00159f9af0 Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Mon, 8 Jun 2020 13:46:47 +0200 Subject: [PATCH 036/152] Fix MDNS Clockv2 example --- .../examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index 0a6ad00cfe..18fa15c074 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -212,7 +212,9 @@ void setup(void) { bool p_bProbeResult)->void { Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); // Unattended added service - p_rMDNSHost.addService(0, "espclk", "tcp", 80); + hMDNSService = p_rMDNSHost.addService(0, "espclk", "tcp", 80); + hMDNSService->addDynamicServiceTxt("curtime", getTimeString()); + hMDNSService->setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallback); })) { Serial.println("mDNS-AP started"); } else { From c786920b7a77b2964eca49e8159c0f0385d33a63 Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Mon, 8 Jun 2020 16:57:03 +0200 Subject: [PATCH 037/152] fix ipv6 --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index e6e44b72ff..f3f1c220be 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1996,7 +1996,7 @@ bool clsLEAMDNSHost::_checkQueryCache() { // Needs update if ((bAAAAUpdateQuerySent) || - ((bResult = _sendQuery(pNetIf, pQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) + ((bResult = _sendQuery(pQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) { pIPv6Address->m_TTL.restart(); bAAAAUpdateQuerySent = true; From 258afd412fa88d3ab945727accff3b92a78dca42 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 9 Jun 2020 11:20:35 +0200 Subject: [PATCH 038/152] fix emulation on host for LEAmDNS2x --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 2 ++ .../ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 2 ++ tests/host/Makefile | 6 ++++++ tests/host/common/ArduinoMainUdp.cpp | 5 ----- tests/host/common/MocklwIP.cpp | 3 ++- tests/host/common/MocklwIP.h | 15 +++++++++++++++ tests/host/common/include/UdpContext.h | 7 +++++-- tests/host/common/user_interface.cpp | 4 +--- 8 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 tests/host/common/MocklwIP.h diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index d49b2f4c2b..86f9b5fc02 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -22,6 +22,8 @@ */ +#include <algorithm> + #include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index e027f494ac..1b5acaa076 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -22,6 +22,8 @@ */ +#include <algorithm> + #include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" diff --git a/tests/host/Makefile b/tests/host/Makefile index f6361f36aa..6a1e987d8a 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -275,6 +275,12 @@ OPT_ARDUINO_LIBS ?= $(addprefix ../../libraries/,\ LEAmDNS_Structs.cpp \ LEAmDNS_Transfer.cpp \ ESP8266mDNS.cpp \ + LEAmDNS2Host.cpp \ + LEAmDNS2Host_Control.cpp \ + LEAmDNS2Host_Debug.cpp \ + LEAmDNS2Host_Structs.cpp \ + LEAmDNS2Host_Transfer.cpp \ + LEAmDNS2_Backbone.cpp \ ) \ ArduinoOTA/ArduinoOTA.cpp \ DNSServer/src/DNSServer.cpp \ diff --git a/tests/host/common/ArduinoMainUdp.cpp b/tests/host/common/ArduinoMainUdp.cpp index 2962f4a483..6c4a034d2a 100644 --- a/tests/host/common/ArduinoMainUdp.cpp +++ b/tests/host/common/ArduinoMainUdp.cpp @@ -29,11 +29,6 @@ DEALINGS WITH THE SOFTWARE. */ -#include "lwip/opt.h" -#include "lwip/udp.h" -#include "lwip/inet.h" -#include "lwip/igmp.h" -#include "lwip/mem.h" #include <include/UdpContext.h> #include <poll.h> #include <map> diff --git a/tests/host/common/MocklwIP.cpp b/tests/host/common/MocklwIP.cpp index 8628cc47bc..1e19f20fc7 100644 --- a/tests/host/common/MocklwIP.cpp +++ b/tests/host/common/MocklwIP.cpp @@ -1,6 +1,7 @@ #include <AddrList.h> -#include <lwip/netif.h> + +#include "MocklwIP.h" esp8266::AddressListImplementation::AddressList addrList; diff --git a/tests/host/common/MocklwIP.h b/tests/host/common/MocklwIP.h new file mode 100644 index 0000000000..e7fead4cb7 --- /dev/null +++ b/tests/host/common/MocklwIP.h @@ -0,0 +1,15 @@ + +#ifndef __MOCKLWIP_H +#define __MOCKLWIP_H + +extern "C" +{ + +#include <user_interface.h> +#include <lwip/netif.h> + +extern netif netif0; + +} // extern "C" + +#endif // __MOCKLWIP_H diff --git a/tests/host/common/include/UdpContext.h b/tests/host/common/include/UdpContext.h index c4a87c19b7..12c41b433e 100644 --- a/tests/host/common/include/UdpContext.h +++ b/tests/host/common/include/UdpContext.h @@ -23,6 +23,9 @@ #include <functional> +#include <MocklwIP.h> +#include <IPAddress.h> + class UdpContext; #define GET_IP_HDR(pb) reinterpret_cast<ip_hdr*>(((uint8_t*)((pb)->payload)) - UDP_HLEN - IP_HLEN); @@ -136,7 +139,7 @@ class UdpContext return pos <= _inbufsize; } - uint32_t getRemoteAddress() + IPAddress getRemoteAddress() { return _dst.addr; } @@ -146,7 +149,7 @@ class UdpContext return _dstport; } - uint32_t getDestAddress() + IPAddress getDestAddress() { mockverbose("TODO: implement UDP getDestAddress\n"); return 0; //ip_hdr* iphdr = GET_IP_HDR(_rx_buf); diff --git a/tests/host/common/user_interface.cpp b/tests/host/common/user_interface.cpp index e7b109401a..00482a356e 100644 --- a/tests/host/common/user_interface.cpp +++ b/tests/host/common/user_interface.cpp @@ -39,13 +39,11 @@ #include <string.h> #include <arpa/inet.h> +#include "MocklwIP.h" extern "C" { -#include <user_interface.h> -#include <lwip/netif.h> - uint8 wifi_get_opmode(void) { return STATION_MODE; From 45c83eff72a87e214d19a520b6010545a7c2cb03 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 9 Jun 2020 11:21:04 +0200 Subject: [PATCH 039/152] fix warning --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 86f9b5fc02..b2d3078246 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -663,7 +663,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcSe clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) { clsQuery* pQuery = 0; - if (pQuery = _installServiceQuery(p_pcService, p_pcProtocol)) + if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) { pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; } @@ -679,7 +679,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcSe clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) { clsQuery* pQuery = 0; - if (pQuery = _installServiceQuery(p_pcService, p_pcProtocol)) + if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) { pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; } From 49979f2f5fefadee3f3371d7d4a03b1771fbbab7 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 9 Jun 2020 22:09:24 +0200 Subject: [PATCH 040/152] comment out 3 delay(clsConsts::u32SendCooldown) - separate defines in a new _Priv.h file --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 5 +- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 87 ------------- .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 2 +- .../ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp | 2 +- .../ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 2 +- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 8 +- .../ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h | 117 ++++++++++++++++++ 8 files changed, 131 insertions(+), 94 deletions(-) create mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index b2d3078246..ba2eae1800 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -26,6 +26,7 @@ #include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" +#include "LEAmDNS2_Priv.h" #ifdef MDNS_IPV4_SUPPORT #include <lwip/igmp.h> @@ -748,7 +749,7 @@ bool clsLEAMDNSHost::update(void) { bool bResult = false; - bResult = (_updateProbeStatus() && _checkQueryCache()) + bResult = (_updateProbeStatus() && _checkQueryCache()); /* for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) @@ -764,7 +765,7 @@ bool clsLEAMDNSHost::update(void) //} } */ - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s update: FAILED (Not connected?)!\n"), _DH());); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s update: FAILED (Not connected?)!\n"), _DH())); return bResult; } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index ef815c7571..7d48a1afe3 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -113,93 +113,6 @@ #define MDNS_IPV6_SUPPORT // If we've got IPv6 support, then we need IPv6 support :-) #endif -/* - LWIP_OPEN_SRC -*/ -#ifndef LWIP_OPEN_SRC -#define LWIP_OPEN_SRC -#endif - -/* - Enable class debug functions -*/ -#define ESP_8266_MDNS_INCLUDE -#define DEBUG_ESP_MDNS_RESPONDER - -/* - Enable/disable debug trace macros -*/ -#if defined(DEBUG_ESP_PORT) && defined(DEBUG_ESP_MDNS_RESPONDER) -#define DEBUG_ESP_MDNS_INFO -#define DEBUG_ESP_MDNS_INFO2 -//#define DEBUG_ESP_MDNS_ERR -//#define DEBUG_ESP_MDNS_TX -//#define DEBUG_ESP_MDNS_RX -#endif - -#ifdef DEBUG_ESP_MDNS_RESPONDER -#ifdef DEBUG_ESP_MDNS_INFO -#define DEBUG_EX_INFO(A) A -#define DEBUG_EX_INFO_IF(C,A...) do if (C) { A; } while (0) -#else -#define DEBUG_EX_INFO(A) -#define DEBUG_EX_INFO_IF(C,A...) -#endif -#ifdef DEBUG_ESP_MDNS_INFO2 -#define DEBUG_EX_INFO2(A) A -#define DEBUG_EX_INFO2_IF(C,A...) do if (C) { A; } while (0) -#else -#define DEBUG_EX_INFO2(A) -#define DEBUG_EX_INFO2_IF(C,A...) -#endif -#ifdef DEBUG_ESP_MDNS_ERR -#define DEBUG_EX_ERR(A) A -#define DEBUG_EX_ERR_IF(C,A...) do if (C) { A; } while (0) -#else -#define DEBUG_EX_ERR(A) -#define DEBUG_EX_ERR_IF(C,A...) -#endif -#ifdef DEBUG_ESP_MDNS_TX -#define DEBUG_EX_TX(A) A -#else -#define DEBUG_EX_TX(A) -#endif -#ifdef DEBUG_ESP_MDNS_RX -#define DEBUG_EX_RX(A) A -#else -#define DEBUG_EX_RX(A) -#endif - -#ifdef DEBUG_ESP_PORT -#define DEBUG_OUTPUT DEBUG_ESP_PORT -#else -#define DEBUG_OUTPUT Serial -#endif -#else -#define DEBUG_EX_INFO(A) -#define DEBUG_EX_INFO2(A) -#define DEBUG_EX_ERR(A) -#define DEBUG_EX_TX(A) -#define DEBUG_EX_RX(A) -#endif - -/* - Enable/disable the usage of the F() macro in debug trace printf calls. - There needs to be an PGM comptible printf function to use this. - - USE_PGM_PRINTF and F -*/ -#define USE_PGM_PRINTF - -#ifdef USE_PGM_PRINTF -#else -#ifdef F -#undef F -#endif -#define F(A) A -#endif - - namespace esp8266 { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index f3f1c220be..f471999fa3 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -24,7 +24,7 @@ #include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" - +#include "LEAmDNS2_Priv.h" namespace esp8266 { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp index f0edcd4232..50a7d07594 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp @@ -24,7 +24,7 @@ #include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" - +#include "LEAmDNS2_Priv.h" namespace esp8266 { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index 1b5acaa076..3cae0ca3bc 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -26,7 +26,7 @@ #include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" - +#include "LEAmDNS2_Priv.h" namespace esp8266 { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index fed239e54a..b7a800d393 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -25,7 +25,7 @@ #include <coredecls.h> // for can_yield() #include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" - +#include "LEAmDNS2_Priv.h" namespace esp8266 { @@ -117,11 +117,13 @@ bool clsLEAMDNSHost::_sendMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParamete (Serial.println("Did send UC"), true)*/); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage (V4): FAILED!\n"), _DH());); +#if 0 if ((clsConsts::u32SendCooldown) && (can_yield())) { delay(clsConsts::u32SendCooldown); } +#endif } else { @@ -186,11 +188,13 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe (Serial.println("Did send MC V4"), true)*/); DEBUG_EX_ERR(if (!bIPv4Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (V4): FAILED!\n"), _DH());); +#if 0 if ((clsConsts::u32SendCooldown) && (can_yield())) { delay(clsConsts::u32SendCooldown); } +#endif } #endif @@ -212,11 +216,13 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe (Serial.println("Did send MC V6"), true)*/); DEBUG_EX_ERR(if (!bIPv6Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (IPv6): FAILED! (%s, %s, %s)\n"), _DH(), (_getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet() ? "1" : "0"), (bPrepareMessage ? "1" : "0"), (bUDPContextSend ? "1" : "0"));); +#if 0 if ((clsConsts::u32SendCooldown) && (can_yield())) { delay(clsConsts::u32SendCooldown); } +#endif } #endif diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index d4ab972a30..870b00e24e 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -24,7 +24,7 @@ #include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" - +#include "LEAmDNS2_Priv.h" namespace esp8266 { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h new file mode 100644 index 0000000000..b0235ec123 --- /dev/null +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h @@ -0,0 +1,117 @@ +/* + LEAmDNS_Priv.h + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +#ifndef MDNS2_PRIV_H +#define MDNS2_PRIV_H + +/* + LWIP_OPEN_SRC +*/ +#ifndef LWIP_OPEN_SRC +#define LWIP_OPEN_SRC +#endif + +/* + Enable class debug functions +*/ +#define ESP_8266_MDNS_INCLUDE +#define DEBUG_ESP_MDNS_RESPONDER + +/* + Enable/disable debug trace macros +*/ +#if defined(DEBUG_ESP_PORT) +#define DEBUG_ESP_MDNS_ERR +#endif +#if defined(DEBUG_ESP_PORT) && defined(DEBUG_ESP_MDNS_RESPONDER) +#define DEBUG_ESP_MDNS_INFO +#define DEBUG_ESP_MDNS_INFO2 +//#define DEBUG_ESP_MDNS_TX +//#define DEBUG_ESP_MDNS_RX +#endif + +#ifdef DEBUG_ESP_MDNS_RESPONDER +#ifdef DEBUG_ESP_MDNS_INFO +#define DEBUG_EX_INFO(A) do { A; } while (0) +#define DEBUG_EX_INFO_IF(C,A...) do if (C) { A; } while (0) +#else +#define DEBUG_EX_INFO(A) +#define DEBUG_EX_INFO_IF(C,A...) +#endif +#ifdef DEBUG_ESP_MDNS_INFO2 +#define DEBUG_EX_INFO2(A) do { A; } while (0) +#define DEBUG_EX_INFO2_IF(C,A...) do if (C) { A; } while (0) +#else +#define DEBUG_EX_INFO2(A) +#define DEBUG_EX_INFO2_IF(C,A...) +#endif +#ifdef DEBUG_ESP_MDNS_ERR +#define DEBUG_EX_ERR(A) do { A; } while (0) +#define DEBUG_EX_ERR_IF(C,A...) do if (C) { A; } while (0) +#else +#define DEBUG_EX_ERR(A) +#define DEBUG_EX_ERR_IF(C,A...) +#endif +#ifdef DEBUG_ESP_MDNS_TX +#define DEBUG_EX_TX(A) do { A; } while (0) +#else +#define DEBUG_EX_TX(A) +#endif +#ifdef DEBUG_ESP_MDNS_RX +#define DEBUG_EX_RX(A) do { A; } while (0) +#else +#define DEBUG_EX_RX(A) +#endif + +#ifdef DEBUG_ESP_PORT +#define DEBUG_OUTPUT DEBUG_ESP_PORT +#else +#define DEBUG_OUTPUT Serial +#endif +#else +#define DEBUG_EX_INFO(A) +#define DEBUG_EX_INFO2(A) +#define DEBUG_EX_ERR(A) +#define DEBUG_EX_TX(A) +#define DEBUG_EX_RX(A) +#endif + +/* + Enable/disable the usage of the F() macro in debug trace printf calls. + There needs to be an PGM comptible printf function to use this. + + USE_PGM_PRINTF and F +*/ +#define USE_PGM_PRINTF + +#ifdef USE_PGM_PRINTF +#else +#ifdef F +#undef F +#endif +#define F(A) A +#endif + + +#endif // MDNS2_PRIV_H From 310526d9c96e2e987798f43f21e2fcbd58694b7b Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 9 Jun 2020 22:21:49 +0200 Subject: [PATCH 041/152] fix debug macros --- libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h index b0235ec123..de0021d000 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h @@ -53,21 +53,21 @@ #ifdef DEBUG_ESP_MDNS_RESPONDER #ifdef DEBUG_ESP_MDNS_INFO -#define DEBUG_EX_INFO(A) do { A; } while (0) +#define DEBUG_EX_INFO(A) A #define DEBUG_EX_INFO_IF(C,A...) do if (C) { A; } while (0) #else #define DEBUG_EX_INFO(A) #define DEBUG_EX_INFO_IF(C,A...) #endif #ifdef DEBUG_ESP_MDNS_INFO2 -#define DEBUG_EX_INFO2(A) do { A; } while (0) +#define DEBUG_EX_INFO2(A) A #define DEBUG_EX_INFO2_IF(C,A...) do if (C) { A; } while (0) #else #define DEBUG_EX_INFO2(A) #define DEBUG_EX_INFO2_IF(C,A...) #endif #ifdef DEBUG_ESP_MDNS_ERR -#define DEBUG_EX_ERR(A) do { A; } while (0) +#define DEBUG_EX_ERR(A) A #define DEBUG_EX_ERR_IF(C,A...) do if (C) { A; } while (0) #else #define DEBUG_EX_ERR(A) From 2204902b8917bf4056d3a8c2e2d27847b9a2fa2d Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Thu, 11 Jun 2020 10:58:07 +0200 Subject: [PATCH 042/152] Add serviceMonitor_v2 --- .../mDNS_ServiceMonitor_v2/MSDN_V2.cpp | 275 ++++++++++++++++++ .../LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.h | 22 ++ 2 files changed, 297 insertions(+) create mode 100644 libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp create mode 100644 libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.h diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp new file mode 100644 index 0000000000..8c77734767 --- /dev/null +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp @@ -0,0 +1,275 @@ +/* + ESP8266 mDNS Responder Service Monitor + + This example demonstrates two features of the LEA MDNSResponder: + 1. The host and service domain negotiation process that ensures + the uniqueness of the finally choosen host and service domain name. + 2. The dynamic MDNS service lookup/query feature. + + A list of 'HTTP' services in the local network is created and kept up to date. + In addition to this, a (very simple) HTTP server is set up on port 80 + and announced as a service. + + The ESP itself is initially announced to clients as 'esp8266.local', if this host domain + is already used in the local network, another host domain is negociated. Keep an + eye to the serial output to learn the final host domain for the HTTP service. + The service itself is is announced as 'host domain'._http._tcp.local. + The HTTP server delivers a short greeting and the current list of other 'HTTP' services (not updated). + The web server code is taken nearly 1:1 from the 'mDNS_Web_Server.ino' example. + Point your browser to 'host domain'.local to see this web page. + + Instructions: + - Update WiFi SSID and password as necessary. + - Flash the sketch to the ESP8266 board + - Install host software: + - For Linux, install Avahi (http://avahi.org/). + - For Windows, install Bonjour (http://www.apple.com/support/bonjour/). + - For Mac OSX and iOS support is built in through Bonjour already. + - Use a browser like 'Safari' to see the page at http://'host domain'.local. + +*/ + + +#include <ESP8266WiFi.h> +#include <WiFiClient.h> +#include <ESP8266WebServer.h> + +/* + Include the MDNSResponder (the library needs to be included also) + As LEA MDNSResponder is experimantal in the ESP8266 environment currently, the + legacy MDNSResponder is defaulted in th include file. + There are two ways to access LEA MDNSResponder: + 1. Prepend every declaration and call to global declarations or functions with the namespace, like: + 'LEAmDNS:MDNSResponder::hMDNSService hMDNSService;' + This way is used in the example. But be careful, if the namespace declaration is missing + somewhere, the call might go to the legacy implementation... + 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. + +*/ +#include <ESP8266mDNS.h> +#include "LocalDefines.h" +#include "Netdump.h" +using namespace NetCapture; +/* + Global defines and vars +*/ + +#define SERVICE_PORT 80 // HTTP port + +char* pcHostDomain = 0; // Negociated host domain +bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain +MDNSResponder::clsService* hMDNSService = 0; // The handle of the http service in the MDNS responder +MDNSResponder::clsQuery* hMDNSServiceQuery = 0; // The handle of the 'http.tcp' service query in the MDNS responder + +const String cstrNoHTTPServices = "Currently no 'http.tcp' services in the local network!<br/>"; +String strHTTPServices = cstrNoHTTPServices; + +// HTTP server at port 'SERVICE_PORT' will respond to HTTP requests +ESP8266WebServer server(SERVICE_PORT); + + +/* + setStationHostname +*/ +bool setStationHostname(const char* p_pcHostname) { + + if (p_pcHostname) { + WiFi.hostname(p_pcHostname); + Serial.printf("setStationHostname: Station hostname is set to '%s'\n", p_pcHostname); + return true; + } + return false; +} + + +void MDNSServiceQueryCallback(const MDNSResponder::clsQuery& p_Query, + const MDNSResponder::clsQuery::clsAnswer& p_Answer, + MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, + bool p_bSetContent) +{ + Serial.printf("----------------Query callback cnt = %d tp = %2x set = %s\r\n",p_Query.answerCount(),p_QueryAnswerTypeFlags,p_bSetContent?"true":"false"); + + for (int i=0;i<p_Query.answerCount();i++) + { + Serial.printf("AnswerID = %d\r\n",i); + p_Query.answerAccessor(i).printTo(Serial); + } +} + +/* + MDNSServiceProbeResultCallback + Probe result callback for Services +*/ + +void serviceProbeResult(MDNSResponder::clsService& p_rMDNSService, + const char* p_pcInstanceName, + bool p_bProbeResult) { + Serial.printf("MDNSServiceProbeResultCallback: Service %s probe %s\n", p_pcInstanceName, (p_bProbeResult ? "succeeded." : "failed!")); +} + +/* + MDNSHostProbeResultCallback + + Probe result callback for the host domain. + If the domain is free, the host domain is set and the http service is + added. + If the domain is already used, a new name is created and the probing is + restarted via p_pMDNSResponder->setHostname(). + +*/ + +void hostProbeResult(clsMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bProbeResult) { + + Serial.printf("MDNSHostProbeResultCallback: Host domain '%s.local' is %s\n", p_pcDomainName.c_str(), (p_bProbeResult ? "free" : "already USED!")); + + if (true == p_bProbeResult) { + // Set station hostname + setStationHostname(pcHostDomain); + + if (!bHostDomainConfirmed) { + // Hostname free -> setup clock service + bHostDomainConfirmed = true; + + if (!hMDNSService) { + // Add a 'http.tcp' service to port 'SERVICE_PORT', using the host domain as instance domain + hMDNSService = MDNS.addService(0, "http", "tcp", SERVICE_PORT, serviceProbeResult); + + if (hMDNSService) { + hMDNSService->setProbeResultCallback(serviceProbeResult); + // MDNS.setServiceProbeResultCallback(hMDNSService, serviceProbeResult); + + // Add some '_http._tcp' protocol specific MDNS service TXT items + // See: http://www.dns-sd.org/txtrecords.html#http + hMDNSService->addServiceTxt("user", ""); + hMDNSService->addServiceTxt("password", ""); + hMDNSService->addServiceTxt("path", "/"); + } + + // Install dynamic 'http.tcp' service query + if (!hMDNSServiceQuery) { + hMDNSServiceQuery = MDNS.installServiceQuery("http", "tcp", MDNSServiceQueryCallback); + if (hMDNSServiceQuery) { + Serial.printf("MDNSProbeResultCallback: Service query for 'http.tcp' services installed.\n"); + } else { + Serial.printf("MDNSProbeResultCallback: FAILED to install service query for 'http.tcp' services!\n"); + } + } + } + } + } + else { + // Change hostname, use '-' as divider between base name and index + if (MDNSResponder::indexDomainName(pcHostDomain, "-", 0)) { + MDNS.setHostName(pcHostDomain); + } else { + Serial.println("MDNSProbeResultCallback: FAILED to update hostname!"); + } + } +} + +/* + HTTP request function (not found is handled by server) +*/ +void handleHTTPRequest() { + Serial.println(""); + Serial.println("HTTP Request"); + + IPAddress ip = server.client().localIP(); + String ipStr = ip.toString(); + String s = "<!DOCTYPE HTML>\r\n<html><h3><head>Hello from "; + s += WiFi.hostname() + ".local at " + server.client().localIP().toString() + "</h3></head>"; + s += "<br/><h4>Local HTTP services are :</h4>"; + s += "<ol>"; + /* + for (auto info : MDNS.answerInfo(hMDNSServiceQuery)) { + s += "<li>"; + s += info.serviceDomain(); + if (info.hostDomainAvailable()) { + s += "<br/>Hostname: "; + s += String(info.hostDomain()); + s += (info.hostPortAvailable()) ? (":" + String(info.hostPort())) : ""; + } + if (info.IP4AddressAvailable()) { + s += "<br/>IP4:"; + for (auto ip : info.IP4Adresses()) { + s += " " + ip.toString(); + } + } + if (info.txtAvailable()) { + s += "<br/>TXT:<br/>"; + for (auto kv : info.keyValues()) { + s += "\t" + String(kv.first) + " : " + String(kv.second) + "<br/>"; + } + } + s += "</li>"; + + } + */ + s += "</ol><br/>"; + + Serial.println("Sending 200"); + server.send(200, "text/html", s); + Serial.println("Done with request"); +} + +//Netdump nd(Netdump::interface::LWIP); + + +/* + setup +*/ +void setup(void) { + Serial.begin(115200); +// nd.printDump(Serial, Packet::PacketDetail::NONE, [](const Packet& p){return(p.getInOut() && p.isMDNS());}); + Serial.setDebugOutput(false); + + // Connect to WiFi network + WiFi.mode(WIFI_AP_STA); + WiFi.softAP("Soft1"); + WiFi.begin(ssid, password); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + // Setup HTTP server + server.on("/", handleHTTPRequest); + + // Setup MDNS responders + MDNS.setProbeResultCallback(hostProbeResult); + + // Init the (currently empty) host domain string with 'esp8266' + MDNS.begin("esp8266_v2"); +/* + if ((!MDNSResponder::indexDomain(pcHostDomain, 0, "esp8266")) || + (!MDNS.begin(pcHostDomain))) { + Serial.println(" Error setting up MDNS responder!"); + while (1) { // STOP + delay(1000); + } + } +*/ + Serial.println("MDNS responder started"); + + // Start HTTP server + server.begin(); + Serial.println("HTTP server started"); +} + +void loop(void) { + // Check if a request has come in + server.handleClient(); + // Allow MDNS processing + MDNS.update(); +} + + + diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.h b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.h new file mode 100644 index 0000000000..62ca01f6ab --- /dev/null +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.h @@ -0,0 +1,22 @@ +// Only modify this file to include +// - function definitions (prototypes) +// - include files +// - extern variable definitions +// In the appropriate section + +#ifndef _MSDN_V2_H_ +#define _MSDN_V2_H_ +#include "Arduino.h" +//add your includes for the project MSDN_V2 here + + +//end of add your includes here + + +//add your function definitions for the project MSDN_V2 here + + + + +//Do not add code below this line +#endif /* _MSDN_V2_H_ */ From 46ab0a00a37f6bfad0074afbfa31d0db1fa8d900 Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Thu, 11 Jun 2020 16:35:06 +0200 Subject: [PATCH 043/152] Improve MDNSServiceQueryCallback in servicemonior v1 --- .../mDNS_ServiceMonitor_v2/MSDN_V2.cpp | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp index 8c77734767..dd87b7d14e 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp @@ -87,13 +87,32 @@ void MDNSServiceQueryCallback(const MDNSResponder::clsQuery& p_Query, MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, bool p_bSetContent) { - Serial.printf("----------------Query callback cnt = %d tp = %2x set = %s\r\n",p_Query.answerCount(),p_QueryAnswerTypeFlags,p_bSetContent?"true":"false"); - - for (int i=0;i<p_Query.answerCount();i++) - { - Serial.printf("AnswerID = %d\r\n",i); - p_Query.answerAccessor(i).printTo(Serial); - } + String answerInfo; + switch (p_QueryAnswerTypeFlags) { + case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain): + answerInfo = "ServiceDomain " + String(p_Answer.m_ServiceDomain.c_str()); + break; + + case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort): + answerInfo = "HostDomainAndPort " + String(p_Answer.m_HostDomain.c_str()) + ":" + String(p_Answer.m_u16Port); + break; + case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address): + answerInfo = "IP4Address "; + for (auto ip : p_Answer.m_IPv4Addresses) { + answerInfo += "- " + ip->m_IPAddress.toString(); + }; + break; + case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::Txts): + answerInfo = "TXT "; + for (auto kv : p_Answer.m_Txts.m_Txts) { + answerInfo += "\nkv : " + String(kv->m_pcKey) + " : " + String(kv->m_pcValue); + } + break; + default : + answerInfo = "Unknown Answertype " + String(p_QueryAnswerTypeFlags); + + } + Serial.printf("Answer %s %s\n", answerInfo.c_str(), p_bSetContent ? "Modified" : "Deleted"); } /* From 225a46e6e6585b45a2aadf411e511d07880d3c18 Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Thu, 11 Jun 2020 16:36:31 +0200 Subject: [PATCH 044/152] Fix HostDomainPort --- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 7d48a1afe3..e5e21d4c08 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -945,6 +945,7 @@ class clsLEAMDNSHost ServiceDomain = 0x01, // Service domain HostDomain = 0x02, // Host domain Port = 0x04, // Port + HostDomainPort = 0x06, Txts = 0x08, // TXT items #ifdef MDNS_IPV4_SUPPORT IPv4Address = 0x10, // IPv4 address From 39dafbca9e29d2f44cdac29a48af988df61bf035 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 12 Jun 2020 00:16:49 +0200 Subject: [PATCH 045/152] temporary test mDNS_ServiceMonitor_v2_test.ino --- .../mDNS_ServiceMonitor_v2_test.ino | 393 ++++++++++++++++++ 1 file changed, 393 insertions(+) create mode 100644 libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino new file mode 100644 index 0000000000..1386b072b0 --- /dev/null +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino @@ -0,0 +1,393 @@ +/* + ESP8266 mDNS Responder Service Monitor + + This example demonstrates two features of the LEA MDNSResponder: + 1. The host and service domain negotiation process that ensures + the uniqueness of the finally choosen host and service domain name. + 2. The dynamic MDNS service lookup/query feature. + + A list of 'HTTP' services in the local network is created and kept up to date. + In addition to this, a (very simple) HTTP server is set up on port 80 + and announced as a service. + + The ESP itself is initially announced to clients as 'esp8266.local', if this host domain + is already used in the local network, another host domain is negociated. Keep an + eye to the serial output to learn the final host domain for the HTTP service. + The service itself is is announced as 'host domain'._http._tcp.local. + The HTTP server delivers a short greeting and the current list of other 'HTTP' services (not updated). + The web server code is taken nearly 1:1 from the 'mDNS_Web_Server.ino' example. + Point your browser to 'host domain'.local to see this web page. + + Instructions: + - Update WiFi SSID and password as necessary. + - Flash the sketch to the ESP8266 board + - Install host software: + - For Linux, install Avahi (http://avahi.org/). + - For Windows, install Bonjour (http://www.apple.com/support/bonjour/). + - For Mac OSX and iOS support is built in through Bonjour already. + - Use a browser like 'Safari' to see the page at http://'host domain'.local. + +*/ + + +#ifndef STASSID +#define STASSID "ssid" +#define STAPSK "psk" +#endif + + +#include <ESP8266WiFi.h> +#include <WiFiClient.h> +#include <ESP8266WebServer.h> + +/* + Include the clsMDNSHost (the library needs to be included also) + As LEA clsMDNSHost is experimantal in the ESP8266 environment currently, the + legacy clsMDNSHost is defaulted in th include file. + There are two ways to access LEA clsMDNSHost: + 1. Prepend every declaration and call to global declarations or functions with the namespace, like: + 'LEAmDNS:clsMDNSHost::hMDNSService hMDNSService;' + This way is used in the example. But be careful, if the namespace declaration is missing + somewhere, the call might go to the legacy implementation... + 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. + +*/ +#include <ESP8266mDNS.h> +//#include "LocalDefines.h" +//#include "Netdump.h" +//using namespace NetCapture; +/* + Global defines and vars +*/ + +clsMDNSHost MDNSv2; + +#define SERVICE_PORT 80 // HTTP port + +char* pcHostDomain = 0; // Negociated host domain +bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain +clsMDNSHost::clsService* hMDNSService = 0; // The handle of the http service in the MDNS responder +clsMDNSHost::clsQuery* hMDNSServiceQuery = 0; // The handle of the 'http.tcp' service query in the MDNS responder + +const String cstrNoHTTPServices = "Currently no 'http.tcp' services in the local network!<br/>"; +String strHTTPServices = cstrNoHTTPServices; + +// HTTP server at port 'SERVICE_PORT' will respond to HTTP requests +ESP8266WebServer server(SERVICE_PORT); + + +/* + setStationHostname +*/ +bool setStationHostname(const char* p_pcHostname) +{ + + if (p_pcHostname) + { + WiFi.hostname(p_pcHostname); + Serial.printf("setStationHostname: Station hostname is set to '%s'\n", p_pcHostname); + return true; + } + return false; +} + +void MDNSServiceQueryCallback(const clsMDNSHost::clsQuery& p_Query, + const clsMDNSHost::clsQuery::clsAnswer& p_Answer, + clsMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, + bool p_bSetContent) +{ + Serial.printf("CB MDNSServiceQueryCallback\n"); + + String answerInfo; + clsMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType mask = 0; + if (p_QueryAnswerTypeFlags & (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain) + { + answerInfo += "(ServiceDomain "; + answerInfo += p_Answer.m_ServiceDomain.c_str(); + answerInfo += ")"; + mask |= (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain; + } + if (p_QueryAnswerTypeFlags & (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort) + { + answerInfo += "(HostDomainAndPort "; + answerInfo += p_Answer.m_HostDomain.c_str(); + answerInfo += ")"; + mask |= (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort; + } + if (p_QueryAnswerTypeFlags & (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address) + { + answerInfo += "(IP4Address "; + for (auto ip : p_Answer.m_IPv4Addresses) + { + answerInfo += "- "; + answerInfo += ip->m_IPAddress.toString(); + } + answerInfo += ")"; + mask |= (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address; + } +#ifdef MDNS_IPV6_SUPPORT + if (p_QueryAnswerTypeFlags & (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address) + { + answerInfo += "(IP6Address "; + for (auto ip : p_Answer.m_IPv6Addresses) + { + answerInfo += "- "; + answerInfo += ip->m_IPAddress.toString(); + } + answerInfo += ")"; + mask |= (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address; + } +#endif // MDNS_IPV6_SUPPORT + if (p_QueryAnswerTypeFlags & (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts) + { + answerInfo += "(TXT "; + for (auto kv : p_Answer.m_Txts.m_Txts) + { + answerInfo += "kv: "; + answerInfo += kv->m_pcKey; + answerInfo += ": "; + answerInfo += kv->m_pcValue; + } + answerInfo += ")"; + mask |= (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts; + } + if (p_QueryAnswerTypeFlags & ~mask) + { + answerInfo += "(other flags are set)"; + } + +#if 0 + switch (p_QueryAnswerTypeFlags) + { + case static_cast<clsMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain): + answerInfo = "ServiceDomain " + String(p_Answer.m_ServiceDomain.c_str()); + break; + + case static_cast<clsMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort): + answerInfo = "HostDomainAndPort " + String(p_Answer.m_HostDomain.c_str()) + ":" + String(p_Answer.m_u16Port); + break; + case static_cast<clsMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address): + answerInfo = "IP4Address "; + for (auto ip : p_Answer.m_IPv4Addresses) + { + answerInfo += "- " + ip->m_IPAddress.toString(); + }; + break; + case static_cast<clsMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts): + answerInfo = "TXT "; + for (auto kv : p_Answer.m_Txts.m_Txts) + { + answerInfo += "\nkv : " + String(kv->m_pcKey) + " : " + String(kv->m_pcValue); + } + break; + default : + answerInfo = "Unknown Answertype " + String(p_QueryAnswerTypeFlags); + + } +#endif + + Serial.printf("Answer %s %s\n", answerInfo.c_str(), p_bSetContent ? "Modified" : "Deleted"); +} + +/* + MDNSServiceProbeResultCallback + Probe result callback for Services +*/ + +void serviceProbeResult(clsMDNSHost::clsService& p_rMDNSService, + const char* p_pcInstanceName, + bool p_bProbeResult) +{ + Serial.printf("MDNSServiceProbeResultCallback: Service %s probe %s\n", p_pcInstanceName, (p_bProbeResult ? "succeeded." : "failed!")); +} + +/* + MDNSHostProbeResultCallback + + Probe result callback for the host domain. + If the domain is free, the host domain is set and the http service is + added. + If the domain is already used, a new name is created and the probing is + restarted via p_pclsMDNSHost->setHostname(). + +*/ + +void hostProbeResult(clsMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bProbeResult) +{ + + Serial.printf("MDNSHostProbeResultCallback: Host domain '%s.local' is %s\n", p_pcDomainName.c_str(), (p_bProbeResult ? "free" : "already USED!")); + + if (true == p_bProbeResult) + { + // Set station hostname + setStationHostname(pcHostDomain); + Serial.printf("settng hostname = '%s'\n", pcHostDomain); + + if (!bHostDomainConfirmed) + { + // Hostname free -> setup clock service + bHostDomainConfirmed = true; + + if (!hMDNSService) + { + Serial.printf("adding service tcp.http port %d\n", SERVICE_PORT); + // Add a 'http.tcp' service to port 'SERVICE_PORT', using the host domain as instance domain + hMDNSService = MDNSv2.addService(0, "http", "tcp", SERVICE_PORT, serviceProbeResult); + + if (hMDNSService) + { + Serial.printf("hMDNSService\n"); + hMDNSService->setProbeResultCallback(serviceProbeResult); + // MDNSv2.setServiceProbeResultCallback(hMDNSService, serviceProbeResult); + + // Add some '_http._tcp' protocol specific MDNS service TXT items + // See: http://www.dns-sd.org/txtrecords.html#http + hMDNSService->addServiceTxt("user", "x"); + hMDNSService->addServiceTxt("password", "y"); + hMDNSService->addServiceTxt("path", "/"); + } + else + Serial.printf("hMDNSService=0 ??\n"); + + // Install dynamic 'http.tcp' service query + if (!hMDNSServiceQuery) + { + Serial.printf("installing hMDNSServiceQuery\n"); + hMDNSServiceQuery = MDNSv2.installServiceQuery("http", "tcp", MDNSServiceQueryCallback); + if (hMDNSServiceQuery) + { + Serial.printf("MDNSProbeResultCallback: Service query for 'http.tcp' services installed.\n"); + Serial.printf("hMDNSServiceQuery:%p/%p\n", hMDNSServiceQuery->m_fnCallbackAnswer, MDNSServiceQueryCallback); + } + else + { + Serial.printf("MDNSProbeResultCallback: FAILED to install service query for 'http.tcp' services!\n"); + } + } + } + } + } + else + { + // Change hostname, use '-' as divider between base name and index + if (clsMDNSHost::indexDomainName(pcHostDomain, "-", 0)) + { + MDNSv2.setHostName(pcHostDomain); + } + else + { + Serial.println("MDNSProbeResultCallback: FAILED to update hostname!"); + } + } +} + +/* + HTTP request function (not found is handled by server) +*/ +void handleHTTPRequest() +{ + Serial.println(""); + Serial.println("HTTP Request"); + + IPAddress ip = server.client().localIP(); + String ipStr = ip.toString(); + String s = "<!DOCTYPE HTML>\r\n<html><h3><head>Hello from "; + s += WiFi.hostname() + ".local at " + server.client().localIP().toString() + "</h3></head>"; + s += "<br/><h4>Local HTTP services are :</h4>"; + s += "<ol>"; + /* + for (auto info : MDNSv2.answerInfo(hMDNSServiceQuery)) { + s += "<li>"; + s += info.serviceDomain(); + if (info.hostDomainAvailable()) { + s += "<br/>Hostname: "; + s += String(info.hostDomain()); + s += (info.hostPortAvailable()) ? (":" + String(info.hostPort())) : ""; + } + if (info.IP4AddressAvailable()) { + s += "<br/>IP4:"; + for (auto ip : info.IP4Adresses()) { + s += " " + ip.toString(); + } + } + if (info.txtAvailable()) { + s += "<br/>TXT:<br/>"; + for (auto kv : info.keyValues()) { + s += "\t" + String(kv.first) + " : " + String(kv.second) + "<br/>"; + } + } + s += "</li>"; + + } + */ + s += "</ol><br/>"; + + Serial.println("Sending 200"); + server.send(200, "text/html", s); + Serial.println("Done with request"); +} + +//Netdump nd(Netdump::interface::LWIP); + + +/* + setup +*/ +void setup(void) +{ + Serial.begin(115200); + // nd.printDump(Serial, Packet::PacketDetail::NONE, [](const Packet& p){return(p.getInOut() && p.isMDNS());}); + Serial.setDebugOutput(false); + + // Connect to WiFi network + WiFi.mode(WIFI_AP_STA); + WiFi.softAP("Soft1"); + WiFi.begin(STASSID, STAPSK); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) + { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to "); + Serial.println(STASSID); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + // Setup HTTP server + server.on("/", handleHTTPRequest); + + // Setup MDNS responders + MDNSv2.setProbeResultCallback(hostProbeResult); + + // Init the (currently empty) host domain string with 'esp8266' + MDNSv2.begin("esp8266_v2"); + /* + if ((!clsMDNSHost::indexDomain(pcHostDomain, 0, "esp8266")) || + (!MDNSv2.begin(pcHostDomain))) { + Serial.println(" Error setting up MDNS responder!"); + while (1) { // STOP + delay(1000); + } + } + */ + Serial.println("MDNS responder started"); + + // Start HTTP server + server.begin(); + Serial.println("HTTP server started"); +} + +void loop(void) +{ + // Check if a request has come in + server.handleClient(); + // Allow MDNS processing + MDNSv2.update(); +} + + + From 59a6ae446f5f1cfda4a569f3cd8f0da529944a15 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 12 Jun 2020 00:17:32 +0200 Subject: [PATCH 046/152] remove useless debug messages --- libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index 870b00e24e..1d15a04137 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -212,19 +212,10 @@ bool clsLEAMDNSHost::clsBackbone::_processUDPInput(void) if (!m_bDelayUDPProcessing) { - DEBUG_EX_INFO(uint32_t u32LoopCounter = 0; IPAddress remoteIPAddr;); while ((m_pUDPContext) && (m_pUDPContext->next())) { clsLEAMDNSHost* pHost = _findHost(); - DEBUG_EX_INFO_IF(u32LoopCounter++, - DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Multi-Loop (%u)!\n"), _DH(), u32LoopCounter); - DEBUG_EX_INFO_IF((remoteIPAddr.isSet()) && (remoteIPAddr != m_pUDPContext->getRemoteAddress()), - DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Changed IP address %s->%s!\n"), - _DH(), - remoteIPAddr.toString().c_str(), - m_pUDPContext->getRemoteAddress().toString().c_str()))); - DEBUG_EX_INFO(remoteIPAddr = m_pUDPContext->getRemoteAddress()); bResult = pHost->_processUDPInput(); From accbd9ce921bfc131a92f6e00322e74742adc1b9 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 12 Jun 2020 10:39:02 +0200 Subject: [PATCH 047/152] fix debug macros --- .../mDNS_ServiceMonitor_v2_test.ino | 1 - libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h | 29 ++++++++++++++----- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino index 1386b072b0..2bae65501d 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino @@ -257,7 +257,6 @@ void hostProbeResult(clsMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bP if (hMDNSServiceQuery) { Serial.printf("MDNSProbeResultCallback: Service query for 'http.tcp' services installed.\n"); - Serial.printf("hMDNSServiceQuery:%p/%p\n", hMDNSServiceQuery->m_fnCallbackAnswer, MDNSServiceQueryCallback); } else { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h index de0021d000..e67e6c03d0 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h @@ -36,14 +36,16 @@ Enable class debug functions */ #define ESP_8266_MDNS_INCLUDE -#define DEBUG_ESP_MDNS_RESPONDER +//#define DEBUG_ESP_MDNS_RESPONDER /* Enable/disable debug trace macros */ + #if defined(DEBUG_ESP_PORT) #define DEBUG_ESP_MDNS_ERR #endif + #if defined(DEBUG_ESP_PORT) && defined(DEBUG_ESP_MDNS_RESPONDER) #define DEBUG_ESP_MDNS_INFO #define DEBUG_ESP_MDNS_INFO2 @@ -51,7 +53,14 @@ //#define DEBUG_ESP_MDNS_RX #endif +#ifdef DEBUG_ESP_PORT +#define DEBUG_OUTPUT DEBUG_ESP_PORT +#else +#define DEBUG_OUTPUT Serial +#endif + #ifdef DEBUG_ESP_MDNS_RESPONDER + #ifdef DEBUG_ESP_MDNS_INFO #define DEBUG_EX_INFO(A) A #define DEBUG_EX_INFO_IF(C,A...) do if (C) { A; } while (0) @@ -59,6 +68,7 @@ #define DEBUG_EX_INFO(A) #define DEBUG_EX_INFO_IF(C,A...) #endif + #ifdef DEBUG_ESP_MDNS_INFO2 #define DEBUG_EX_INFO2(A) A #define DEBUG_EX_INFO2_IF(C,A...) do if (C) { A; } while (0) @@ -66,6 +76,7 @@ #define DEBUG_EX_INFO2(A) #define DEBUG_EX_INFO2_IF(C,A...) #endif + #ifdef DEBUG_ESP_MDNS_ERR #define DEBUG_EX_ERR(A) A #define DEBUG_EX_ERR_IF(C,A...) do if (C) { A; } while (0) @@ -73,29 +84,31 @@ #define DEBUG_EX_ERR(A) #define DEBUG_EX_ERR_IF(C,A...) #endif + #ifdef DEBUG_ESP_MDNS_TX #define DEBUG_EX_TX(A) do { A; } while (0) #else #define DEBUG_EX_TX(A) #endif + #ifdef DEBUG_ESP_MDNS_RX #define DEBUG_EX_RX(A) do { A; } while (0) #else #define DEBUG_EX_RX(A) #endif -#ifdef DEBUG_ESP_PORT -#define DEBUG_OUTPUT DEBUG_ESP_PORT -#else -#define DEBUG_OUTPUT Serial -#endif -#else +#else // !defined(DEBUG_ESP_MDNS_RESPONDER) + #define DEBUG_EX_INFO(A) +#define DEBUG_EX_INFO_IF(C,A...) #define DEBUG_EX_INFO2(A) +#define DEBUG_EX_INFO2_IF(C,A...) #define DEBUG_EX_ERR(A) +#define DEBUG_EX_ERR_IF(C,A...) #define DEBUG_EX_TX(A) #define DEBUG_EX_RX(A) -#endif + +#endif // !defined(DEBUG_ESP_MDNS_RESPONDER) /* Enable/disable the usage of the F() macro in debug trace printf calls. From 1638402a1a4282b5a12ba683426cdc1059909f54 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 12 Jun 2020 12:27:13 +0200 Subject: [PATCH 048/152] always enable mdns error message when debug on serial port is enabled --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 29 +++++++------------ .../ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp | 4 +-- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 4 +-- .../ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h | 17 +---------- 5 files changed, 17 insertions(+), 39 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index ba2eae1800..af004c3e19 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -747,26 +747,19 @@ bool clsLEAMDNSHost::removeQuery(clsLEAMDNSHost::clsQuery * p_pMDNSQuery) */ bool clsLEAMDNSHost::update(void) { - bool bResult = false; + if (!_updateProbeStatus()) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: FAILED\n"), _DH())); + return false; + } - bResult = (_updateProbeStatus() && _checkQueryCache()); -/* - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) - if (netif_is_up(pNetIf)) - { - //if (clsBackbone::sm_pBackbone->setDelayUDPProcessing(true)) - //{ - if (_checkQueryCache(pNetIf)) - { - bResult = true; - } + if (!_checkQueryCache()) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: FAILED\n"), _DH())); + return false; + } - // clsBackbone::sm_pBackbone->setDelayUDPProcessing(false); - //} - } -*/ - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s update: FAILED (Not connected?)!\n"), _DH())); - return bResult; + return true; } /* diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp index 50a7d07594..d638bf209a 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp @@ -34,7 +34,7 @@ namespace experimental { -#ifdef DEBUG_ESP_MDNS_RESPONDER +#ifdef DEBUG_ESP_PORT /* clsLEAmDNS2_Host::_DH @@ -315,7 +315,7 @@ const char* clsLEAMDNSHost::_NSECBitmap2String(const clsNSECBitmap* p_pNSECBitma return acFlagsString; // 31 } -#endif // DEBUG_ESP_MDNS_RESPONDER +#endif // DEBUG_ESP_PORT } // namespace MDNSImplementation diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index b7a800d393..0be8d6bf17 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -1451,7 +1451,7 @@ bool clsLEAMDNSHost::_udpAppend32(uint32_t p_u32Value) return (_udpAppendBuffer((unsigned char*)&p_u32Value, sizeof(p_u32Value))); } -#ifdef DEBUG_ESP_MDNS_RESPONDER +#ifdef DEBUG_ESP_PORT /* MDNSResponder::_udpDump @@ -1500,7 +1500,7 @@ bool clsLEAMDNSHost::_udpDump(unsigned p_uOffset, } return true; } -#endif +#endif // DEBUG_ESP_PORT /** diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index 1d15a04137..d3ae03ad1f 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -239,7 +239,7 @@ bool clsLEAMDNSHost::clsBackbone::_processUDPInput(void) MISC */ -#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_MDNS_RESPONDER +#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_PORT /* clsLEAmDNS2_Host::clsBackbone::_DH diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h index e67e6c03d0..30f82b03b3 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h @@ -56,11 +56,9 @@ #ifdef DEBUG_ESP_PORT #define DEBUG_OUTPUT DEBUG_ESP_PORT #else -#define DEBUG_OUTPUT Serial +#define DEBUG_OUTPUT Serialx #endif -#ifdef DEBUG_ESP_MDNS_RESPONDER - #ifdef DEBUG_ESP_MDNS_INFO #define DEBUG_EX_INFO(A) A #define DEBUG_EX_INFO_IF(C,A...) do if (C) { A; } while (0) @@ -97,19 +95,6 @@ #define DEBUG_EX_RX(A) #endif -#else // !defined(DEBUG_ESP_MDNS_RESPONDER) - -#define DEBUG_EX_INFO(A) -#define DEBUG_EX_INFO_IF(C,A...) -#define DEBUG_EX_INFO2(A) -#define DEBUG_EX_INFO2_IF(C,A...) -#define DEBUG_EX_ERR(A) -#define DEBUG_EX_ERR_IF(C,A...) -#define DEBUG_EX_TX(A) -#define DEBUG_EX_RX(A) - -#endif // !defined(DEBUG_ESP_MDNS_RESPONDER) - /* Enable/disable the usage of the F() macro in debug trace printf calls. There needs to be an PGM comptible printf function to use this. From 79efe995d183e16d033685772095e4372eda26f1 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 12 Jun 2020 12:29:01 +0200 Subject: [PATCH 049/152] fix crash in mDNS_ServiceMonitor_v2_test.ino --- .../mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino index 2bae65501d..9b14e22a85 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino @@ -221,7 +221,7 @@ void hostProbeResult(clsMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bP { // Set station hostname setStationHostname(pcHostDomain); - Serial.printf("settng hostname = '%s'\n", pcHostDomain); + Serial.printf("setting hostname = '%s'\n", pcHostDomain?: "nullptr"); if (!bHostDomainConfirmed) { From bb08c8cb9cd10678ac3b868077ae8a4876e6e1fe Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 12 Jun 2020 14:30:08 +0200 Subject: [PATCH 050/152] temporarily disable ipv6 --- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index e5e21d4c08..2a9fa30295 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -110,7 +110,8 @@ #define MDNS_IPV4_SUPPORT #if LWIP_IPV6 -#define MDNS_IPV6_SUPPORT // If we've got IPv6 support, then we need IPv6 support :-) +#pragma message "IPV6 for MDNS temporarily disabled" +//#define MDNS_IPV6_SUPPORT // If we've got IPv6 support, then we need IPv6 support :-) #endif namespace esp8266 From 5505446b05cf8619a5bf55a33fb89f4603cf45da Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 12 Jun 2020 18:52:35 +0200 Subject: [PATCH 051/152] reintroduce `delay()` without `can_yield()` calls --- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 3 +-- libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 12 ++++++------ libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 2a9fa30295..e5e21d4c08 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -110,8 +110,7 @@ #define MDNS_IPV4_SUPPORT #if LWIP_IPV6 -#pragma message "IPV6 for MDNS temporarily disabled" -//#define MDNS_IPV6_SUPPORT // If we've got IPv6 support, then we need IPv6 support :-) +#define MDNS_IPV6_SUPPORT // If we've got IPv6 support, then we need IPv6 support :-) #endif namespace esp8266 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 0be8d6bf17..a0cb00a729 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -117,9 +117,9 @@ bool clsLEAMDNSHost::_sendMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParamete (Serial.println("Did send UC"), true)*/); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage (V4): FAILED!\n"), _DH());); -#if 0 +#if 1 if ((clsConsts::u32SendCooldown) && - (can_yield())) + 1)//(can_yield())) { delay(clsConsts::u32SendCooldown); } @@ -188,9 +188,9 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe (Serial.println("Did send MC V4"), true)*/); DEBUG_EX_ERR(if (!bIPv4Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (V4): FAILED!\n"), _DH());); -#if 0 +#if 1 if ((clsConsts::u32SendCooldown) && - (can_yield())) + 1)//(can_yield())) { delay(clsConsts::u32SendCooldown); } @@ -216,9 +216,9 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe (Serial.println("Did send MC V6"), true)*/); DEBUG_EX_ERR(if (!bIPv6Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (IPv6): FAILED! (%s, %s, %s)\n"), _DH(), (_getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet() ? "1" : "0"), (bPrepareMessage ? "1" : "0"), (bUDPContextSend ? "1" : "0"));); -#if 0 +#if 1 if ((clsConsts::u32SendCooldown) && - (can_yield())) + 1)//(can_yield())) { delay(clsConsts::u32SendCooldown); } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h index 30f82b03b3..312a03d045 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h @@ -36,7 +36,7 @@ Enable class debug functions */ #define ESP_8266_MDNS_INCLUDE -//#define DEBUG_ESP_MDNS_RESPONDER +//#define DEBUG_ESP_MDNS_RESPONDER // force debug, arduino IDE uses DEBUG_ESP_MDNS /* Enable/disable debug trace macros @@ -46,7 +46,7 @@ #define DEBUG_ESP_MDNS_ERR #endif -#if defined(DEBUG_ESP_PORT) && defined(DEBUG_ESP_MDNS_RESPONDER) +#if defined(DEBUG_ESP_PORT) && (defined(DEBUG_ESP_MDNS) || defined(DEBUG_ESP_MDNS_RESPONDER)) #define DEBUG_ESP_MDNS_INFO #define DEBUG_ESP_MDNS_INFO2 //#define DEBUG_ESP_MDNS_TX From 4563fde8aa4d083724237bc6f2bb6565dc1a0935 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Fri, 12 Jun 2020 20:02:21 +0200 Subject: [PATCH 052/152] netdump as an option --- .../mDNS_ServiceMonitor_v2_test.ino | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino index 9b14e22a85..7e9926c50c 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino @@ -30,6 +30,8 @@ */ +#define END 0 // enable netdump + #ifndef STASSID #define STASSID "ssid" #define STAPSK "psk" @@ -40,6 +42,14 @@ #include <WiFiClient.h> #include <ESP8266WebServer.h> +#if END +#include <Netdump.h> +using namespace NetCapture; +Netdump nd; +#endif + + + /* Include the clsMDNSHost (the library needs to be included also) As LEA clsMDNSHost is experimantal in the ESP8266 environment currently, the @@ -326,7 +336,6 @@ void handleHTTPRequest() Serial.println("Done with request"); } -//Netdump nd(Netdump::interface::LWIP); /* @@ -378,6 +387,11 @@ void setup(void) // Start HTTP server server.begin(); Serial.println("HTTP server started"); + +#if END + nd.printDump(Serial, Packet::PacketDetail::FULL); +#endif + } void loop(void) From 6a83937eb20c14ffde8380e0504c3e9a5bcec7ab Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sat, 13 Jun 2020 12:42:31 +0200 Subject: [PATCH 053/152] change mdns service names in test example --- .../mDNS_ServiceMonitor_v2_test.ino | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino index 7e9926c50c..a74e14ce86 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino @@ -13,7 +13,7 @@ The ESP itself is initially announced to clients as 'esp8266.local', if this host domain is already used in the local network, another host domain is negociated. Keep an eye to the serial output to learn the final host domain for the HTTP service. - The service itself is is announced as 'host domain'._http._tcp.local. + The service itself is is announced as 'host domain'._sapuducul._tcp.local. The HTTP server delivers a short greeting and the current list of other 'HTTP' services (not updated). The web server code is taken nearly 1:1 from the 'mDNS_Web_Server.ino' example. Point your browser to 'host domain'.local to see this web page. @@ -76,8 +76,8 @@ clsMDNSHost MDNSv2; char* pcHostDomain = 0; // Negociated host domain bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain -clsMDNSHost::clsService* hMDNSService = 0; // The handle of the http service in the MDNS responder -clsMDNSHost::clsQuery* hMDNSServiceQuery = 0; // The handle of the 'http.tcp' service query in the MDNS responder +clsMDNSHost::clsService* hMDNSService = 0; // The handle of the sapuducu service in the MDNS responder +clsMDNSHost::clsQuery* hMDNSServiceQuery = 0; // The handle of the 'espclk.tcp' service query in the MDNS responder const String cstrNoHTTPServices = "Currently no 'http.tcp' services in the local network!<br/>"; String strHTTPServices = cstrNoHTTPServices; @@ -240,9 +240,9 @@ void hostProbeResult(clsMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bP if (!hMDNSService) { - Serial.printf("adding service tcp.http port %d\n", SERVICE_PORT); - // Add a 'http.tcp' service to port 'SERVICE_PORT', using the host domain as instance domain - hMDNSService = MDNSv2.addService(0, "http", "tcp", SERVICE_PORT, serviceProbeResult); + Serial.printf("adding service tcp.sapuducu port %d\n", SERVICE_PORT); + // Add a 'sapuducu.tcp' service to port 'SERVICE_PORT', using the host domain as instance domain + hMDNSService = MDNSv2.addService(0, "sapuducu", "tcp", SERVICE_PORT, serviceProbeResult); if (hMDNSService) { @@ -250,7 +250,7 @@ void hostProbeResult(clsMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bP hMDNSService->setProbeResultCallback(serviceProbeResult); // MDNSv2.setServiceProbeResultCallback(hMDNSService, serviceProbeResult); - // Add some '_http._tcp' protocol specific MDNS service TXT items + // Add some '_sapuducu._tcp' protocol specific MDNS service TXT items // See: http://www.dns-sd.org/txtrecords.html#http hMDNSService->addServiceTxt("user", "x"); hMDNSService->addServiceTxt("password", "y"); @@ -259,18 +259,18 @@ void hostProbeResult(clsMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bP else Serial.printf("hMDNSService=0 ??\n"); - // Install dynamic 'http.tcp' service query + // Install dynamic 'espclk.tcp' service query if (!hMDNSServiceQuery) { Serial.printf("installing hMDNSServiceQuery\n"); - hMDNSServiceQuery = MDNSv2.installServiceQuery("http", "tcp", MDNSServiceQueryCallback); + hMDNSServiceQuery = MDNSv2.installServiceQuery("espclk", "tcp", MDNSServiceQueryCallback); if (hMDNSServiceQuery) { - Serial.printf("MDNSProbeResultCallback: Service query for 'http.tcp' services installed.\n"); + Serial.printf("MDNSProbeResultCallback: Service query for 'espclk.tcp' services installed.\n"); } else { - Serial.printf("MDNSProbeResultCallback: FAILED to install service query for 'http.tcp' services!\n"); + Serial.printf("MDNSProbeResultCallback: FAILED to install service query for 'espclk.tcp' services!\n"); } } } @@ -394,12 +394,20 @@ void setup(void) } + + void loop(void) { // Check if a request has come in server.handleClient(); // Allow MDNS processing MDNSv2.update(); + + static esp8266::polledTimeout::periodicMs timeout(10000); + if (timeout.expired()) + { + Serial.printf("up=%lumn heap=%u\n", millis() / 1000 / 60, ESP.getFreeHeap()); + } } From cf74cc1f84ca76b8fc9827d0d35b6d789b9cb8e3 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 14 Jun 2020 14:58:08 +0200 Subject: [PATCH 054/152] brings parts of #7375, + sendTimeout() --- .../ESP8266WiFi/src/include/UdpContext.h | 41 +++++++++-- tests/host/common/include/UdpContext.h | 73 +++++++++++-------- 2 files changed, 77 insertions(+), 37 deletions(-) diff --git a/libraries/ESP8266WiFi/src/include/UdpContext.h b/libraries/ESP8266WiFi/src/include/UdpContext.h index a81384b2a7..c3a63380c4 100644 --- a/libraries/ESP8266WiFi/src/include/UdpContext.h +++ b/libraries/ESP8266WiFi/src/include/UdpContext.h @@ -31,6 +31,7 @@ void esp_schedule(); } #include <AddrList.h> +#include <PolledTimeout.h> #define PBUF_ALIGNER_ADJUST 4 #define PBUF_ALIGNER(x) ((void*)((((intptr_t)(x))+3)&~3)) @@ -419,7 +420,16 @@ class UdpContext return size; } - bool send(CONST ip_addr_t* addr = 0, uint16_t port = 0) + void cancelBuffer () + { + if (_tx_buf_head) + pbuf_free(_tx_buf_head); + _tx_buf_head = 0; + _tx_buf_cur = 0; + _tx_buf_offset = 0; + } + + err_t trySend(CONST ip_addr_t* addr = 0, uint16_t port = 0, bool keepBuffer = true) { size_t data_size = _tx_buf_offset; pbuf* tx_copy = pbuf_alloc(PBUF_TRANSPORT, data_size, PBUF_RAM); @@ -435,16 +445,12 @@ class UdpContext data_size -= will_copy; } } - if (_tx_buf_head) - pbuf_free(_tx_buf_head); - _tx_buf_head = 0; - _tx_buf_cur = 0; - _tx_buf_offset = 0; + if (!keepBuffer) + cancelBuffer(); if(!tx_copy){ - return false; + return ERR_MEM; } - if (!addr) { addr = &_pcb->remote_ip; port = _pcb->remote_port; @@ -463,6 +469,25 @@ class UdpContext _pcb->ttl = old_ttl; #endif pbuf_free(tx_copy); + if (err == ERR_OK) + cancelBuffer(); + return err; + } + + bool send(CONST ip_addr_t* addr = 0, uint16_t port = 0) + { + return trySend(addr, port, /* don't keep buffer */false) == ERR_OK; + } + + bool sendTimeout(CONST ip_addr_t* addr, uint16_t port, + esp8266::polledTimeout::oneShotFastUs::timeType timeoutMs) + { + err_t err; + esp8266::polledTimeout::oneShotFastMs timeout(timeoutMs); + while (((err = trySend(addr, port)) != ERR_OK) && !timeout) + delay(0); + if (err != ERR_OK) + cancelBuffer(); return err == ERR_OK; } diff --git a/tests/host/common/include/UdpContext.h b/tests/host/common/include/UdpContext.h index 12c41b433e..775dd5852e 100644 --- a/tests/host/common/include/UdpContext.h +++ b/tests/host/common/include/UdpContext.h @@ -1,22 +1,22 @@ /* - UdpContext.h - emulation of UDP connection handling on top of lwIP + UdpContext.h - emulation of UDP connection handling on top of lwIP - Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef UDPCONTEXT_H #define UDPCONTEXT_H @@ -55,12 +55,13 @@ class UdpContext void unref() { - if(--_refcnt == 0) { + if (--_refcnt == 0) + { delete this; } } - bool connect (const ip_addr_t* addr, uint16_t port) + bool connect(const ip_addr_t* addr, uint16_t port) { _dst = *addr; _dstport = port; @@ -111,7 +112,8 @@ class UdpContext // warning: handler is called from tcp stack context // esp_yield and non-reentrant functions which depend on it will fail - void onRx(rxhandler_t handler) { + void onRx(rxhandler_t handler) + { _on_rx = handler; } @@ -135,7 +137,8 @@ class UdpContext mockUDPSwallow(pos, _inbuf, _inbufsize); } - bool isValidOffset(const size_t pos) const { + bool isValidOffset(const size_t pos) const + { return pos <= _inbufsize; } @@ -176,7 +179,7 @@ class UdpContext int read() { char c; - return read(&c, 1)? c: -1; + return read(&c, 1) ? c : -1; } size_t read(char* dst, size_t size) @@ -187,7 +190,7 @@ class UdpContext int peek() { char c; - return mockUDPPeekBytes(_sock, &c, 1, _timeout_ms, _inbuf, _inbufsize)?: -1; + return mockUDPPeekBytes(_sock, &c, 1, _timeout_ms, _inbuf, _inbufsize) ? : -1; } void flush() @@ -198,7 +201,7 @@ class UdpContext _inbufsize = 0; } - size_t append (const char* data, size_t size) + size_t append(const char* data, size_t size) { if (size + _outbufsize > sizeof _outbuf) { @@ -211,16 +214,28 @@ class UdpContext return size; } - bool send (ip_addr_t* addr = 0, uint16_t port = 0) + err_t trySend(ip_addr_t* addr = 0, uint16_t port = 0, bool keepBuffer = true) + { + uint32_t dst = addr ? addr->addr : _dst.addr; + uint16_t dstport = port ? : _dstport; + size_t wrt = mockUDPWrite(_sock, (const uint8_t*)_outbuf, _outbufsize, _timeout_ms, dst, dstport); + err_t ret = _outbufsize ? ERR_OK : ERR_ABRT; + if (!keepBuffer || wrt == _outbufsize) + cancelBuffer(); + return ret; + } + + void cancelBuffer() { - uint32_t dst = addr? addr->addr: _dst.addr; - uint16_t dstport = port?: _dstport; - size_t ret = mockUDPWrite(_sock, (const uint8_t*)_outbuf, _outbufsize, _timeout_ms, dst, dstport); _outbufsize = 0; - return ret > 0; } - void mock_cb (void) + bool send(ip_addr_t* addr = 0, uint16_t port = 0) + { + return trySend(addr, port, false) == ERR_OK; + } + + void mock_cb(void) { if (_on_rx) _on_rx(); } @@ -231,7 +246,7 @@ class UdpContext private: - void translate_addr () + void translate_addr() { if (addrsize == 4) { @@ -263,7 +278,7 @@ class UdpContext uint8_t addr[16]; }; -extern "C" inline err_t igmp_joingroup (const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) +extern "C" inline err_t igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) { (void)ifaddr; UdpContext::staticMCastAddr = groupaddr->addr; From f8533fc63aa474c106eb049a77ffab35a057661f Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 14 Jun 2020 14:58:54 +0200 Subject: [PATCH 055/152] use udp::sendTimeout --- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 3 ++- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 15 ++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index e5e21d4c08..6e89556bad 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -179,7 +179,8 @@ class clsLEAMDNSHost #else static const uint8_t u8DNS_RRTYPE_NSEC = 0x2F; #endif - static const uint32_t u32SendCooldown = 50; // Delay (ms) between to 'UDPContext->send()' calls + //static const uint32_t u32SendCooldown = 50; // Delay (ms) between to 'UDPContext->send()' calls + static constexpr uint32_t u32SendTimeoutMs = 5; // timeout (ms) for a call to `UDPContext->send()` (1.5ms=1460@1Mbits/s) }; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index a0cb00a729..7642c19221 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -113,11 +113,10 @@ bool clsLEAMDNSHost::_sendMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParamete bResult = ((ipRemote.isSet()) && (_prepareMessage(pNetIf, p_rSendParameter)) && - (m_pUDPContext->send(ipRemote, m_pUDPContext->getRemotePort())) /*&& + (m_pUDPContext->sendTimeout(ipRemote, m_pUDPContext->getRemotePort(), clsConsts::u32SendTimeoutMs)) /*&& (Serial.println("Did send UC"), true)*/); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage (V4): FAILED!\n"), _DH());); - -#if 1 +#if 0 if ((clsConsts::u32SendCooldown) && 1)//(can_yield())) { @@ -183,12 +182,11 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe DEBUG_EX_INFO(if (!_getResponderIPAddress(pNetIf, enuIPProtocolType::V4)) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast IPv4: NO IPv4 address!.\n"), _DH());); bIPv4Result = ((_prepareMessage(pNetIf, p_rSendParameter)) && (m_pUDPContext->setMulticastInterface(pNetIf), true) && - (m_pUDPContext->send(ip4MulticastAddress, DNS_MQUERY_PORT)) && + (m_pUDPContext->sendTimeout(ip4MulticastAddress, DNS_MQUERY_PORT, clsConsts::u32SendTimeoutMs)) && (m_pUDPContext->setMulticastInterface(0), true) /*&& (Serial.println("Did send MC V4"), true)*/); DEBUG_EX_ERR(if (!bIPv4Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (V4): FAILED!\n"), _DH());); - -#if 1 +#if 0 if ((clsConsts::u32SendCooldown) && 1)//(can_yield())) { @@ -211,12 +209,11 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe ); bIPv6Result = ((DEBUG_EX_ERR(bPrepareMessage =)_prepareMessage(pNetIf, p_rSendParameter)) && (m_pUDPContext->setMulticastInterface(pNetIf), true) && - (DEBUG_EX_ERR(bUDPContextSend =)m_pUDPContext->send(ip6MulticastAddress, DNS_MQUERY_PORT)) && + (DEBUG_EX_ERR(bUDPContextSend =)m_pUDPContext->sendTimeout(ip6MulticastAddress, DNS_MQUERY_PORT, clsConsts::u32SendTimeoutMs)) && (m_pUDPContext->setMulticastInterface(0), true) /*&& (Serial.println("Did send MC V6"), true)*/); DEBUG_EX_ERR(if (!bIPv6Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (IPv6): FAILED! (%s, %s, %s)\n"), _DH(), (_getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet() ? "1" : "0"), (bPrepareMessage ? "1" : "0"), (bUDPContextSend ? "1" : "0"));); - -#if 1 +#if 0 if ((clsConsts::u32SendCooldown) && 1)//(can_yield())) { From 5c3d2b682c4d26435f2868eb8ad52299574c7034 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 14 Jun 2020 15:02:45 +0200 Subject: [PATCH 056/152] fix constant --- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 6e89556bad..8770d084c3 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -180,7 +180,7 @@ class clsLEAMDNSHost static const uint8_t u8DNS_RRTYPE_NSEC = 0x2F; #endif //static const uint32_t u32SendCooldown = 50; // Delay (ms) between to 'UDPContext->send()' calls - static constexpr uint32_t u32SendTimeoutMs = 5; // timeout (ms) for a call to `UDPContext->send()` (1.5ms=1460@1Mbits/s) + static constexpr uint32_t u32SendTimeoutMs = 25; // timeout (ms) for a call to `UDPContext->send()` (12ms=1460B@1Mb/s) }; From 54066fb8fe0492beeb07d59ca01b7197ce437d10 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 14 Jun 2020 15:09:26 +0200 Subject: [PATCH 057/152] +mock udp::sendTimeout() --- tests/host/common/include/UdpContext.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/host/common/include/UdpContext.h b/tests/host/common/include/UdpContext.h index 775dd5852e..cd3e453982 100644 --- a/tests/host/common/include/UdpContext.h +++ b/tests/host/common/include/UdpContext.h @@ -25,6 +25,7 @@ #include <MocklwIP.h> #include <IPAddress.h> +#include <PolledTimeout.h> class UdpContext; @@ -235,6 +236,18 @@ class UdpContext return trySend(addr, port, false) == ERR_OK; } + bool sendTimeout(ip_addr_t* addr, uint16_t port, + esp8266::polledTimeout::oneShotFastUs::timeType timeoutMs) + { + err_t err; + esp8266::polledTimeout::oneShotFastMs timeout(timeoutMs); + while (((err = trySend(addr, port)) != ERR_OK) && !timeout) + delay(0); + if (err != ERR_OK) + cancelBuffer(); + return err == ERR_OK; + } + void mock_cb(void) { if (_on_rx) _on_rx(); From 295f397baf48f8cf6cb5161c03243ac2a079fbfa Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 14 Jun 2020 15:16:54 +0200 Subject: [PATCH 058/152] fix typo --- libraries/ESP8266WiFi/src/include/UdpContext.h | 2 +- tests/host/common/include/UdpContext.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266WiFi/src/include/UdpContext.h b/libraries/ESP8266WiFi/src/include/UdpContext.h index c3a63380c4..9a429d9d85 100644 --- a/libraries/ESP8266WiFi/src/include/UdpContext.h +++ b/libraries/ESP8266WiFi/src/include/UdpContext.h @@ -480,7 +480,7 @@ class UdpContext } bool sendTimeout(CONST ip_addr_t* addr, uint16_t port, - esp8266::polledTimeout::oneShotFastUs::timeType timeoutMs) + esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs) { err_t err; esp8266::polledTimeout::oneShotFastMs timeout(timeoutMs); diff --git a/tests/host/common/include/UdpContext.h b/tests/host/common/include/UdpContext.h index cd3e453982..bf104bc40f 100644 --- a/tests/host/common/include/UdpContext.h +++ b/tests/host/common/include/UdpContext.h @@ -237,7 +237,7 @@ class UdpContext } bool sendTimeout(ip_addr_t* addr, uint16_t port, - esp8266::polledTimeout::oneShotFastUs::timeType timeoutMs) + esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs) { err_t err; esp8266::polledTimeout::oneShotFastMs timeout(timeoutMs); From bc10fbf55fd55a112fdf14df3e72f7d3d6c63dc1 Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Sun, 14 Jun 2020 15:22:25 +0200 Subject: [PATCH 059/152] Fix HTTP Request in servicemonitor example --- .../mDNS_ServiceMonitor_v2_test.ino | 85 ++++++++++--------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino index a74e14ce86..22407a4f6b 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino @@ -295,45 +295,54 @@ void hostProbeResult(clsMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bP */ void handleHTTPRequest() { - Serial.println(""); - Serial.println("HTTP Request"); - - IPAddress ip = server.client().localIP(); - String ipStr = ip.toString(); - String s = "<!DOCTYPE HTML>\r\n<html><h3><head>Hello from "; - s += WiFi.hostname() + ".local at " + server.client().localIP().toString() + "</h3></head>"; - s += "<br/><h4>Local HTTP services are :</h4>"; - s += "<ol>"; - /* - for (auto info : MDNSv2.answerInfo(hMDNSServiceQuery)) { - s += "<li>"; - s += info.serviceDomain(); - if (info.hostDomainAvailable()) { - s += "<br/>Hostname: "; - s += String(info.hostDomain()); - s += (info.hostPortAvailable()) ? (":" + String(info.hostPort())) : ""; - } - if (info.IP4AddressAvailable()) { - s += "<br/>IP4:"; - for (auto ip : info.IP4Adresses()) { - s += " " + ip.toString(); - } - } - if (info.txtAvailable()) { - s += "<br/>TXT:<br/>"; - for (auto kv : info.keyValues()) { - s += "\t" + String(kv.first) + " : " + String(kv.second) + "<br/>"; - } - } - s += "</li>"; - - } - */ - s += "</ol><br/>"; + Serial.println(""); + Serial.println("HTTP Request"); + + IPAddress ip = server.client().localIP(); + String ipStr = ip.toString(); + String s = "<!DOCTYPE HTML>\r\n<html><h3><head>Hello from "; + s += WiFi.hostname() + ".local at " + server.client().localIP().toString() + "</h3></head>"; + s += "<br/><h4>Local HTTP services are :</h4>"; + s += "<ol>"; + // hMDNSServiceQuery-> + + + for (auto info : hMDNSServiceQuery->answerAccessors()) { + s += "<li>"; + s += info.serviceDomain(); + + if (info.hostDomainAvailable()) { + s += "<br/>Hostname: "; + s += String(info.hostDomain()); + s += (info.hostPortAvailable()) ? (":" + String(info.hostPort())) : ""; + } + if (info.IPv4AddressAvailable()) { + s += "<br/>IPv4:"; + for (auto ip : info.IPv4Addresses()) { + s += " " + ip.toString(); + } + } +#ifdef MDNS_IPV6_SUPPORT + if (info.IPv6AddressAvailable()) { + s += "<br/>IPv6:"; + for (auto ip : info.IPv6Addresses()) { + s += " " + ip.toString(); + } + } +#endif + if (info.txtsAvailable()) { + s += "<br/>TXT:<br/>"; + for (auto kv : info.txtKeyValues()) { + s += "\t" + String(kv.first) + " : " + String(kv.second) + "<br/>"; + } + } + s += "</li>"; + } + s += "</ol><br/>"; - Serial.println("Sending 200"); - server.send(200, "text/html", s); - Serial.println("Done with request"); + Serial.println("Sending 200"); + server.send(200, "text/html", s); + Serial.println("Done with request"); } From 68d440975f857b7a9e387fb19749671b67488e5b Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 16 Jun 2020 16:01:02 +0200 Subject: [PATCH 060/152] emulation on host: adding key/value cmdline parameters usable in sketches --- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 2 +- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 5 +---- tests/host/common/Arduino.h | 7 +++++++ tests/host/common/ArduinoMain.cpp | 15 ++++++++++++++- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 8770d084c3..88d403baa8 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -180,7 +180,7 @@ class clsLEAMDNSHost static const uint8_t u8DNS_RRTYPE_NSEC = 0x2F; #endif //static const uint32_t u32SendCooldown = 50; // Delay (ms) between to 'UDPContext->send()' calls - static constexpr uint32_t u32SendTimeoutMs = 25; // timeout (ms) for a call to `UDPContext->send()` (12ms=1460B@1Mb/s) + static constexpr uint32_t u32SendTimeoutMs = 50; // timeout (ms) for a call to `UDPContext->send()` (12ms=1460B@1Mb/s) }; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 7642c19221..f54e6fa475 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -2029,10 +2029,7 @@ bool clsLEAMDNSHost::_writeMDNSAnswer_TXT(clsLEAMDNSHost::clsService& p_rService attributes.m_u16Class, (p_rSendParameter.m_bUnannounce ? 0 - : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL)), - p_rService.m_pcInstanceName, - p_rService.m_pcType, - p_rService.m_pcProtocol); + : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL))); ); _releaseTempServiceTxts(p_rService); diff --git a/tests/host/common/Arduino.h b/tests/host/common/Arduino.h index 4c0a8c6765..8735ecba6c 100644 --- a/tests/host/common/Arduino.h +++ b/tests/host/common/Arduino.h @@ -270,3 +270,10 @@ extern "C" void configTime(long timezone, int daylightOffset_sec, #include "pins_arduino.h" #endif /* Arduino_h */ + +#if __cplusplus +#include <WString.h> +#include <map> +#define MOCKARGS 1 +extern std::map<String,String> mockArgs; +#endif diff --git a/tests/host/common/ArduinoMain.cpp b/tests/host/common/ArduinoMain.cpp index 7bfcd97032..f507c081a1 100644 --- a/tests/host/common/ArduinoMain.cpp +++ b/tests/host/common/ArduinoMain.cpp @@ -54,6 +54,8 @@ int mock_port_shifter = MOCK_PORT_SHIFTER; static struct termios initial_settings; +std::map<String,String> mockArgs; + int mockverbose (const char* fmt, ...) { va_list ap; @@ -132,6 +134,8 @@ void help (const char* argv0, int exitcode) "\t (spiffs, littlefs: negative value will force mismatched size)\n" " -T - show timestamp on output\n" " -v - verbose\n" + " -K - key\n" + " -V - value\n" , argv0, MOCK_PORT_SHIFTER, spiffs_kb, littlefs_kb); exit(exitcode); } @@ -149,6 +153,8 @@ static struct option options[] = { "spiffskb", required_argument, NULL, 'S' }, { "littlefskb", required_argument, NULL, 'L' }, { "portshifter", required_argument, NULL, 's' }, + { "key", required_argument, NULL, 'K' }, + { "value", required_argument, NULL, 'V' }, }; void cleanup () @@ -181,10 +187,11 @@ int main (int argc, char* const argv []) mock_port_shifter = 0; else mock_port_shifter = MOCK_PORT_SHIFTER; + String key; for (;;) { - int n = getopt_long(argc, argv, "hlcfbvTi:S:s:L:", options, NULL); + int n = getopt_long(argc, argv, "hlcfbvTi:S:s:L:K:V:", options, NULL); if (n < 0) break; switch (n) @@ -222,6 +229,12 @@ int main (int argc, char* const argv []) case 'T': serial_timestamp = true; break; + case 'K': + key = optarg; + break; + case 'V': + mockArgs[key] = optarg; + break; default: help(argv[0], EXIT_FAILURE); } From 9cd34f35c3641fc1e7357a131c5fde53d0b8c926 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 16 Jun 2020 23:14:22 +0200 Subject: [PATCH 061/152] fix services enumeration --- .../mDNS_ServiceMonitor_v2_test.ino | 50 ++++++++++--------- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 23 +++++---- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino index 22407a4f6b..9ca8b10f60 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino @@ -307,36 +307,38 @@ void handleHTTPRequest() // hMDNSServiceQuery-> - for (auto info : hMDNSServiceQuery->answerAccessors()) { - s += "<li>"; - s += info.serviceDomain(); - - if (info.hostDomainAvailable()) { - s += "<br/>Hostname: "; - s += String(info.hostDomain()); - s += (info.hostPortAvailable()) ? (":" + String(info.hostPort())) : ""; - } - if (info.IPv4AddressAvailable()) { - s += "<br/>IPv4:"; - for (auto ip : info.IPv4Addresses()) { - s += " " + ip.toString(); + if (hMDNSServiceQuery) { + for (auto info : hMDNSServiceQuery->answerAccessors()) { + s += "<li>"; + s += info.serviceDomain(); + + if (info.hostDomainAvailable()) { + s += "<br/>Hostname: "; + s += String(info.hostDomain()); + s += (info.hostPortAvailable()) ? (":" + String(info.hostPort())) : ""; + } + if (info.IPv4AddressAvailable()) { + s += "<br/>IPv4:"; + for (auto ip : info.IPv4Addresses()) { + s += " " + ip.toString(); + } } - } #ifdef MDNS_IPV6_SUPPORT - if (info.IPv6AddressAvailable()) { - s += "<br/>IPv6:"; - for (auto ip : info.IPv6Addresses()) { - s += " " + ip.toString(); + if (info.IPv6AddressAvailable()) { + s += "<br/>IPv6:"; + for (auto ip : info.IPv6Addresses()) { + s += " " + ip.toString(); + } } - } #endif - if (info.txtsAvailable()) { - s += "<br/>TXT:<br/>"; - for (auto kv : info.txtKeyValues()) { - s += "\t" + String(kv.first) + " : " + String(kv.second) + "<br/>"; + if (info.txtsAvailable()) { + s += "<br/>TXT:<br/>"; + for (auto kv : info.txtKeyValues()) { + s += "\t" + String(kv.first) + " : " + String(kv.second) + "<br/>"; + } } + s += "</li>"; } - s += "</li>"; } s += "</ol><br/>"; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index c910260c17..ba5c6bd9cd 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -889,20 +889,23 @@ std::vector<clsLEAMDNSHost_Legacy::stcMDNSServiceInfo> clsLEAMDNSHost_Legacy::an { std::vector<stcMDNSServiceInfo> serviceInfos; - for (stcHostInformation& hostInformation : m_HostInformations) + if (p_hServiceQuery) { - clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; - if (pQuery) + for (stcHostInformation& hostInformation : m_HostInformations) { - for (clsLEAMDNSHost::clsQuery::clsAnswerAccessor& answerAccessor : pQuery->answerAccessors()) + clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; + if (pQuery) { - serviceInfos.push_back(stcMDNSServiceInfo(answerAccessor)); + for (clsLEAMDNSHost::clsQuery::clsAnswerAccessor& answerAccessor : pQuery->answerAccessors()) + { + serviceInfos.push_back(stcMDNSServiceInfo(answerAccessor)); + } + } + else + { + serviceInfos.clear(); + break; } - } - else - { - serviceInfos.clear(); - break; } } return serviceInfos; From 7d99299f48b3b5d0bc637dd021e6fcc00cb47c6d Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 18 Jun 2020 13:38:59 +0200 Subject: [PATCH 062/152] add LwipIntf::stateUpCB() This new class will be extended in the ethernet PR to come. This static method will be used in the MDNSv2 PR to come. --- cores/esp8266/LwipIntf.h | 25 ++++++++++++++++++ cores/esp8266/LwipIntfCB.cpp | 41 +++++++++++++++++++++++++++++ tools/sdk/lib/liblwip2-1460-feat.a | Bin 1595772 -> 1592566 bytes tools/sdk/lib/liblwip2-1460.a | Bin 1421598 -> 1418632 bytes tools/sdk/lib/liblwip2-536-feat.a | Bin 1595696 -> 1592490 bytes tools/sdk/lib/liblwip2-536.a | Bin 1421522 -> 1418556 bytes tools/sdk/lib/liblwip6-1460-feat.a | Bin 1924160 -> 1920874 bytes tools/sdk/lib/liblwip6-536-feat.a | Bin 1924084 -> 1920798 bytes tools/sdk/lwip2/include/lwipopts.h | 3 +++ 9 files changed, 69 insertions(+) create mode 100644 cores/esp8266/LwipIntf.h create mode 100644 cores/esp8266/LwipIntfCB.cpp diff --git a/cores/esp8266/LwipIntf.h b/cores/esp8266/LwipIntf.h new file mode 100644 index 0000000000..cbf2927315 --- /dev/null +++ b/cores/esp8266/LwipIntf.h @@ -0,0 +1,25 @@ + +#ifndef _LWIPINTF_H +#define _LWIPINTF_H + +#include <lwip/netif.h> + +#include <functional> + +class LwipIntf +{ +private: + + LwipIntf () { } + +protected: + + static bool stateChangeSysCB (std::function<void(netif*)>&& cb); + +public: + + static bool stateUpCB (std::function<void(netif*)>&& cb); + +}; + +#endif // _LWIPINTF_H diff --git a/cores/esp8266/LwipIntfCB.cpp b/cores/esp8266/LwipIntfCB.cpp new file mode 100644 index 0000000000..4eb81cb6b8 --- /dev/null +++ b/cores/esp8266/LwipIntfCB.cpp @@ -0,0 +1,41 @@ + +#include <LwipIntf.h> +#include <Schedule.h> + +#define NETIF_STATUS_CB_SIZE 3 + +static int netifStatusChangeListLength = 0; +std::function<void(netif*)> netifStatusChangeList [NETIF_STATUS_CB_SIZE]; + +extern "C" void netif_status_changed (struct netif* netif) +{ + // override the default empty weak function + for (int i = 0; i < netifStatusChangeListLength; i++) + netifStatusChangeList[i](netif); +} + +bool LwipIntf::stateChangeSysCB (std::function<void(netif*)>&& cb) +{ + if (netifStatusChangeListLength >= NETIF_STATUS_CB_SIZE) + { +#if defined(DEBUG_ESP_CORE) + DEBUGV("NETIF_STATUS_CB_SIZE is too low\n"); +#endif + return false; + } + + netifStatusChangeList[netifStatusChangeListLength++] = cb; + return true; +} + +bool LwipIntf::stateUpCB (std::function<void(netif*)>&& cb) +{ + return stateChangeSysCB([cb](netif* nif) + { + if (netif_is_up(nif)) + schedule_function([cb, nif]() + { + cb(nif); + }); + }); +} diff --git a/tools/sdk/lib/liblwip2-1460-feat.a b/tools/sdk/lib/liblwip2-1460-feat.a index 6c231417b2b65ae9588bd5fb6039dfd80d378def..4840eb4875a9739c2d2071c12e9b15465b5176d1 100644 GIT binary patch delta 234037 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°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 MTT|`7XSv(|09bEh`Tzg` delta 237130 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 Wd)_<3B3E@xKlB@4SN;#SQT`7kSO?|+ diff --git a/tools/sdk/lib/liblwip2-1460.a b/tools/sdk/lib/liblwip2-1460.a index 1e56d939138d25eff2f5a882b6f3ddc3fcdbb40b..458a234143901649882142ff7cd049442f129c56 100644 GIT binary patch delta 209426 zcmd442YeO9yZ^tld(v}~bJFQaNPz@M0s%q~z4zV&0s;ckK|~Hk1Ph2Ba8MCJQ9%$9 z(9l#AMNw2#YzT;oy?}xhl;7vG`yAOXzwf<z|M%Y4|2MDf+4ns2Ox@Yp+1Z)N+E4l| zeYM|;ih)LTiyJg5EGkY<FHEO#|E8xms$aLRElw|sHVk#lFtT6xA3Xy9X@Dn^4CC`Y zhH<9L|JD&Ol&<mLKFnvf8ScZX9clctBk)fZ|CjUv|4B+cOC}rtog*yltnqh8;O`W| z*Owaq(Gk(0kMVyU*Sv2;{JZ0pokqm}eFQEGPaQQPc$_c&A2}lH>@*@vJb!Zp{!Zb4 z**)-|q%i7jpAmI@@_%|n-#WqgN5}W`jp$#F+DA;>SR-@<Lhz5yw_G%0Tu1DZTE>5P z9N1^X{{0d7CrbaK;~jIG;l1|M|IiWmuLTr0Kh21{dHR3*h;KZ~u#Z3p{tIVc-wuXv z*oOblhyR-zM(7BH;L3Bt2E+K<<J@s0;lFSsF4<>XaRjau7)ePxjijo+%g2a9BWe6? zM$)v?M$!#Ujij4a8%ei+Yb4!WY9u|d(n#8T)<}A?gOT*i8YAf?@SEUc;7`HdwK0-@ zUST9%I&CCJmHe9{``-z#kgX}+u_fY|sas~Nl;laHr;i&meA@I8(`QT@e%06!ldc{; z%FrJ#P>K4Q<|-=qKy->WTd3?E=c3zrgIlY_2CWL$1skQkvSV(AC>1<drO%Gqm6xj> zH&uK@(RoKs)dmrkQBV*Zk)0pBIlEpYdIa_A6*Vl;^MCNCdK#28C<%U)ovUu#5s}j) zT74fJQ22zJAB--_jNBYy7*?cbR<O7zU-b)?6{V{o!39M-)zV;ty2Yv}cun1Y<`WUY z19b<ehk}*sJ)r6ZpRIQdIKTL7^OcAlsrCObRn1^>Nndqc@S2i)&9@?gk&VXjG_6sd z8WCLEXpZ@GM6hDxT!h)Gab0!Yjv0;f6;A7$bWv(T@cX70p}phVW)CVgAh@E%MEbqd zVg^q$OB<WVBX(>ry;-Tdf=yfHsWHK;Tg_2zgP*i&s^$f&wVtk;?^xOT<@m^3q71_{ zdYi$Fj}r5*o-ku{?a|XF8wF#pojAJS>Jc+g&QnJfj2b<&0OFFm4H|^bx@e;(O>f&9 zS0m%^b^ZI|8vg?|1leN8XMN_y>$iT3N(#O*YE$OlCnVVN>k2!jjShAWl$q$Lg&DS) zMaD&<SxH7VX`Ud*I{du_j(0f51NJ$bN%lM3pPb<ESaPDncaW1E-a}3`0=Df0EoqL! z@8k*&hlPVHIy{qH$>C+>$_{TMS8@0?a#e@VlB+qq37JwE4mXYjXF9w&67j3*j^%ke zWI6l|Imh87l!B_^@HHrj1Szd+UA&NtNRW18sW1!gHesgqelmpAc}SS?8=J&JrF~=+ zH4Ec;VHUv4!p!LF!s+0n!py@l;cW0J;au?N!Uf=Og^R#Hf&+}K7?xkfp&9s3;Zm>% z*PA*Wz|q1(z&_zJaEkCqaAo09;7s8$;2Oe{z;%SDBYvY;EG&t}!VAHr!i&M}gqMK3 z2;U6uC44J*fbcT#FyR&8QNpXi<Av`5PqrDcu7PEyIIIKD6@D1JP<SJFsqkj-a^c6o zD}}d#?-AY(UMIW@{IKvI@D||%;OzmiyaLNE;p5<EginHB5dIkaitwl4Bf_77-xdA> zd|dcD@F&8*f<G7j9sC;^w=p`DhH*(OcxN*#2<X7uI)yCvcSRT1CgWablTc5Xw|FDr z6mSb+R^+zAtl*u6c|&#g;QBM5LRiY^AdSW}GD3`m{5lsiwUoy|zF3&)yIGhKuOXw6 zq2C8wyiu5bw+j2%{%jWuJ-<j!bv(Z+?1lVIVdmx?VcuF_k|D&&_+FUz{g1-TPdM6( z1T<(_V6Sj3a3VPX2j;$_I5YvL3zvd(ggb(33F8gds4LtLTp~OG++27txQ%cbxRWq% z#U8@rz=3{Z;e9zocrtjT@HFr^;o0EH!gIj0gn8>O5MBUYBD@m3On5CgD7+4Qx5EMB zL0Ik=hljuq2|o(nEW8E$gz!#qx$s`_)4~VA2ZUb*9}<2Y{D$zG;CF<1cYGLzr1RSR z0L#bX@Dun8;a|Yt3I7H@Cwu|?n{c=?j6Z~vz`k&VS<$IODZ;4ZMrC0>05gSCS#&kT zf^-;lgn6qJ3-f{2SU4SADqJ1hPB<IfMVJ+{mvA0<fG{iFFyT7jQQ!bm+7g!W;?M~^ zNw^Dm0lAV>!xy`FH5sX7&0j0bn!iCf3A|A_9lV!}rx*2~6GnRzFkTc3@8kE$$S##m z3Nz5t!VL6F;dJl?ay7%CoE;Z(1~@|4zU71)K%OYfhg=1lQU1(jHF4+;&KB+u&KDjE zE)pINZYazrUNhlQ;MT%dgF6b32X_~q2<|I93p_X=mK$LiA$$|~YT>2eiNd#lrwOkB zUnhJgI26t*@M4i`@U6o4fbS5#53Gd)>tVT1ERTZM3-gxSNk)0Hc=rgSDj55PSuqa^ zr-NS;W@UU^xHk9$VK#Ih3D*aI7Qyx(5j2G5TXARv{!zFU_*daJ;6H`ifjwy8>6a~I zv@kEFPq-U6MYt!pvM^iBOyR+7|7(b41RUxJvo)+M%+|0iIn(KubrwclGkOZc$>=Z4 zN;gzE2Yi)qP4GD3eDJm80DSUZoFNXy;Om8(fENfe2TO$ef|m)81P6s#(e4($7JR?( z0`P;vi@;Bj*?7PN_P8vsk&%3yjJI9<fiNGP9|`kz{ZyDw&Y#K1E>6Zp7n`_$DW~5^ zVfu}AIAG9oHCk#op0iz?FHFxx!g1h+!t8W36K1p8S~wNlQJAf2cVSlEzQSmWjKNX3 znHe#!<p^;=oieT#W+_b+X04tkoCm&6xE44d%*(e}m=*Ts9i5-KI#IO=?s&7i8XL6U znx$?FUjJ5ib4%~w;kRa*M|ua_yggGj4eouryP6%0IojRa*(W&UXgBj>pWv3G-Bfz; z0%W`T1-rb{O&P&^-|4Q>g5Th`X|Tz=-BnreR{Y)={1CtMgZb}uSEGX0zc&l=bKo_> z*6(*W-ygJN<@;llsujHOL3i`$h+vmvGu4XVfn(kALY(+vck{?i!BHRP<t#_KLq-X( zHTQr^#lHWR;LZ<o@;ta<SMo}Wp*oNKQ0JL9I?d`9dVl?hlwif<KJ(EQ`s^(cDG48n zj-!DdYKvf><2lL~y#9Eux+VA^eq)2L;@1~EcRV+|5KVHDr6;danMic&6E!anIF#0p zOH+lqWuxet>PFq7a#FS6yC;%TCLjf-icH|i44Y@4A_m@hvUY=PvL|Axb863%icH5T z%(D>537>%<)8m;<he%Hy+udv#yy|3iRbR(fNy-U6c5*@ln^MzQ8BG5u`JcU>+i(22 z!N)%O{qObhVqRZQ9_FjCqt3_YE%UTTmo7`1X?`1~3mZk|skQp{WpUNRGEB7Q`q@vD zs+-#_eKsN{$9%!kM;b-um=`TQe|b`ldDx>1vvK}4Os|NHNeRC4dBVSxT&h{Op3Zn6 zsU~Vt?ibCwjYDoNGolnHk0)&0r0IsG!h2JwBGYWQu;DyKqNl@CL@rOBuzU(V5i^|= zZ$fy;3GVo!jw%j*^2MG1jp8cQfuX(%y6l>yM}oh8<@@`>+tKptD3977?EL*KbAw%C zIboBKFe$ZIlv=<kwOggs?vqk`UrKGGNB4LWrM68<?Z-2Aso9^roB^)7jf(1WfGctK zYUb5>dB#J;7-5v{7;(0*$1~UTp4I*ik%hsN=e>a+FXh!Le12V2QSI0@UDer3`|)6j zZ4#T1UOhdtOOu0qK~UdP+RPi<rgJUzb%<}RrM?XDtF_eU<l3?7GdZ8;Ipf1iHO!ap zjHvBZAB+4H&yhthXT0xEc+Th5!+c?B!8t!|4c7TNb4RbAXPd!yYx{zAeu?CzLOpig zOUP`;mIbf<wNmiMUrSQYB4xbu@vBUfq2id!p6FoD-&%V=16pPnJ2>W(!S%n@kGu_y z0j~Sn;K|=onq)=8Q!<~$=I@BWlQEjO4b6+EHXo*z$I}8T7z*U$)@%lyFsnax9talv zJ~pR5q>+gwh}2_5&4ahd$cD>di+%<PiY#dkO(VKO@af+>HhL2&@p@vKv_Kefe7qQO zpCDC%I1bv(i~ACl^@cb;`{u@-f&BV7FFeeNdpbPW;zDKbay(b2$FUHm#q|!3y-?I| zqwQ@lBsav(1ka6|2M^cBJ!yNp4ynE_t`%Ho$K@a`v*Lb(&dfM=LubUDgM4~i4@5RC z?rWrEY8;;&Q{v8r2hUunl@SYvtT+q5$S7asypvym53k322ggj}o(ML**h$?JTyn9x zY82djvB&TXcn^#F8IIv`ZQv^+ZUPb<8TT8)h>GLeU9=JZHk3T^Q#?pc9Q$QP9LJ$l z+*=6SG~zEo?ulPhh0bvh8F3zDLK)_J;lV+Fj8c1o&;C&%E(YPo=c}y<GA(g(@bf>e zMiRRHIR?*>C;$8^emo*n&D0@W1N5W%2OqoCpwbtVbyezl<h{aLc!Z@HVlgVu5B_<n zow{~aTh*=LdOYgKB0V)!FLN&XU91$#Aj|9pSP1~K-rY;A+;-LT3O;p|Qk7IqovqZG zo_pa^L-m308mhMyJ>O(dk#!9tw*$O<2-lrRiG-iaSK#j;d)b!tw&NTI89R=J?0ozE zI>A)M6+JAZ&8$k$wBH%j8a~8pP1j|n%1K?yQhNM$UICOpJg4I)*RSt0)x^5Z@H+Pq zoI<fShFf>Y&Rv#emO^$dQj*IokI+pmRYC36{VbKMX6ktsGB{h`W2u@ZQuLyw8bq+D zjCv1f)1!u}CA!R`n&7m?qx#j~i?ES<y9|1ncl1D^wS@9F5a+H3{0R6Qmk{YuMMmK! zh^z#i8>X_&qy*h9Om#CWC+M|ds!Q@HBvHMlG*pstwQ{onP4%TP)i$sVC86F|`Ch|l z38zA)ryp7Ygle5rxM1O)dr$)!Y(;@6j~Qjx2HvBvt{D$s)fN&xCI`euLfp`<79Nw; zLiIN4&1ad%vl80vj#_g&JUL47W;2fMAeMTosC7cIRxD$9Yu2F0SFJK#PbglnMZjuH zm=DLk0rnC*s#A6iJOaC2>by)}Aqu%nnIqx(YGf#P5@0sKkC0KfR51%TaD$`hF>>dK zd!gH1oFk3go5Z>Mzj2N=a+kw-6+*wtcDCz%?p=^Q0@*B=>|w}w(QkER0rLhF`c?>8 zmXc<p-cPKEa}-~}=%&`ZfWbMZIOf>Jk&Jt<%DBl?dIJhAVXbx(FOg%PNaw3(g{-UT zypn}CM`c5uBPP}Q;F_r1If_A_q5j0_GpO(a6e{8Vc1m}iUAj&5PZ6qq*luJdpbH{Z zl{mYWGlTC!wp9;`R2fxyWl^ZAD3p(I&npN#VmH*1zt?X?s;sLoLEzk6;hs0Zjaez< z*VwV7w8lluK;fjWfKVBYIx&eY{E#?aQr1D<;V%VSEy8Ft0(XHb9r%}8L|vaA8l}>6 z3z6mc9g1y_-)^Rw&4jAIVKWY{`WrOgh+>Wzy;pCDQd#OleJDy*N@YXhXJs}@2je$p z44*Q%T`xqb>LYSdxx{fa{3f(#)ntwHKLTiJG~JKeDgFb+cEO3UX){V*RU`hAl=gwo z#0k3*?99J}%_kx2iPtXCfoPSi_Ucv9sz#s|6eD{uig&1J|C|Ehp8OD}h&H$x!#$r9 z*^z6;FD*&Kn%~OIwYP9x{Pb%yPeT&?^^z#~l7dz#D23!F%oYRT;Polywkch|V^+^W z!_S9Pz$kqS3Ms9aRJI9r&Yf&E$CLmg^?Ke|ezqM(^E;WV$@UFq7j^5yD12UA-W7g= zof`iNkkK>_;m03SygQ_vI`CQ@R;*%<q;=Jy5(2B36T)@|V~5bDxcq|{6=PKjGpxAA zF-^icCYouew8fXLspXgAP-*r4DV9gSdcP+oIJA9&E`8bOiEV~(l+lZ)-MZzVu;gxh z?N&x_o_5+elqc3)k8w`*z8_$lQv43Vp^PCsjj*v7PfQ!6JnhyOlU23ygGs8dQipZ3 z6!l23a?i`1uTV2*-{0lGrKr}b5Z<Kg<usJkVf55_9!JQW#U(L~h8Dj<>Tl;+F@N7f z{$Kh4S@aJ+Icj{*EGlnZQN@M_AMYPlc%w&I5xA@>3iU@RBMemw&#l`%Dhgx^m~rcb zr7VM&zhAl<sXTf|x;j)I%uo-6>!mf+N$qQ*!sGwL58UMoYpN*gA0&@oMDaB|wfuov zYLwD}KYWoYN&63b8|rJfdt%Fb)lrA7;HfcLdU8x;mQFuodUUl2e`M`CNF<X!NY1z@ zcD3k)b0!Wp^Bkuj?+*SjK3C7Ht2zWrC;IdoKg2`@tA0~em&}Rq=_5PCGAG7Diw0$a zP&r<4*;qzpd$a`2lF<W)3A@`^MpgSG1M5k9+r6sW880j82Acu8ccHtkwk@K_pKWv% zH8v>9Xs3(52+t_!|1ZL}VslQGk#E;`+BklrjP|<d<H&0IRI7v@dVj3H^sf5Kr&k<{ zEYv;f;~jn5QE%y8A4c{l@3A9nveJ_q!u6EbpQ#r%R8>{3Uf)n%n~`Z`qV1w#?lX~> z9<Y-u;z%&Ebx{f0)0)Och*``Twm4tkQKG7;+WLtS)j}2MA7INUGTPyyP>D~u1f!lY z0(Rb7t89CHUDQYoR}J+Yjo`PDeuAea`c0mi=^q-Y3ha*{5iRWRen9&oXBwr(eQ2;k zhL_?A*jZDT;YdKs|JoJqpI%}A`U?A>SJ)E~F)mRj`+1*Wv^HuoC1Mz1;T3j%UZdeD z10QO8i=DcDjE@e}2O6unX8pqQmQ9pp*%L#O{@uh7edf)?WIdp{TFE&fxd|*j#hL=c zFjZ&Ww1sNYSL#bUh?3A-W1S_(gz6DhyWt0>E)Kqn(bz$BcQ^+p$|)nqbk~PlsOqYR zKHEa2R_NhqwHB>jI5QU2Q>T}z)Mh;$XJ(KcQyM0d0a8Ye5xMP+0vJ0#o%Qrm)w_bE zwFAUScm~oNIi{;Vg&0(p{uNq%`#}U#4@VO34j6Kb$oY(*oIdT`$xYKr<dl(PL~bWw zfL_;9rH<gM3XGk;z7A8w;3y-<h<v2Tr{iqrc_0AhY8=$3j2t6!prNYkv{oq4Y~7Tn zA-b%UO6|x8m6*^KVjGjhn;6E<!!U<y;Y2xQ<QS3Lc^IzuBe(!YPigEtNP+TQh~6k8 zhbo1g?lK5q?1}>&%Iu0$Mk)N^P;5tGy5L|qp~fmk<a7%qUH5CP{2f_3FnHt}NvTeH z$uT0Qo05V-$HYjYBMkXp3ap#n)>;*y2A*n-lImeAIY~lYo(-#=1=M#MJIj!_0ox@4 zE(Y5ri24*Vs+%rtqk2yq;|S~uQ_)E*IY#7c$Q3Uk49htQI+T%PM4k=~=_~<Lhca?V zCkw2`-qlv6wiyeAsewa{v(f(4N?(*ch$BYiwWu@R(b<j@btv1e0|=?AU23c*Fm|a; zaG1Ypl3oFw3X>dBCQeC6czwr;E2a0tx#MKVUX{)mcxNe*V?=J3;2=kbS)dMO<bS#F zQ+0Yf)VryUDuYoo9OiGRUX*~7_;7&XokxBc=evaIuZ=M82s?TfH4N(`^(iBVs=a-| zXF&ktr6(#;I3##|pdesZT~-p9={V?0897GeX<#KhA50y}$RQnGbafqmV3y*b4rSyR zk*9;z9Q?qnzyY0rkuH`Pak$rUu=AY-Rz2_ovknIXrHmXS@)}^p)WU4UK^@A-F(L>4 zRmOBn;^l@J&Ch7GOoL?|j*tU;)nvxu!J+2j2c`oK$|)nqh<vcf$Ko7`LrJ4DQ{<G9 zLyd}kQEq@>C=R<Q5GaM@7&^fCa47nMxd#U$ri>gTa-fk|!$}a`$h>?!RE^+@1=YQf zu*`TsvVTEE{bL8!h~gd)@lZAN{MRE=bhnNwoASw!@u0k;YERK>Sb0FSVxF0zzwW5K zly8KL2jrek%8qOotUMqp7SYSF@_^|0%btpQUME$XzRyC&1M*#>iY^)Kw&=@FstL8y zVdVj>!p=@|I>5>UqNZ0TSJZ1es|>1+g^UN}hdVpIm%_>eqNFa4Xd|pVAQ~c~!?5yz zXoHBpg_Q?H-*$1LO)^okI3OzR>V#DcD-Vd4il`5)JRmyKRaHb4!z3Ztd2L4F%tL`` z#*)(kFcYYgZlf`o44vsX^9bqBCTBQ0bEyNa1?vJAa~>b%1(4riqKebPr~hg?AkZ~9 z^9TjHj-2TPx&fRBW(DH>z7TH{#)HZz7p?$)MmQb(k}x9<$D#7@!&}U*?v%o?H==}- zUCh8#ZT!G6gQ|{=b|)*O&rF24v5Pynn0H=CXAn6ck&SRUjB)W47teF?Vi(`$;-HJy zxR?*7P{ey&9C*=XIpX3IE<WwzuUvfI#g|+htu9BF?BWa;^E)6CWY<5Vk;|d2i+j3w zsEfzDnBT}kIa}!B+g*IGi?_S@utNMH&mXuPK63GAF8;>FKe+f87ysd63zaSuzWo9& zmz(3Yww(D-4q3pJT%6(JTo>1NaXl9|a&f7Pd%Jj`i-&^)q126bIdDF1NIu2I_Dp8U z!3{3?A{XE6;@e%k%Ek9y=76#Ovc-7B#gDmohl}^P_%#<Fb@7KT{@BG|xcGaUo%&~B zFyyZsN4l89XrYowc5xLKa}I7ur`W}%F6Q*wkPfHLhIle(s)j6_3LD}FUA)P~kGuFu z7w>iPb1r_##e9Vhh5xp&o&OJ94j;LgQ(HqGesuA#F6Mi7NGA+Ej}ZG^oa*ALE^fn_ zsv!?OT@J%se2t55bTJ2GLw?t~c(aRlxtNnsL;7$1#mN6he_1g5(8Zi#8uGwdr6Ept zabp*^cX3}A&vEhNE<Q?bCb!dBmqRB!o<foJcQI!chU8Oi)?@ps>e=~dH()looS$;> z0Y`NkRJ{@#XZxvqeX6fY^~zI?6a66a^ux<qzAo;Ex7&O@z&XwBhp%P@dKYXRC4?=u zx)bq}WO+N=O_m^Ebm_d}(s_qmptJfTjso4mIh9>ZOsSX{?{pS3BbgW{bWS9L+8U^Z z3X5~aLe2wRJl4e%$&!$Hwp?HAui7J|HUm%)5;*5eK{Oqr3X-z|ip06O&3YSsi1Pr7 zvh}F}D7tJXg{z!EJOeKWvdb07OHLrA1MS$CLaRu^YK-^3P*nVOkChv?=}*S1FU@dr zfj$mz+2U=!%iCgdnxm>6)vQ66Rd=~mpC+>-1M`xjIsvMod`II7h6=1QIbUxagzMf- zpB{v7P6fJTFsep@9y=JdAXGl+JB4awN3zJfx#R;~@?m7Yc){Fc>*%8huCHWlvrBcG z?d+)Tb;<XWt2pxGWGSbwUGnqf0^MbZsvhcJC3_)~)Kw(&MH!|pS)y-7uI9*Ff)j<i zxODoHC7dBH`86({N=|pe3Cx5g)NfwkQd;3+P0nyU+)I6MEm$9R={!M}h@W!FpL59% zy5w&<a=U#u-lat%_}aziT$~VhS*OUwJzPA>#j{;}n~U!wONnlXYY$7Nle3L*2zA(Z zxRjnDOU_<%@mnsP6Z+YHQK^9+T%wCERW6+h#TiSM;3~T~!=+QpB`<Z!hmj?@^Id$i z!%ks7?s7OoE^zX9fjr;gaNlKlri<&4yE!@?UGlzUCwODHOMVTR{eGCqJ}87Do9j|q z?&4K0UgP3@E<Wz!?_JC_BcbqXxVU+UnZO<)3wWf9XSsN(i}$(sTNj^mu_xhj#K|tM z;^JmtJeyb$7=Cg&jCJvKF22jf8(qA|#qZf%URI_O6&kwfBk)A(R=#?KIu{m@+hqxR z1j5T*e5Z>!S0bdt1u-Fh+{HUwY_HOjFgg1wq|Z4PAr2gMSw3{J-CYsSpS$E=yZ8qe z|K#Eb_A;dUafU;vu2*oe-Mz__7qcvvL%xd(T+F!<p@7=DxQmOqI3}di-^GJn%sCYy zohe*G60*#8Im~tOjV@m5V$Q}0`Ca4U2VMM#i|tOC-1R#`a@KWD;|K-xl8aw=@mntb zz{MwA%-J8IaJbeb#J{`vPZx)wdlm>OMX|3YspGVf5La_?u8Z?s+{DE#T+H<?p>XWp zri4F)a;JVoID;fL_2j6yy5-M|SKE{_^tBUIY7y^1dkjr#;Xc?ykF5RRP{=P(j*yee z@1LN8)+By+47v4jaT~ruAp10&62h)1&1o_^Pc-?g#W4<ZEt<lUi^jgK@Fbvlg>p2) zG+%i1k=DMH02f)=(|jPaXEUYP&c-*COLr@sxt2auGqQA&#*iyI`X|UTTK_v)dND28 zmzD0wOtSPVg5+v)7d=W#x)ab|vJ_l%_DiMcyCbuqHL$&1JcbNEXs3+{!c6y6VWw}k zFw-$lI30YWg<4F{Ik4O!4t2mQgn23N66WyL8ex8DctE%WyivF@m=o0)W>fG^;TGUM z!Y#r3g<JD3Iw+QQ;KRaQz;6k&zP&Hp18gs}L<D`oXDCM%;DFyx!n_I>gqdT7%T68k zm?DJhg1z7X9hd`t{w0@!D+n_|)r6U#>cYLi4alf(jJT;VBW@+kE7(Ce7u-!a58Ow% zHis7niG@$DGU0~cF~Tg;3BoMWslv^{vxQrO=LvTJ^EH@>W69kj%#vFn%nYow8Rg#} zmPcs89fOm>_u~-r;lq9(&GRm{7h~d1qCTHJT)K+FvtO0Tto-(3OgzL{LcdZ6%o6%j zn3u*Az->kc7FWD*b#RI>D`sV3UcXG?Cg2*vrQkZk%zd%&NHE{O8UAQ+sqj>=y+{-C zz;synz~LHL=4Plcb2CDixtUHzR&Yled|@ZEiJ32qu#B686T!C$bCCE>;dJm_!n~_D zh2i=qpuu6=!iNl*Mf9XF+lsxy>EP#tS&8_(p*~CHHQ~D8w}n}6_`IPG>&HjJtjM1V z_hS3=Gc9N_n6ry6Hp3k`8<t36<}6Ma;TlQ8%s`qj6U}E#Xn}5#Fy1JQ`oave1DOkP z8F4pSz%0@}!c-b0%s}l$l+eimPoW%5TOoLsFzdt(!fa#~3AX{?EZh!!yYK*TV3k;g z!E&$gDDZmWtHF;5PXIqA%u2LFco}%N@Cxv=!W?UVQFt}@RpIquPN7Ez0>&m--Vujg zU=F>6R(^gj%%b~In57bi)-SXQG)5Tp*YFFo{ZAD}AsJPKS?Q_^XMt-*;QBM599Rm( zp$53VFe_RkVYc~Q$hdK1!M$8OK$vx6m@prbql9?}jTh#noFtsb_J08_kn;9hBFr4y zizp#yj@MFN4FL0ii+7OIZSh}gB6&v~rW}n5`7Pmk;P-_afKP%0R4Rexv^bQ4zZPx< zJ}b;h^s{g~@I~P+U=uZ%;S2#s3bXNv6P^T45}pIDD0~y!|8%h|heM9=UEo^6Yr%De z9|kuN-U{wW#zkcl+g+H&-dC8#K3JHSc!V(Dey_F}<<DZ_U>F19HJ&EShtPGxY)r5T znyu3eyjZvte5)`UnLC7gfVJ>o@O{EV!J##gW5Jt3flh<vaZ#EHeo}ZIc(3q$@N>co z!7mA;7!7+3B{HxSY_FjN-vYMRP=Z;y_8LksZ_&@hZzhYH+m0~z>%eD(cYtYBgf2Ym zN!5FMcw+VabJRvJE;J28QJK1IQAB~>TQROo=Z=dlEKi)PCRh{Gsens}8m-a+Fr2Qd z(g83S);2<2ydEwd;^MI`p6=rLF22oXz3xr_@X$~rAG9hbc;v;r@?rB;D^s6ds8TCW z7&m?N)DaWv{M*@Q3%D!M>kC!5KDz)DJ-I)T-nUStmtR<@#+iD{VpX}q^wG1Y|9jun z7OP~vcJaUXzGbn>EPr{iDpGn_L3EAs%q8kq)0}JS$psNP<~?$LR?cU_^pTq&KWXZ1 zg%LUGw2uGG-$Z|%7nh{|)G@cJ+*NbJd=+o(j(!jdZx{~NYh=`JhEgp(<W`kaGr@9X zrI6E{h5lijsb3XGNWZDxj38?^yh42+s_c!Tp6*ibr!PQV_iGsKt5Dk0iIPF0y8IR7 z&ARh#SYYzJo`zG+r>_XP3w&iko4&GLzK-bwRDb6R^~q4bDC)T`_47J$naZug4llD( zii2iCugjs=)ZKTQmGsnQDy=3vx^BG{(CYwwrh>OW-C}WM>m3NTX8INC??XLQdbM5Z zZM3x<#W82O@>ST-+v(&p$O4znNZlJcHHTgi<SD3UL5=D~F7*ZaL8{NaLfz8`Jpoa# z=Td(}pJNKf-;NXvfWlbi1j(igLD-pkQMbMwLGHgI$o+jUr+}?nNd0pignHh`SE!$c zdLh)9;6^U>s4#u{cGNfzI!g?q6bDUGKlI>nrat>3q2O!jdMi|J<J>FMr$aqU)Y+zn z)Z0T3d9q)xaWa;A^#0=Ll!U9Ukl*If^Or=V1QuN(XD5F*J&IwtH1n>Ae>LJ?Err(- z?xFY}y&^mg(>!m7;QWNb<BlO<EK(51LUgF!2Q&YzafAXqC;^(H#}1@lm?vhI=KU-5 zIDql*^uGQVy;`_PP)u>cuzy1-{0WL^&JEl$w&@UVmt=swSw<R45PPCN(cvkSAp5=F zCFhPFM?#(;55>b#7jmiSMh<j3u`GyAI6?(c*NK;X9>>(cTgG{I+{A<;u6;#-Lxw{S zMZo~O;0OiS+zBw`-KdO)@kA)MkcPtR`7e5i|F>$+)*~UGAw}+G;?7BrDTa}bz8E7$ zd-_+zBmN~oEV{};$%F#KITRkpi`?N&z8<e<0Tdwv?CA<{#uWk9L(^9l3dI%R<SPQ) zaDy}W!0^z%{FT6^SA-X=ff8h0fMIv+uN3kn!JWb`3-GQdImZ3}SAZ)eKsE?8ONua+ z4X@ZC!?g0a{|dc~X7*bAgpH7+%lMb6*UVm*AJ`-MA%|<w6s!(ea1NEhlhAXgbN{XA zv%;MjAB2N$Y|mf1B0Q@(+;AU+OennPo$ylrs<az!a}*ii5FP)tS;-rTyO{fWp!OM^ z^_eM2l|7wNZ}hdRRQ0fpci@t1y-H<YUf^EXFd`+aVg34z8gQ+)`9fNG<X!6FgqQ;; zD0LDc4UE>iH>%2!H4r<Ny?>}rY*aZFxvJ32L%p?9*eqkQ`vjyIi`{4GDw|Y`>ilLb z%b87t6y~g2Zi_I&!sx;LEm8+IVGbQ%U$MUV2u@~C{n#dz-;8gu5yi)#1sMl#BO292 z8N~hyd1Rbw1&)3ng%=xDycF!klD??=)G%V+3)9Jusz#MAaV)_941Sf7!0jqxqbI5F zppv*nk9$<r8QTE$#S=YUC81*b8`H0UIAT)%?FiU3%uJ*|X4q$tCwXEAcA(Y<csXYH zJ0leb4S#Q3xw`&5$g=!p$RT{qMQO!Ot_EHBxq}mH{N41WM^&Yw>)|JMV{b^JV^L<l z*ga>!G2`Gbb|2A*`HC5O78lg;#2gLRoj0q-YMj1lvq}#vM_QDh&l}T!8@yP4eyR8P zhaw4K{*_2VxF0vE5#jHToJRWlA;2jAvq(*}k-UK+#!VTHX#FSbQnBYQ_)Fky8p&0V zX;0i5jyC$e2-Wacu?sESV-GqmMyjIQ#Cg>1fW&dSV2i3?qL4dnQ3EQaA}w)kRUZVA zl{gaN#dTC`5JauS*Y(p|RH-V}e?q@<Z{$91w0Z$fEfPE7H*UJhgQrr%9HHwyrn1au z!}Y+&R6TWzUIwdLrnf()=3_BTy{)RNc{EZl+-jG`(_8T^=U)BsR+XCl1mcUoieXlc z;a(&0qsdib-ausWlWs@w=`jO!mB&@KYN}g5j*tEI;KS$VJD3^sh@SSiD)3fE+4+*n zknh--$@=lfF+IB}EWT8V((L)vzO>2U$}to5M{vekfnOe1*JM0{@Ub+Un;7{Dp1^OC z$5-?@&VEkhGW<RCqHSuR_hCdC>1#0zCnV;pZK@w9az3G|sI>B7PpBTsd^JjM+pco3 ze)+xa>U#70Xx(RrDyYU)*{Ug*TMR>ZwYjEWHLD0~kk+>PfgP$(f~_=)N+q~_MxEo~ z<&itpAf-l?U-hIKpp>ciJ*6_#Kz;HlRm~rPl2L;#hQfY8=2{(Bu5QYI9;sF{EZ!Vh z2xSWnwdSLEH2V3_gbVpadKjgjEmzIe4E<-hx+VV(){`x^Kh#6JqpH@_#WUIQx5f6i zA8|IGp?B<3nOMj4?k-hFCFro-xa21zbpCEtjKr1gR^O-{y2~Dwlh3UOR3#4+!$8?V zRBI~Zaa-(Tbd@|+;j#jVK=0dwK-cO0d$3-7hCa4OJ*w80FW##<C^e+~^?m9_Q_a=A zpH%~KdhA)~_SZ+ARSjT^*biH*&fBkA``Os2pvmt}M=+9AyjaiMubO4lWpr!JH;{nu z;}9LUBvbdBQ_*MXh4N@TxBU2iWrbD0h8L>xv+(V#wykM@oT}0l$rQmJZ5~v0i`fXN z%w3n|_SMVc)f2_n8B{hGi;Eytk3EQ0{<-?`gQ}LQtB)VVk}JQycn}N0B6OvfRMoT_ z5NcA^ma3?&w;`!%+4wO!Uy9T{UqY!Y(AT`ArmJ@P)Jv+3`B;?Bd0FMv<EUa%@d0!v z((Xc(X`2(_r_&+a3dw_xQp%8wt{owWewE4T_OM>`vdUMuLta+ZD@{U@6XNlVGCHP1 zn|FK~n^B{C{qpZ#RwF7!F7o3Z!!Dlx|1Y;}p$E^mnwBShu0|$5a_E8z`-kfrpFCvV zk*w;L4^A;39~any+=V`7HNmZ>P;4|Dkq&*d;^R-DrqDc3MlGR9X2p@7DmQ0SENz%9 zUhOo850N<t1T&fSq@u$I$d%Atr{Uu#^o8mxaur9ZkasC60L?XITtb?K<a7W`72HfJ z!{Kd6q~e_p!+F*GK*b)?)53f@9}wmk(jgP^Q>iH|Z-_%F_#NT4U{21YPA4!YXOg>v zIXRQeZrOLj99%jld^Pwt;pyN@!t=qr3+Q(l^B*G?);7QJCUC0oE-)u>(!*hJbz$DX zHHF^<7YM%%t|xo~+>VUPz$?;4m<8Dj9H2ucECa-Wr8i7C2h7=@)Tsd;FPsOqH%^7T z7TDf56<ilQS9DmS3x!*NIa!q9v;;2~Zo}6#E;gq_dpOt|r-E73>qOoa{IGBj@D^c= z2pHRic?ot24*)+S%**kDFgud32ww%Z_f6%_yJKLnH%>*w<G}X!Jn%K(PsGC{@R!0j zfWH@B1U@f(6Zm)Go5Ab@Gh@qv;lk*o8nMDF!3kVnN+k_Tn(#f~s>1hyvxL`y^MoG+ z7YaWNw!i-&9M&8A`yY4<*#7<pejIFn{{wFa+u#4d0ah;i10XDW!S?q*@H5~tiC{n2 z{{9E~0kHl34}1`8fByp?0?!tGR#N->ALOj0_V+*VTVVV9ANU<Gh6eD#36>9Gxl25s z1g{bP6#RhjXJAfNq5ikvt-{}fcMAUi=42J>oCoh0{snwc_z&=5VT*H^-VzHR2kd&& zb1e9za6I_5a02*iVXhQ7D_jx$vv4)=Md2*4iQAT8vKP;Nv&dXc5J%>Ka}g{_;?MwG zQMd^>UAPo%?*a>bz9iHVIaeRl7485o5$+6bD%=g+jf_43(q#;EaiB~r;cyrwj276K zNk(%@GuOong^><}lUS(3W`DVGGI*shoBex)v%%|xbHN<ef!}~p6P9h_z@fdTgxQ$v z5pDpsKPtupVC;{I!uCf+Fj`mVqav8O{EU9V%ot}+kfXpq2%|8JU+kS<;edy_vwJI; zLpK(D(E}e=oX|q94CcmBWImHP9K(H)Yk+fv3&6F6nE?*5P^Uh)M7SB4BPEo#K>ah? zh@~Z%vs>uU4%|byAGn|JP%uX^s524FIUnR}!4rh1fH~iqaz1!w3(o>`BP+@mfNul` zXjufyE#j~kyh3;h_%30#Tx*2cay=k?7np+y3}-cXt1ug}ox*&uabSTuYr*@4*RlOS zD3(Xza9Efv*IU9{!S4${1wJm!hU*L&wXYBOCt(bBIXl8aJ_O9!In*fw+dIO7uLARp zFd-4;KMs~eQDU24L72suB|H~w?*a?Y^T75lu;BS%dly*n&0u>MSn#c2zCbbJ<zRak zSTIY`-USxSQtWH**b2+tunZ9oEUv4B9{`UNehADLHU|0#nDckYETOr=JHZQu_k))T zvq|Q=Huc{HuM`e^0?R#OVY9kU_zd`A;UB?#EvM%T;O)X5G%UM>xrXW)VYZSl2y@p! zPNt{dO5h{HeA#)|-uV>{>98CZhw9)@gmb`O3bSSWUbq?fyf9n9--X!%a)_0YaV=K3 z@DOmU@HjA=VCu|d`_J8QXqgWOdwW>$t>6O6)13R8o6&{1iEuvRYAIX?++Mg4+*P;< zxVLaiFgMs?IPBmICkJ5Z0n2D{U{8kcT~rzYo+3O7JWF^C_y*ze;6=idz&8s|1>Y__ z9lT0-4)|W-o4|qfVqq<PM0f@GG2uJG<-)7MPYd(@eomO3l%r%c_*vj%!YqkX!u7zP z3pWCP>u|vCdjBF0ETTV!+kic2uo-AqaI|o5FkhG{9|lel9t*B4%-m-R^Va3SHuc%K z)e+_`S{#MzPY33{u{iJ^EfwZH+D@1`?jrmkxR>xYFjrYH9NvDzgm;0t(HiB?fyW9T z0AEk8h)T)!e}P!|=;YWV9a6!|gsXsq!s+0<g|or;3)cWYB+O#pEL;qJLbwE6F3g9} zUa-CMcSl%Wr$Z&@CE=(rBR(da4n8H!$UYa&1Ai-A3;d%n6Y;BXUGSg64Zz%dka0C- z`yVZqR&ekMcLS#g_XAfJ9stf19t5r-JOo@vcqF)3n011SRv6iMa2w$X;7&H9{Q2nY zAr7oK{e)+LhY0i0Ia2s~@L1vb;7P&@!5pe*WUM!HgjsL61cq|nDK`nTIlnC+maVXG z$1EzbLai3w4qhY73iUX-vfaoTPYU}X-z%H~eo;6L{Hky|_)X!O;P-?BbznImmd4<Z zg>h|+^JG+lSn%({Nnj(!k+YJ93$w1o3a5iP-;aJ-Nz;TGS5@I6a8?Za|4?G3s38ul zrA^4_V=>~E!U^E^!pvD$VHB9rTR0s&P?)(KF3iZT5@tihUEer;hwmT8oWCr%<;dxH zAVDc8oDaTRnEku^g;}c~5@!Eyvv3pe6T;2F<-#4oPYd?~^D9I`Al>P`91;h%^GAhQ z0Y4PJ9{jQJ0`M2Yw}HPCW~DnPybk=E@CNWDVb-T;6e}~i9~|(D<#||=g<k~MAZIua zr#ixYAukpl0B$Ti6kIAi9NbQL1h|VZGuBI(53m6a2Mpe$TxZ3|CWA)_PX&(`o(-NX zJO?~ecoBH6@U7s5!pp%+h3^C}7v`<FQusdbJ#2p&@%^x@6NmNShlSbBZxQDGx?Ol9 zc$e^_;Ae#QgI^GS8T^XyE8ru-r@-$De}ec8E(>EK&VxS@<_qX|!f{|O5u=U|{JSu_ zR-B<oIbT4-g}H1!RyYsL_de>>0;dV{1+*&Io^ZylRhBq32j>Zwf(wOPgBu9912+|B zm#dX9UphMo_Xc+p9tQ3sJO(^S7|Y@VMwwWq!eNZ?jo=BwH-o1Nvs*S-csckc;T2#m zP-8AN_%30tqhBNZ0Qdpn4d9J7qx>I+Wve)B0q+!k9K1((CwRZ`elS<AF|q^T!@@6u z-x7Wa{J!uZ@JZoU!Ka1a0Dm12%lojL6+Q<3S@<~kqVUIHGtP;aUlAgO&w}HGe*`B9 zp9fbI{u!Ju{3|#|IKb8awZsx_;*C|9+hmsr`@zkH6TxkSQ^B2ttAe@oj-`?V?k8Le zJVdwzJW{v`cr4%l>4BR+PZEa~U~I>1%Ugoy2)72$7j6r_Nw__j>-iW?NAR7({35wp zxG#9EaDVUy;WCc@a-APNkA%Zsa+Wjo>N(+6xXWG=)?lvrqYfLBw}l@8e;~XG{E_ez z;Ln72g1-?i2meG4AfVl_ToQ+8z)|r|1Z;-6!kCf01g<K~#w1(#H858PQs-@OJ>mDj zjfBsFTMPdP?kfB%IM81#mtYwojFmIS1Yy48O&5*;&k^S6*L>kB;G2Zg!OMhmz$=9d z!S@K)2d{THV3feJQ5-np#pR034I84TgxL^1EzE}KfH2?v4heH3e{LX4za7Ev2(wZ8 zP`EqzV`07rei4uBPY>6^@|`#=2A>mN4gO7dJ(#=IQlAY-n9t#T;27a&!Q7sfI)}lj z!f%4B2p<J!37-nUk}sAo!F7dy2bTzYP%)beb5o8s!ZF~^!d`GMVIP>A-!c*0tAh(P z$!Xxx!n|F%STjI}>aa`^hkD>y!i~W<2=i84B+OguX5k^=+lBc(_by@X&vBpdeDH(9 z+)rnd@G|bFvrQ~_!l7JPgP#$80Q`b5_uF_y_(|{)VSej*SD2gAa>Xb!_6+zF;TOSQ z3cm;DO45WZT>n$BoEL{rz`qNB1?IpY1B$XZ1;Jr{qVWn>1at2_>STc{3Fm?{gbTsk zCzv|*!F7ZigX;&x(gKzy!fn7Uh5LZp3v;bmSK*Q1-on$t1BGt@4;K!AM+@`w%QeCe zfu{;rc@&n}V&UhMdBS_Z3(L>kYaU2ZmGzG8W_PthTRU(Xt9$dbT0e-B`RihReuvo& z-~L<ggmvQ*y>h47%{+XIK8>>~*7cr*`0O%$<C73?Sgw!q{N?RB>nS*w>1j{Vd4+y~ z*6BL296{fvui`07?<hBCsnYWNU1o#{-FkZ<U8)!DfpogQKwF9KycYqS|6H%xYvy69 z!ApD1>gEey>2LR%Ibmmpqao9&`yd)T!I}8f9z#X=`^!w6U{8F~bM~3OyoV;BQTxjY zV~4_h;KKth75mOGy>p+LgMAe~+-K$@E!NXGMe2N<!dIhCEp+}@Nq8T>GOmr#r^3RL z^{S`M_{(#X@NY{}JtajY_WwyWFODuh`?UFbc-$?BL5)D!cVZ&-k-HKr1kR%(Vs_G6 zNH70Wj!8%x{?|fm7~R5{I+MFlSrrT64^x&Z(GnTKej)xp$3ylhf^%TQJorZ)br4p# zX9ZPNB$s}Md)Ob2pd{SG-fg7$D#V`JgE&5FvP}%Lx<GDnYMjh-I>g|@dsE8AuwfC4 zi0n;<MNR|aUpyRu3Z_5}MQU&j5qJ#-5;dd52(M`e#|b9kd2Q)&fqv~pvr>Tj8hIk> zb;HTaPa_e<@4yxA95jz;#D_;*R|JdcQq-}O$(>J3{=3nrVW*%N?};9`4lcg;k;`L- zZ!7qq;oA*`x<2llljY+F2l(M?y6DNX;0`}`utVlM%5}!`!+iYgq<lX?^qk>)O6j== z&6*wgAuIaX1@P+e-Up}Xm!Abk`X`K@g!u&IXfMA#MjzqBKGtg?bJ1^;z5c1A#~9Ja z$Z_5p`ul@s#lU_9Vfgs+t9<j|&GdbO$Sq$}$UVM(_zm+VLLTmG4V?%dHz<kpg`*gv zd~KK%BjHY1JQb#}0rc_HjNvQ9ukzJof#Xv0%Xh>;gcN%g0eNEU^J}(Utg#ImO1X0D z+Sq2#!y&dhJSW9=yap2QYX~~FGZSohpCflAEAJ`&%u8l!r&&lqY;Wc{+{>?+u><KG z>E&+Yv4hD`UVa#k9cq`0f7;ZmjM(9fKGw_cb+Kh+pJ8s$)m}D>i}=j0?CsnUPF{Wi z^LAyj4exJ=+F_5kl<BgQ5$Ua`Z+zJ-nDhtrdontoUEJPYWWTo@W##QhPVh!kX8<|T z%Ldgugc(foenB3#0P-{=b~#cL8P}HE^mrFT6xWU(4DT|;AJ?9&yp43mAv2}IEl5~g zCp+tg*%9vXg9{)sJLw*W%yjP?2*Ov$HH@)uhwB>-nHhn@h{;#K0+b@X{8Z~}z)zg9 z-mBr+*YIgdyaTCI!qg-gvAf`q?rU;03t}|9`I-_9@1Nvm_dwO-okMQ!1j=pjd@aba zUiJlirDUIXHG^&$pe4!M3qkl=k<+|(idvH^qnf<T)NF;nbYDBpTJ&Cv$b9YTY<Npi zl)esRkC$2ZbtFeR@pK}`dihxQbte0~e7gF&kdwU6k-H|-lIH!E&fVhhTiHlD6Rw|l z#jG9REv^=^0;hVBEwz|mlTsOvx`{=cYOge3!tY9Hsnd`)wVL0RQae%kZhlruwdbMS zGZ0=<IrmPjWpowphEqkZB2ycV0T+W1!fZsO9_Ac6m~c-=J@i$xzIQjh4OJ=7N%89Y zUp1@7T}M$_Hr1+~#eVUxnwjRGVfxIgW<~7P5`EaLt!9^(95(x!<|j(u{<@i2%g)Lx z{5L8`kbolmH-^J}JGlr;hMl+9m^Z#1)xBPyc-{O$4b?BcVOH;GXYng$aXlO}c)``z zyx_0FTHQ|aH%zj1$GSlE*Xa5!n?duA(#(}eABRWsW8pDR7acJxA$eVon1A;B1Q%7s zD?7C3;oQ)UCSEa~5<8S6#bAs^tVx(mNX=r{58_a3KEZ2eW7~7KVp`Hs;7w2h>)$lb zH+h5Q+RXL=WqVq?T2l!xF^-RBwvU_PqZz-^L6h|z|Nf)Vr=~vgmYG&$2i)FPV;7{E zy^mvi#ajVt)%ixR>|4y4Fjjq%uJE?muG^i^jhv#`td&L~4bFdDcpVYP@ZGGX(P}8- zOUgP;$pT1X>?>HBgm4qfSf75Q3&ChrO+WUw*{ADA@DZJ<c#Drh|2~G-%xKNkOwpBW zX&@wx;j5QX%1Ic>cH-`)%L9-(A(kFCb+@Bt6)!ugsm~}ju&u}F*+<Q4oj7a9JN_qn z;O%R)>WM6-4C2l!c0!G|X~<97K-S$>oKzb>u@>DJMhsgeN2~PbF#YjSGqLh6MB$x2 zgenX#hE1BNY}USa%nIhg@bdh3%<Ra>#}Jx{e;ED$$eguG<v*P?-v}#D{mgtL{2xwQ z(~S?9waOE|HQ$WDY{Ap#%<BFIg~pf(Bc_eT|Fxf*Rb0}bflfPbHdV#teb1Y#G6Q_N zgeJCSqHI(o3KGWN^bJ*;hSNPl6WBJPiiak!jYNTkc44@cob2d-jxae33pbPVKeWM# z;2%X!wO<_$*q?Cz6bBAcdyoivt`3eCE(H68Ir^R=+yY!txC6L085tnkQ@g<3z>P%S z1I$+l>huD)wRcj0r4KBf#i0z`Q}`-ye_?d+jG@BUfUgps0v;#K?%cJ)OTjaQmw~Sr z-U?nId@umZ60y7qUM74392EW%e7Epf@cqIU!F)+!ZaAA}vv6%NJ1dme1D6XA0Y5Fw z@x=pRdtw^~7>z^XFcJKQ@MJI-x-p<>;17j4?)b6rO<;BqsB<&;J7Km==Y%<?_?z&f z;6H>hj2JL{s9YR+%|dQcgbToxh1u`R6z12K8p3VB^@Q7l8w<0a-BOsN@9l*Lf!QBs zT*JY=ZASTzg=L^P@VX8co&+8(%xlaY3+Z_}c#7~$Fnf5E&jsHg%*(n+cp>;^;iX{C zqo+Pc;#b)d+hDmLmV3ovJ$SwF2CzMy3p$&@_H-^V2f*y<T;Tm+dpZ~RdGLPm`y$w$ z&ILK^mOY&dd>nj4bONVg`IHv4kR@O)LLj#WpAl{g=6*wzcK}}y?gVDrK{?-2B80nx zy~2ILiNd@b6@+;Ss@Xd!z%wsFwm7hOxhD|=WziK0uLL&~UIT6>{0O+UFiWVT@C)GX z!biY;h2H{me<Fr|6!p*9F9Mc#;c&G$ybtEP8kJ6h*`Xqz0<*_M{sbHlJ`G+h`~~<{ z;UB<v2>%Aw!W=rhj~qZiVX&+hhgk4VGTO^xc(A8-fg6GMi=1E1xH^wI&A^9+TY%pZ z=H=tcJnD1?pA;SjJ}q1Z4ty<^k+7T<z8Y-rF9FZjfZ5e$K-YpfS)RNA94UMgI8Jyu zI7v7Nt|-h)mM**=oa3<bFU{?_U<j0B!uDJ+@J_Hj7Yw`yY|jM)vxeJK!N7;X_Ea$N zF|a)q4E!b7o(cy34m?OAJ_DXeP6EJ83r95!S*{ZY6Al4kRCH%U3V49XndT)=IeVIy zuszKSOuzOtFEIUXDQ{BMN(wU@6qfg_ZXGf)22v@<>TZ79P*2FQx|!P=>wP$@G#!&` zb;sz?V4l+TW}a&43%S-AjNN=w1GYZ8Nlj}O{t@1eny{5=D-Wk6-8;|9S5N3bo>kr4 zH$ZR5vvTt4<zP5H0?~^>oiccEx;D>+B2TMh5BBKje9LF%)p7pi>{(F~9b;r2-D6Br ziXH?dr1P453;%gm2YKqF_u}NORfNxu$ZcJCsU5s@yi)j@`iKnwxd#7-HvIfZ6rIJf zoeGI{t}RHnO;P<ub&KoOD{5Gx?bT-`B@OBp+N;m@wJP6O%L-43+3iPSe~sp-x8B{{ zsvP-b6nge%M3Fwx+{*Fsiw(waI0*>jH=o4l#1>YY%<;UPoP}omUym{X!@>Bla8`Zu z7JXd{D>H5m!;1893jy<#S8r-zRaM*d%Pp*C73Ra~ud$Rjp%BrCLkw}*x@xJFsbX}? zQmcx2E?$?FT8-;Jj0mHr@c+*FyovA`J(XVqlDyBOosFKh08ysl^=U6;K2J<N)dPj= zzgxdiYNbYSeu~E*slO|=G7<+u-|%y$P{7X*R`dK1>Wr3FYTup+`Z~Xb-`W0wsDiWn zFUH`@uAiHO%<ykT7}Ndi98dEPK!Hv5Uj$F_b2-6e!yE(ESbMN1mMxXfyN9oX-ZH%m zL1P`sLoKZ)SU>Y|ODjFV&)~|>hnVT-u78%lBKmJ0e~$zdp8r!6VYvS}xJLLtM_MEO zClFGUpPwb8jYRJI<?&6~1DXFZB;WAgj}$2X8U(@dmHlvt;OmoFfN0|DKMR$_coc>w zzJ#Mo{sH{*V)*S>L;nDz)%0_^h2>`t%H!t~C(O?QtZ+X!k%{oXiF`)-w?h);{|*61 z8)mUS(8_9$e~B5>+G^r0LmvD;bDSjB+ei0qZ53d*gGH^aEY(kMY;6rP-;36sHrA-X zaK!8{w%=gdCubws{`&SCNr&V%NWH&Ay@(`qN#?f<e<Rz{EtwNo{7r4O9?9I>!{5TT z^hxf(&`NE~faD&REklyIoY&vVb}35^W9nKnw16=x`2$==e;YgOG07Zc_qVexW0S`* z2^|#6YkYD?6t=&MZJChFO+NhHZM8|s9dVKTz0^~XO-|-_N`G(LGCg?+0~nxq-DfAi z#{dQ^3u<$d$1s30)q!&#=O=SgihraU2+NJh6PdbE>Q`8nCUY*0e~jX6#@mt?GVHPH zJy=#G`)HYB=V)c}eR^wKD@Wz(ciN(9$kBhawQf++`ucWOy1GuUX=l~Im3gsU=*oP` zMDWUZ+gk<ZH*vaodn+ZD<M81gF6=Y!*JbUkZ1c}py`;TWr|<;QmslYi<q!*vO*or3 zP*m{~D*uUGCRS{MVhs1#f>ixkdn>>BE6A`Xy1{KM-{(-ShW{&Q`utrGPr8xV3?X=; zTX2z$pYvD@KUX^{e<8AL`n|ea2UM4EJ*|UPJ^NbL^saP?_0Gj_bhno9=JRrnLUeb| zcuT^KwYP&+Bh7*(x)(!@9g0wW(S7(IQoZ5&0s`u52Q<JA$S_+n)PbEDY7Bp(2fsj7 ze(j4M!eql6BN*Bo=<(WqhtY4OVR9u-^za}oW~!dn(aOfE$-6sR0|VT2IMRPLDxc4v z&1!2TzJ?3tiJrdz$?^Y)5;OeE@T>e45Qb^QUd7}`FaHG2-a&APzC8>63~ximy@G6d zSrw!2AbY&WsdFbe+}n-G2sQ>sdKaRMqkFETCDxmT>Jhz)>@#9lAT>$Rs~Mp80umE_ z_mgliya^2T9<s;FS{!{ZLye5L$BNgGqrHCpd?%}=QxFeIL1<rR)SKs{bj!|Gow%ti z@hyxh%X=YS-_Y60to1Tw+xX$Fjh9>UML)sSj2%!znjucJKApFB0LC7P(XYZs(KNV6 zmwOOO4==x!NADu{^zz>nNALay$?fHh#ElfaX92j6H(gilVx^id#p;G#tj5(iF+r7@ z^rOB7SK)p;*v*9kqw09QqKj2Ab{v(?RYmCO+4`w2R*v~`oIcsb8m&@vo32(NR{YNB zYIX42dK0J@PVX7F>en6DOK^o!hi+EGxK4~<-^Wl=y>rLuW!<dyd@{Y;&FTu3tnSu} zw0_eaPq%S8x`&mgM(FxItmZ}haI0pj$|#%$xEOio(T>8-%fKnmc@t0)uxG)(ANE?E z$~W||sw;+esHas&b<)4`v_$9jvIbXPhC)<ds{&{vK}H!4wdOi>new2&wwG1aZ-@7_ z9UlKLbgfSMwO-b^c)Nh&?E>-`HT&tdy{$HCvA(6ZRm1!-PVek()l?tolfA79kp9}+ z>V;G1K2}N7&v5b7CX<6exM7W4JH|>Wc8s<Qb2c8C$mdE?wHX7I_!<qnQS%Y~Y#*xv zb8@VYRT=*Y@0UJSUNyTw-Z$y3GIG;&(u|3Qdf&O0z4OQE(!N$6{Y>a<HRSmroHJ}s zg%&+=)>1QmWmbh2+XW2H)qE~m|Iyb<^V@2zZMA4z{bp5kPCsN2q4enIgm!a3t9{1P zEX6t2<}`d;g<4)Kv{A6L_B2K6k%%AqS>y1Pad3Yp{WJSpRV&%`WShnOCE=nLHANm* zWH6(5>&Ky(V8{NN9eXDz<n8wAWAKPe_*;K#pp&>CZRfd2KCaAF15m-%>n#JU3XZGK z!yLZtxV}5U8YvmK#idAP-cDRoRp^<D@tX;-Bandut>esL!$DS6pIuGIc$h}>j<WnE zdh{UV`;9ogc94}utzCa<-R9Eze2~?Xu8jtx2F0^%w|N#IXTPCWk0{0twyt+7@(DX7 z^I73o|I`T&3vE5^wzm_ux7T2Yx1=G~^-jK`!kDk&=&D1!Ziv-0zdcf@vcsGv%XuGG zYgSf8;qPM(b8VLs^iWe*9%@y>7+c9utET@aUb^0499pf%N;qFn9ctZ%t=2CMwI-^a zdg3svNVU=T^R!sMIn1gW%Sj<IuQHu&SLh4FtXlX6Tw}OZv#<hcX<C2g^W}7?@QLRP z&bIy>X-H}E7SeozE>tmEC+h{naWy;Yb;B+GU&sB!t@?P-{!HO=om^(sQ!RAIGApkN zX9K2I{5S(%c_oZCkE51V=(&iYbk-}%aIY;c-&1C#R*gK3hS)S-_<vy}v>dB<U#(Dn z-96T#h<`W;T7Gf8bp-#Xvi!B@tox<}-b8_gMmQfq>#fiaqd7%J<3^Lg$3E*0443vP z+`=>*l2IsjnliSLY(il8uBcF+H1?8S6eZ1f2rsk**!~yc@f=}*sm3+|RhXs$8Mg^d zS29YQ#{PHXsM|E0`5qcty_1YeN3)5HDn_%Poa*p<WV9SK-;*mi+%_8VhZYlahIDAR z+Y98%j#3_S6<SL?nv5DxvyxoRVNSzU=??!$Mm?g*VAaob_)BtihkK($R2G=|=Np4! zO@`^odo0J{r^sx)VK^H~)o|Fuo4uyP3&?p6XR=AmclZFgmc!g0K-G5mT5^HI+rR-; z=vX+?&4FcJg^z_<dS3{$#J&^eK=e7`D&WupWfn$gfieq#UtL0j)iJ`%r(YO(!w9!n zn29RFOcOtK&~sgIP2pm2Xn``D^7<n01m?PP>T@KsrSM2_d*SimuEI0Gy=_MMUk?jE zo6_?Q;Nil&G^2%=fcb5NI;+4_gdYOW5`F}HgYYKsBH_(oe#D~R$HBJ?KM7vN={0mH zhvi=3-C%nZ8}hwidx5gtmi7W=;peFj#$9N<ER4!+ye`aU?5HqWcW1w0=<~9ELwST# z|BN5R0=e;vFfOk%5)CCrVBv=z@MlB`v#!Jo^R7!4=8a?THw<OgiCUCP`%%}$O+!m} zA^U5QF>}yCl-O>B78#?m8ofl$+}MN9REDt!pM~wgXD~Bh4?cq#zCHL1W(MrRXRw#| zpFR2v3nQ>cpTW#ckdcAeZahqmcJ7WXF5WK8c4?O|?}%rFGr@<1dH31_%Ls>e>ARG3 z=|&w`j*C(QFh996GWO-a6mAXvUU(t+H{lz>2I>j*mjF2kKwbg%3m*cf2_FVm6@C*O z$P&xjuoMV$e7Aw{hhTdRFakXZ=1y*m;567?4-EbS+(+bJgE>M$oo~U{kkKMC_fv%H zgJ(G$FdD*ggE%w>bL%&HXa(jMV{%(CKV6gCgI5W61K%s$A8d~kLuUy15s{AsKPEgH zyhC^*c(=WD7anH9@~k+_2Xi|YMz$EtDNN*B!EXw$1ivSIH<+`ZsPh2$Q{m^qUkS6= z&j_=0xr-b1kFk-tAePU;eEibkD=_z?A^!;W3ZDlj3jYGGApAR+d&^PZQutmV90j&F zE{2?==S3p-ft!K@^pFfoYjNO9181X9UKQL&xE6S@FkfZ3TN-uhf;j<&%oUaP05Z4~ z%&{oSIop=&g!wkhX24!1494vpaMlUKf(M*4fDGpSy<R-9F|h}YAx{T$;sFE72JaT; z^J2enJ@7$c-c9y$VCc61za{cEV0$?*mu_@{#a<5#rS4#RJus5SMA++r!PUSQ=oy>= zw$}rLnFxD5Fqk#mUJnfBEp0Cc1{Z;=qSc|_VsN%F6O?Z+-Gu{dyS*M5%mmr%fx%3W zy&f3c6Kt;s2KNTr>w&?2!S;G!@Gx*+iC_%aUJeZTB=AU)PX~_`4zT9iI~PM~Hh6|O z@Tqvc@I3GW;icdu!fa%g39kWj|9|H4e(>GG>%sR6KL~zE_+jv7d+9DbY=VVz_~>~j znDeg4d%#Z%KMg)0d;ok%_+>CBl2D&58voH2nGMv3!ry{F7CsN=@IQ5aVf)W<JZ?b1 zr`eyv?Cp3^RVl9ojuvLy&fViEXPrn9&IH@bej%>`&J=k*xQ1|Ta9v^618y*u5P*k9 zuy6>5fi?x(J0OEQfH}BAd1r7x;U3^2!ff?M3J(X56&?YeBzzTky6|Z59O3ccz<jY> z2g|L(>;>H^i~=%N3-e*KR(KhBgYaG8jl!$J_U6X8pCNLV_k#I^v^O^fCxh+HjoJTa zQQNy4!-4m@y}L0u9sCgk1y=`uCY%GdH#CNvMf#J-S)><)`AiANqnmzPg1y4L@A(~q z@{ZtCd+9DLgJH>|11kZHy}nnN0~XwFpXUEC_a4wyRPEdM%;d~Dlhble2)!kwkpu_{ z2_)3edy^u)_Zm6~dO)d)(%A?|5qv~Iiikl3K}EraJdfB>5W84FvA6fS_PHZG-}kQd z`d{n)*7{~8XMXqYefI3xrS(m$m+P|AfNKENg(s64U0l;{;>F~IsQTTd%;bH50@DQ7 z_M7-|a=EBF&sHntm&xU$>aX3zm&p~P>Uw3Z@Gn$HGP|IqSIr7@NHszYG;Br~0vXM< zQC^q{P*s=#=WcK`gFmCTa3Z*#Fte#pnAy}sI0M{`Tqzm|y*M_?k?87J2&j3{)v;iv zwq6|zW&-Hdv0!?vSI2^@f%WQGa1wZ-c)%w4ZsD5XmBOrwYlZ88A0}5u`ZHM`)k2gH z2{S-X3Zn)Z9D3%;S_Vk3hy}y%=!#e{+W@^H7R*3g7W0ff_oJfSTHtSmv%%k&F5S(A zpjW}N3gFVKV1@Yz<#JsM>UtF{n1R--V8JN#Mh!8;?8_&!rNUKo6YGVqP^UY3;VU>o z3q8aTTEyteS7<N`I6O~>nD@nGra3OX@>O`AsMFCqg;}1K3ge+_EEh&ai!OYv4#0(l zuUNVzf?oLwrbBw=E10p=D__Bk<x_MBjGJ+moCv^Gy4aQcuBg+UOTrA$r@{=-m%@7d z;SUNdLAYX|TgtJ*bSO@k4(SE1Fi(dniaKLfi(Dg`TDih>wm_IQqNy+oCcmG>M__@a zv4dzd1$Pr}3GOZ24$O~L^q?nrm~cPv7~!$tNy6j7(}gF3Zxfyjo-aHH9JyPB1rSyW zF9fd_z8lQ%l=OH7_(9>#;9bI7!25)^fgcxs5PVelQLtXr3U>~J^`cguxOD`AUeyYX zr@;JTM9+?cF9<&ez9jrS_<J&18<vS*gjsn15@vSTP@owW-jFaV3nmCh)f2&01Cgk} z`dU*o>VmU{>w)uy>w_B!Hv{wI6g_AKZY$gg+)=nIcn~=y8qg8KtXboPxpj<DECL?^ zGlki7>qV-t%tq!;QD+R63Zo(z_X#7xjJ3inTpNWMnQg)a;C~4hf%k&-(yf*d9up15 z;D~T{@YBL9bf<*-g8A)`G3yULFFXYNuJCZMUa$%?EST4*j$~$*{UnTRiWq;0z+{O* zJ4-`+dd3PfRpNx1DrJS){&21^%_A3#B;nd%y%rVfjD0;(XP=-@xG}hyW~6^B2(3k< zJ-EFvQ$jB~Ma5;P^`cWS!plXcMm(4WO|LlxGthd?DVWa)z2+3mhn8M*3TF1{HK$-^ z*>d*(=ukR@)xtSoz33F`dEhOgUI^BUPNB{~?-q3idY>=@{R|lnGPU%YQ!vYlUULd& zqomiIf+I{iz33DIQY^aY6pX*<qEkR7ST8ySGf8<OB|Tv6_(?b){D&};HwH;VGcCY+ zEh@MzI8M}Ap31WQrJ>#sDvJhNv?Sqy;B?`^;M&5&!1aVjg7qR*xHAsiOw^0Pt%YZR zI||PQcNbm?{|&u(6_)RX#z4_n3mz`K9XwWe2Y9mZF7OQD!{E8XN5Bh&kAfEovq9TH zM*Vbww~!+c{1A4E22#-2EgS+L5N6*}FJy&z)`(-G&I0wUF!S|{a0d9Sa4qn8Vb+3o zg;|~=mqaLn@TqW1@K?fJz~2e?0RJpJ0Q|e~ATU2A#lu&|tgJ92R#})4OA^M-NRKk| zA3|->V9e?XGiHUtj9D{b#;mn4W2P6cLXolQF6xcIw+i!#I#9R>JY2Xncq~sBWvJUh zm@FDBnKOi0=;jFXk-D6W>cCj87G}&g2;*jK5oW}83MYVf3$y30*Q>%E_CJj$M1w8b zG2uk;v%-w!8DX{!{MN`oFvjl+v&vl(X4~+oa2xPf!fejJ6J`zi862TQBOv@K8e_mN zw8d1P2lfgt0EdL{0+$nB3a%u454bitD_W@Q39~gU6lSB;Oc)Qgh|yXE=66To>fr9e zY@luxM#E<e6h=ibh70F`#|kr5rVBR*&lP5>ED-JlUZNT4&k}yGX!HfI5grY`UwABd ztMCNyL&8j<J;F?(gThRq5@Dv$Q^HK4vt;C{AADXf-Gu-(<6Y6<gXEGhlkQXDieR25 zOUq2H?}Ygv`B@n4nDM7@KA5M>(tH!JSGWiq5{|TkkRU<_a5@>!P!tEFwy>_2!py%y zVHVhC!mOgLg&ByB!gayjh55YTDYkUKK6qd}+kXhGufs)yAssE;4160oJ6h%D3;UqH zSU3P)E{yibSS`#zZxCjnw+J)PJB1V3{_~t%dXNH*r^pDh3;fJYd|KEI^;d;s!LJK5 zK<@}M<t_^2W_%>fK=3l{=-nZg?C<6(UkzVlPfv1<cgz%3Z<ed8^~y%IaF(l!_4`J3 z9(T-jO`h%QY7S7-cw4TX<87@fGY2=98jhQ_cdL4Q4vdabF}Fc=X-SXUTqP!_&d!54 zLG{PYdS!>&I}e5m)NfR6r8?e@+ZeTpx9RE%Z}U~7J8)aB?%{2NdJi}2$U~}D1Qv&= zxe=(=QZM6Xoq1SQnGe-IYW#etZdOn6mZ*FSpt*Cm8n6JGBh(&<2*Gc>C8&;f;<iC; z!p%DKsQT(o*9+EHkE+M-g4xX~W}#~qR%g#$2tx(xW!^fe%8OiC*5~o6-6B^FbD<i) z$dzu_!*hSIQj1*4*6LZ&RoNw|QJ!ep>ffESqN}ohUE~T`7iKB{Vpp1VBw6L*p1*l^ zw4Ez8ZwmYyjxhI&M1C8yeAphYfxJo|Az^J>ruM=K_c`<udfL%>ychCK<D#GQcq^$& zOI+U4HQI&hq~j|elUpx$%?GJ9&Bi5@m$>fnMBcQJ_iWkVgmDu8rI$4nWSwWN!3t}x zufwEX2c~Z<+TIRDt2K4vZ>2HQ>8p*|T5{|vlpN0!yt(X5ee;ZgNxf+MR=5?@+H|;E zirb~2?7161Zr6kOb*yjk>nhs`zgTx&PP^oq45QXhP_k=AJ+wMPC3b>(dWEZelP{s+ zuHb`Fmv1zFqwM%*(u2RJB<_GIYXY?^F??><St$7LQ}HWZshG80u+r5o?iXmB#D9Be zg~DCcij}VJ=3({WO4k>alHi(IDGXiYj~*2_Hy6iX4CGPu@haCLE7nx^uXZI_znJRS zYF8z*t9om->y-JR+Pucq(|kc)TjMIg-UFFyA&pm&wJ2A$)oW{A^$NH}h&eG8u5yWd z)@uNB@^C1o&!kQ<b<DxFECygY)f3@uD*S1<4*twlz1AU=UDd<uP~BcrgV(z%CN7}a zJ86+0GHbP<co+L2{UOrohV`y-uoI(PeQ+C~T=$sos?U|HetT{8ep=<1zgm@PbrXF} zuuB8CnPSw@2k0n|46QYm2Di{&M~L)e^adTSCpWkn!;c>~xW<}qsv-B6`f-S6eQ3{W z>1ZCN*nnbpx^$F&^nw^okEgVkQ((kAMuTIaLq9Iwul>l`=&A=lMs9RXtnde&&AN^T zkzfCr)2F~W3)GhzUD@%Ypyu>zggne%K;4`rDr=Lgn)QvTI&N}RHS3j(-Q>F6XZ_?> zwc2<ps;};d@g<F!JaJ_9=%F))j~P03MD~c0GqXodD=x^bU%&LOa(1~Yr~^+0YyJbX z;bXyu|7T+*aB}%SURQX0pR2!`{CvD!QoP^wXdqOOV+<ZVYR07Dg9oSN)hozVwU4_h zNAmwmH9z;}m522T|4Xy*zclme=H298UfukgZRX|t*Am9O+`2cL&CU7SY%Uf!=H=G^ zTc%jA{>_H#HTW;hyxfvsj=P3tM0D9lvEs!Yl>VOoL-t1150d#9#C4j?dWws4J<PZ$ za{;2s$0M#WWVEZi9w75kiR%S2dqB8MQ~^x$!800H1qytq<H{zpYlQ1nGP_2&<|B}$ zQ+4=3(@cu0b1^$-S<vq?!gPxBd#PR?%wuWDbShPty{s&5??jF25OPGL2DpK6A-It+ zdsCgs=o~NsdI&S3eT5mh!NLp#H@TsC24cK0{hA`2&iKy~ArpMNa2@bn!Uf=E!t710 z5N-utBisr65LvS9k(>A_vSi<hoA}@02tT*-4dyLsfGdM93s(hyCCpHNFPs9_^MYVL zAFSsEf!V#&^Mb&w!Li71y2(brGFi$>(hZInsUpB_eUwY-XPTx|mjcBNZ^$SP2IupW zk*Y>FVMeaEFkjgQ2(#P`5oRQ(k&$0?XO3p1KP~I2I?$lyMPi5+?h$5rTqVrD-a26p z-|Zs9Cpx-Mn7Qz{Fyp}GAvD7PasLl8Q~KZ9W0V?Nev2Al28e4+$PCa&!VJ(C!VJ*2 z!VJ(4!VHjJa0<IAU_Tr#{V=81o6-?n$y7%PW%)DGMIh_Nq;Q>%7Ev9{yw{6K!K`(9 z+737w+)K=)g82xfdA=hI70v*U7R~}s6vmr@F-^}Af`xhz=7<IhlwKPO^#)+BOQ568 z!1oBZ0IwJB34TDhFL;OWMDQcRw}JNy-wi%2ypr*MN`wv2ct-dE@bki3!CVK<uVX1- zz3o4kvH3*Q8JjD@+2Cu!jKI&rY)k$WW&~Vlcl3GET_AWVz|n4CZZJdc1+F684_rfd z3YZ-On&C@o9bv{SPk1@Fq40g+BH`8GHo|Mck!~W~523d(V?RK68+e%T4zOMu3Xczf zr;GY=@ND6;;N|41(a*eVgjrTL3a5g%M>)E^|1QyBlI|B~k{%XjlInBC;b;!{8Bu5Q zo)%`y_^NPA@aw{@!FmlS>~;X_ZU4bt!B_MgAqXQOToVh$;Gcx=1pgtt7_7Jbhxw&o zz3o4kNgam=5@XDy*3)*ttH65N4tO0{Pul^roat#h;7urh(Rn)%c7fSVqeD-F8wsBT zcOj$h@u{V!?SNSo_4-Z#lXr-iVakmX&IRjfJ22A_JYCeAfVqc+-rlo0ggZrpNw-wE zHF%9MpMD#KJA=0g_XYn;cqDkQ@C@){!gIjfuZ9tr3w~M{k-ybACBgz|oE2UOJ}<ls z%ndkbnMwVrFbnKg!h6Br2_FRi=q^dT>Uz+r-N2|bb@GUz(}&i%(Pzs;zv=(2%AVY} zKfB7-%KzVKqR;lfv68P2j`Dn{24;IRN*ey^a$@ji-SQ8-e$-TJ{%~!zjufc8KV38N z4z%Y_s4i5$;b!eBRGt390KhASYV%*NE!Ne-b&c&Vrfc0jHr}(>y@y{{NtS7kHt|Zn z#<KCc-BNvQ*)y%ryQu*&FzTp1F)+1O{T5?qS--heO_yE6+B;Zva@lG2nlyYcSF>Dp zvQ<7a`u5C5_vW|fjLhiU^SdrPWDU(+f5}r$t^Xn%!tr2bY&$*wU?wU!?37-nz!IoY zxk%*eW1{9*uiEJsXbcJ50~g#q(TwNgz+|k0wRTQa7i_!cjn`%@d@XO+&Cjh@f6b-T zH0%1(l5TGMzDhohxR`e!pihR>7m0QiC)JB8XL;7CK$4wSc{#cdmU5s}x`){z3V0p% zt1d})t2#}>2wrWLLhBgNj=7aM0FKCVSPlcra#*avIGJQ81^$hG1lGgW!_8`~zDcsH zo6o6W4ZA*;?zOIAr{LXZTn)Qv4yTzrc~^AAtvCvWFCtmuKJuX@2%49{ZWrI&-FS0E zd+t*2)UX>>d==sFPI(Z9LctcW<(*31grK8pC)-J7rUl_(_%B2w5*~@@-4X7uh9=wP zd;Nq!&k3)`@9Z!eky+stelC9f1w12M4eHawZQ%B_@GK<S)UX@BQ^FqjfW@y3VbnM1 zM>y@}GXp0s_KQJRVzGJ^PFu%(>eFPb=UA$eQtZU0Z@{n_=Cj5M?}jTe;XnY%7#@xu zgdOIROm{d2VfKXimBk6)4X0wm{I-RKr-v0LnU-tEHL^Hi5z#Qi&%ibpzH-Y957(z! zd|e3UzX2oh+^NzPEMO-i%#Q&^n7eYC;Q)e(#kcDH6uU0=JPM}TZOt93cdFee$g#lC zk0W5iA3PDKwx-&3tjm7&S}MvnPIbGUYWFp#s4i*t$jS}jVkpmi3GTK{=!(#U@=fMg zyMzwvY?@uMCTCJ$^E9e;OSqK=nrWeDLNcuuX`xR-mWoTaD@GFOb4&9QA~GUj0+Kw` zN(-YBI0_qTqlGaEa}eQBJG~ZkT*7dqOQ@3;CM0kTb*QU0HYtJMEkn1MJdL0@fuDpz zJ+v@AVHh3gV=|9sCp4x`f3uo{X@K(*_R)nQ<_^?}`3d_N`eEjD2n!RoF>oWyGBB_- zVKj9{nOy3)JmD3(Fvk22!pek+6sG8Stxeb$Qop9#sb(dWSkq27%d2)Z?b~q{;0rbF zMC;L@`kbmeR4Ah~**`)sqRHMj!>*Ic4NXIzG4rYz79R|uv&>a5hhjtFKNvL>vb`C0 zOY3q#UCXe`4bUG-8`6{&)RUwdG4Wl&H;@|fjmb{1D#94wgl7D{S(8Q>@lDCWU=hkq zd^2(=s6Ravk>gRec#MO$h8mt}XV-lgrfw{ceH<n%PMRoFX$1^fHQ-N~N}mJWF0HUz zJ)3D~H4VW}ERW@krto{nO(X1Q{)ERPDv5YefeTn3TTJa@un}&ASexNDp<sn;s;n$K zg{822mR%!t2W)yfbJ4ax$OR?dE?kEa3jTt8^>*b9t%P7uZOF1~R^$;9-dpIbm&ej! zeJm&R1mV&<aH*GesgHKau=uUo+n4(Qc(>4PZ~rMY%PkGP0~m1H14kFg2DRNmw2K9@ z_oAM82N%J-RZn%Rg*<PhX4bOv&8=#0Eju~#35|t&Fh9fGQ#WkHzo}DXG24zXN1TlC zYW$etZ=hg>Tfk^cm}8bMECOYey!UN_PVhmL5bp}E8#97U7~z#<E67^mT}5^UQyA;j zWOuLzL#Ddawmp@eVcWQtZKglC9=?0mkwY-5CfByhr*W2tcjI5$3DzF(COYBxq6=in z-XI#Yy|wM4fKG|%3fbTe^-FC#8!OZ@>e$(V7wP$4x||ZsRU_-z$yx0Xd+&h>2uZ8p zXommb+ej&{kNuI6<>F)SW2W|99fF05w?f%lQVDK!3o@O&N66iS71XzN?DCa9fNk$n z%aH_qg4~PEd#o729T5C7pc1p~5rH@qDm&Z?`tI-|wJIAe*T3V`6WMk*9LwpcYxg!| z)S$X{bF;hJR@bhS$S;)Ua~7v!o2+wH4#5K`RDjn;(kY*Mx2~OsW-=}Zx9+M{j(yS` zTw>?iX{PmAY)S2Ub`#UgRO9pP_DLMyHV4|H5G=Ob$-Ur)Imo6{O;DsWx0Jk*XCHSZ z`)RJw{2K3l1;xXM8D=9kxrL(`lqlY=4j0;qRS(eMOltms7N+r7!<@y$NI*I^>Zrae zw0EQyAikzTn(6Ir%+1~KR@ziAgjKA;Bayz14ydCI?aCqT{wBJ{g{_U2s81T&O)J^R zAoD0y;i_>6|K{e`=*T^)Nh3S6F>~8|nkC>nm~3<yS!JH!5OWv_Rm7TLo@9=jJsT~f z<!9&=XSo>-3)PNB_R=CQCpTkFCPUS!c+#0(y@<E!7{<<Lo`rT*?(1**HCL;u(=pCu zI%0az2sOU3T{p6wt~9&ZL<?=AS__?oZA|)GEt+IKv{3bFrcKW%FJa>L($A}ERcA3{ z25Sv^VYEzSP&SxDz>J!?xp8&8T1RMqgZUU#-n9{<<fSFmo7h(^>*=5h7uf}7Th*b+ z{+GF4T`RK7TCe(*)7+k8PE&U_x9`AWNwbBW0V%76ea8AWSn@*)JI*rOme{RrpJ{#V zQ}J!=Tyzaux3R}rSHkLG8~X#Zi(1*%PBPQfV{PsBkbbAMS5<3gSHvf(f_8TG@KC0e z&&4j$a1^2BT_t1Mp*W%^yP`b`c8C)q%&+Z7%A$U)8j@UBUFu*Tx1RH=tsU(tsq2uA zu~STT8M;(LIY6)A3ZmWR8DxLByH1lX%T#_RI|mhJbSE@t^VPkb>{)|eLTZE_GCSA8 z)E%aEfRDhyOR#Hn{~Zp6wwojV*5gyu=<Y_Mg&s8L{;kXhrO};-w}jp>?=4j}y1y4x z!#dlIa%MxvyGa+1OVrgxpxaw;rtGcDVf9xkrULYj(PJjot7CWF3$f}-XM2RXQFZHL zS3@^)au@V13)G4(c4qneP(;Jsf3FQoI@lcRH@YuY=epSC%suL}E_N++Y7)BIt;{=B z->&v4I8&{gUETU9sG4=NhnhV~ws*6COma>$L5&ao|FB+_r_I(=k5<BR{;MBYu98X9 z?HN@{>aVirJO6O`s>1Ts3MFUnx0fVhO>pm{c5dkA;qd(Wb#v5)qv)&T<&+%7eQo3l zs$=OlS3T;?yu|ehN>b@a_H8H^r6blc=x3IWSdT;prgYGm$GDXaG=D@!W5eqX6u{DT zqk1ta-@kEvfwG0cXuiGUZ4(8gbm1s_Vx<d5o3eFC(ngHhY?Eq4nUl@T<S26vm&w9| zs}<`=dXyg_*NpONHWL|9p3FueGs;hd;lG&`6|&eapd|8olUygtVK#2rQSL*o8|5At z2sCq|{3|&(%J-u{nR!wE5vj}3aW=xg3nNa3h18`wH^(;|5#Xm06vl9!ksyrL;P0IZ znW~ARj>gPL6Yd1ACEN>~E8HJkAUp)D$AsbWC@{x_BMilO2zpQ$TnyHO!r&QTJtz#G z4c3FgV2(fx5l0t+^`J2FoUzn{!eGWy56yy+6VWkYFe9nQgu#epBswSzfw5F{6wFxi zvj>^6+#x&w{D|;K@P6TO;KRa<z*EAEz%#-O^l9M*;8!&x{TD-cT{M<~-w|fZqz91^ zi1pyBR7a_0_Wvkc2>xBT5!gaap&1SiIl|4rLE+|L?vqM0t-+P_I4y*B5E4bB3ph=< z8(1$8g_&ExdVwgoAGkow3;{P4W=gaYo(}FHd<VFj@G@|3;fR7TK!gXt!-V&O#|R$* zPZE9>JXQELupV6YV>lJ82baOD6x>dgUoPr_m2f^-4>Uua1CJPJ#tat-Oh!G@3}({l zk!ElaSdTP=+ko{zGnlER2b#ehz^BCnrVzh)(ak>K*M*0G-w|dCT@;?d_D7FE!@^zA z&?C@bCXpV225$iWBo-b7|0cX297Jv4HyL`yZ_wm{VD7F>9t=(t9t}<t9t+MPbKl#E z5DG+N8n~%2OKdCQMc@v?E5Ulu8FsgT^`JBOFjx;dgPBcw&>8#+c#POR3!WtW1~{Te zpke3|gxf^pGI+l5C*Z}xpM&+tG|Y2sWVNXO0^T6ZC6!x*xukNZa2$BIFefS;h;qaz z1K|nL;FOAE!WF>J3Rec75$3YXv%-ns^TNsCcZD;+mxQ@A^HX8I4}2xerJ3KA9!}dB z!q1}768xty$5vc;$}umygT2B7!6D%>;Bvw<z*U6jgKG$LukD(`tHE`I*YR+YJP|g5 z8w&pmTqL{)+(!6OaA)BI;2y%qz<q_E1#^pL2Kp4Zm|Pa^2(oFWFst7@aD*DHa(eU{ zTm;sm*Wfnb`@}+f@LJ(cU_FuzGi<E%NH&;_l^)3kvnuM5Y;aGo9?1sx2J4Y*aDTS{ zdMF#hP-y6pY%r_JOX3-8$2novjyHv8gZ08xm|p<CEb8}yKNn`z{YH2P_`2|;;9oVP z{vU>5pp9or909t8`2oQ%{34hSBbxa)nEObR-v?I_{sPRs(D_j*5u7ia0d6GBu10g= z+TgZ&g)1y%L+C6T`QRSH4Z+-3jgA(92Mf0bj}&GLI9`~^J4KjJ%UQyMz_$xCrSB4s z6hl}h0+V-zFdrD}gcpK02`>h37hVc}SeVKFsPH=QA>jwWPYOQ-J|Vmt{JdV_ikKaS z@Umze1^-)^Ef=?oW9;7p>lLeDCc8eU79E8USRYgihF0{TT5we`dn8;|R~@Jiss%GU z^g*@Ye767Gdx3@uprH?{1vdn9<c{i%!70Mcz}zQ@>dnD*g<FETl^@mHf*T9B2e%Mr zt!XFBn$m?FfrUO0dWyynFgH=7Lu0^0geQZ!=^oYjT%RC33p`brSvFI6DOev=TRHm4 zRUcFf=A&63R0}QyNAyXx5L!UkPRn4%Kp#{KW~lW+wcuW0elVaJ7NRGGM}bcXj|IOh z%zov6geQUD7G?xKh;qbW3_cc(+rVE6&jVi-X3TyRo)7+AcoEo&jRt5f*b&|Y4hnAp zCkXEZ^X-@sco>|hSGYoW1VWl<>;cyjehi!|d=y+D`~tYC@XO#<!molm2wwnq6aEt1 zTlg!mUJ(m_zd`vkhKa^ius*>S8oz=ki8?oNn=Z_mgtrL?!1IOqwA7=+u!}jFhF(Go z<^)H*g0>1uJ>1+u^I#Msy&q77LMnv)qLBf9Qn(iQgfJf%&kHvO>t(jE%W}gnKy-)C z0)FKovrxY;JOuoq@JR4=GU_LCF=G6BL%{Pjs^Nnnw{QUL7sdlk&(ERdcyI+#F9+rq z9jdbp$Ph+2jJm=Z;QGRBdYfxT`m?#^cqT130(TK^1MVx#S};VIu^c7b9Xv(2FPI}8 zbZ0R54&ia&Wx{N2R|-!Buh%PFVPQ4|Zm~qm%fNd5EqE1ppQtOaUUCcd&ES)w&JzBD z@OH31gcfEV0lzKk`@tUxKMwv<IPwI9Z$x+!%vow&$yx#I5l#XJgj2v}gww&?a*XDg zq}7EBz#PV>dQ)(YFw05<VWuv&&_w?qhM2r9MS~rO_QL(ZU4;jLdkGH(_ZJ=q9xTix zol35b>;lgg9u2-jcr19K@C3I1cZ<MQX{GQS@FrmxG5GnBj@}90CCqH%2PLZC1Abii zKJZatJ_%0>ZvvkdW;VS_j=(bW>2=XyKD{G+5PVUXdG?8L3HXXIv+SDiQ{bP3Pk{B( zUAX@WSTEfLp9SlsyWn%+h+ex3;Y|p7?JoFjaAkiqW}kwSguel&3ttD<7XArbPuOMR z!6M9lzWxLSH`#4(BkJsucaCyIZ;{eNG&mmJSGWi~Shxjvq%cRN#|!gh)G5Lpz_WyV zfNvKb0=`Rl7<id5r(3V!4kygN$q?3w2G6SEhZ(Bh2Hq|_56n+xR9^soRG6m~91>m! zeo}ZN_=NCg@bkhvE9+(9$Jzhqq<T8aKKxt4FM!_{J_G(p_$>Gf;d9_`g)e}A5dIka zn=lVN<aZdle+BFj{u#`#)Dddf7V5NUa588`;dpR$;i}+NVb1f+60Q%<6>bHtFWdpl zJ%>5zB!u$ORk$L!mvAE6|NbJ>gvL<eEO6=Jv~|GKM4b;Ieioyn4Z)>HyB2{LiF$kR zJ;Lm;tP<`6R>A|p4`_}=+v**nF$@}y2#*4Dn?rgw2F!0H<aywygzpAFBYZFTwD3ys ztHSq#Ul(Sx{f;nSNG_JffL-HHM1$?Y72&;Ly*L;i?*r?_!C<xxdTlV6Z9q&g8n~yy zdTlV&PlEN@VDNKby*3#95?HSd21j0lpce;2xByNShdu!7!)a^i=XCUNS}?*DJ)9QI zN3cGe7MuXqhtq<Y$NF$uFtfEE-2~@?Cz6w+oe|94K>H6N42?OWQ3kBn{X)Ggc#){{ zfpm{BIyS~CVLp(QFds+{2<L(M9gFVQ2R|arhtq!HCT#x?i_iiZPYJUSoe=H>{tp@5 zB$nj2g&DXHgv*0J7G~hS6vk87xGJ0o{!tiVGJYpV;Akxf7P>a{ARFumHwFiV`55IM ztu#{vt|ZLIXrgdOaGG#$a4lh$_FUm1-~!>1;0R|+&{3A~u4JSk+75$XImyh9A;OF? zcZQ}qW6Y@$WX5=!Fk?JN7)=WvFi|te{=e7yvP|3)Rmb795LStyR$wLE7W{y4XYh96 zZs5nsaD@&X70v;l6s`w;K{y}G2^}=g_TxXoOwqUX;k3}8#~+AB2k^(j?2LRV+!K6N zxG(re;j!S-wZ7BA777VHyB+KZF98RI?*k_YuSEGXDv7|xAyJt1K24ZiG@esMM~{MY zg-?R@0k%+o7OW4j1)l=95;HG?I|!cz_Y^)49t4ii(Mu4<h{iYIX~I8(Zxj9nJYV>C z@M2-hL=Q?h2-XMEW<;}Q2i3vM8hs!wm|3%5)R8q2<FE+Ko2P`CH_r$&YfcL@YhD#* z*1Rsvta(S6S#wc%Ecg@Q8Q?3zcYv>HM*1&?@RMjL@E^htgJaM#F$M?0vBHPJal-6! zl@&e?t}J{4oFx1_SRYOcci8mii26BjBfY{E8f<#?T3_&&;BI2*JFs5g3-uqsdVMeW zXRu!13;q*4TFiTq1-FqiInM-DPB<34To_$MW3@1=r?Ei<+>9;43E-W=tn0gl;h(Wj zm<`u6WIV6w*=b>V#%X(0r)RGV)30}g<G~+?+5W>2J-Z?r^z52&BKRla6!0Iy3`7iE zpxxTwSmC<hGQ#X1R1{`QT3xs`I9a$8+yD9$5EZt1jfL5wwGhUG(P$^kKy(pK1NRh0 zB{KR6Bjt@D!VKIfVU%`bf-oDsspJSeZUkYrXt3npA>1CkP`E4jZsA+ND}{T3*9-Rn zZx-$keo%NQSTEy+U&F!sL|wQ4kBcxG8b^i4f=>xg0CSE2Q)n{ytnhU3hvYiZy#Gv? zdH=OA^Zt8b_8Wc?Mg=qeigHB1Xxezn&><#!tT2<k3OPIKK@DL#T2q*g))8jm$`gj$ zMnmDU;38pmOxg%n2Y2EQGxUH@r*5LbyyVo)c$B7A;IYEYj>*EEz%zuqfaeN#11}I} zb}SJd0=`$6S+GWUC;T_=7hx}WtMGpCL&9uW_6WZSJ}7)1Tq1l4d|dc4_&MRvz%L53 zU3pFTEASiO2xIvzg!e?_8u&xu@4=r5v+?;__$To9!he9dsXE=^v*0gbz6aW<*Hrg_ zeZu@c6c)xdo7mx4gm`FF73TMzWMRHIW(X&NvxWJMCto-Z+(?+)Y&I9>yJB16PT-Eh zUBQFMIY@s55VKP$M8|^03A2tC3$rnqDa^)Xo-oVDox&^=ONG0F?-RZiyjFMsc%$$* z@V1BuvmpFScn)~4@Ivro!pp!%gzp7EExZbRN_ZXkCE*R=bHbazZwhY*Ul5M4&|Mbc zG4SWY$H3nRp8|g;d>U+{PQ~Y<vjX-Bvqu{iMt2e?#zxJcg*K`RqlO#F!bof*qb%Eh zIFtt=TQr!|`NA#0jfC5Qn+taaw-xRN?kwC3+(URExUcXKF!$=GUz5Nig=ew-A1}gP z(3m2;96U>S1$cq*TJREK1-@7K0q`o}ZQz|`#L5reeG?xLj)(da<Rlov-8d#1Y@wbN zW^4FD*^<1e?tL|^^CjxzwQd~ienjQ1b9XTl)m`h{U9p3~>$q8Gj;oaQ?wQyPVAFbt zZ$GQPS`Wk9PN~KU_mj`7<+#K2dy3j;RILpVJE^%F;KmU3GH%v|bE?YyP_3oL-w)Ld z>M7pxly4($hU$--wd=gvyO9pRseZ>DhB|J7@>g%G&6^-DRaYRIDXP(C+}f#oc$=W! z!_7K!LDhNyX6CE84?w(rQN8j2LflTZ+yX;A)tW8tS=QAu%D)xvUuv!f@V>K^+Pl@A zX}w%ly}i|410nuxt2^D!yAv-NDt((96WG^97iheK2ag8{R(hRS7hRxn_cnJZ^QUzv z*rhtSqx$QMXD7KpMN!c>FkYS7=1$AMxE_PlVNt}b)I9f%yxF{eqN&YIftktC?GMiH zQjNE})9mw)p)FLC*O~Y(t?t?G&bYC7L+^P|kW-g?9$1%_Kk=YD)A6yRWX^E#WRF$( zyWN>7KZ7mHlj((*E_>{x>4xR<<l9hm?3D<F<={B8yLP+l29vd->o^o+UU$?pyWI)a zHLrSWx4UC`ZZhePX@Ky>41_Va-I{o>D%|5v3T8mX$*ZVi=YK$r+2gKZz2Z{K_qeN= zFRMrPxEoa(3j5wEc?e6$cOD*ir*4A-3BD&C_2(XUVj1qbYQ$}UP9%<dlim^6TIK9@ zmyht1{+zhs_?;cc6|J-45|BMJ<NAVU#MOcN^ti8)oYUgY!i%YK>+m}zjys7LBNlEn zEQ9zRBk1z?-Dts!A7S=gBaRzpzhK01oHjR(A4O8)I3$iZ{Q~Fx#atE)JFDC;($WF- z>Rxx{3jFf!-^Inf-YxjSYL4azh40PvkGjia+k*;^x*PQm(E9r^@G=fFch1uo=is;k zn}@(`9KTW<aXS%16WUy;A6}22Rsol(w^8S`_JGHvStI^+*bewjj!wGbk)Zn?b@!<} zhbCH^jS+#A_)p<mpuPDsOxKF9s*?7(iz=Um<AMGrXK*ww!!u+8gG`2}Y5a0EZ=bu8 z^}MY%>~kk$SA}Ey+<E3`b#0$J#cZO=?RU?&-f^o9``w+eeZwdF-HouBLDB(ta>s7) zC)l6wWeL7>2wQLnr$AKj4TN98;dH%<?;G++a#bHs;tfvX?&FER{j^&=4M9vXyx)4% ziUaOC)oVd9uHp<R`jHM}aF6*JcH$~c!f(tpb>V<JtLZav5laKO^>f@J=1$zZz);+? z;6x+zFpOepKvQb#IvZDr1T*8-!CNbCkZOGp(dwqg9dswB@r*uiXKaOxl?~ke+uP+B zenY;~Q1Ny>4NmZ#x7DG8?(_<$SUzu|v);or<n0*)+rDn<JGfL)yVOU!WW?mt*}gBp zXpB$QdCZ+^#;cx>x%);qUB!tTih>o2W33JwUe1ohTz!6L^ev<pEBHcg_@>gMm1N7u z&-mU|WS4Ir&8#N7eb@2pUGofn9bYfR-n*9U_t7!$Ix;5fUxx)8Z*?owa(!;vzW**0 zTE5|QbtBp3b1}r5=&BQlPTwbceJj<VL+<7QX0&$)yC5##c(wPCI~x;aFW?rajNp6s z(yJ8T>#D-z?&PdnsC3{e+->FKye{v-ad5pIGISuq5c4IK9^;otZ*?^a7CL;wlrPx^ zH@f-CQ2hwGyN?q?y-&^u-{LETbKavYE<Jr4X#Od3A0KP6_ZYW+9pF3SQLjJlZW!Pu z;x03d-<RS(P?Zk5i_A-^|6zB_Fq<SZ)0}|YLRhcXSM5LS&JK@9^e}&z1)1}95(lYo z54#VTE!4Ir-1SlB-+ID50viA|E^${i-&6f~>#k;(xHJ8e;j#HW>t%+wWM7GUx@jh< z<R{(R%%<wpliKocPr7@-R`;XY*5sq^%#gOVjJBSJ&#?K(Q9P@#I5F{<yR6x+r2a8f zK&+1#f81R${%3lz(cFTb?{i4UY9Bgk{c(5OsQO;5ZX?mC{_S!1K&%hy{It7rZ7xX( z`w9~<i1R+u(M;w-mV&M@X{KyL+za)$-Is|C*Qj+*yT_R=)}Mg)wkmhR-LXs}Oa=~_ zJ<(h6=ys=3NKHS1N8;zUx*vB;cs_o@J<-1l{sd=n!~e$KlKLmz9|jyw$gr^U!T;p6 z@_)872saza`3IAg|K5}&UA^>)*`eh9*W3?yOJ04~oooLC+iRMCS+V4=i|#c|Biq<? zAa1;P)`*Fy@#0y*rSq5h&?w!B;|z*k=}sIx-QHvu4HtKL=Z6wriX4pc9=OjrvQ;1+ z6wUybL^+}tu^$(WI?#Adm>pa`glHL^JmWQCK8tynD%A_YrAN!~wc<ljZw4+sTBbSp zYf*0n)>}xxZd>p#rMqu*fS~t~fCf9qeB#mrc8-0*J;2;=gz9_`DK9(<Tvd1~I9Yfe zI74_bxb$e5mEh8&Wj6BtwUHRw3Fd>99y|;#JzM4oxb$q9GvFR#<|Qz@12q2zc(Cw0 z;E}=?!Q+KL22U3L3VbIx!dY2t_Lfou+!K7CaBuKh;bGv7!ehV>36BHs6`lyz$H~B* zRbYLb40sz@?>PZ}7<@*|Kf>|L|A?>;8gC0f3;sa(W$?$suY$i6J`dJYis9&+U_GT6 z{5e=pDF%ND)>DeXSHXHpG59-h8MGPk9;82CmMdui<BZ@`;kw|u!fc!y3O5563AYEg z5#|eWC*eL|eVhzD>ksZD>SMrzgvWtL==sYq#ILF2L}NC%SePG5XA1K{HcxmF_)g*b zz)OW!g6|Vv4_+(01-w!CVemHL$RiNgYh>PYqNF~52K+c!pFaaG0Ur@FC%{h&p8~Vf zK)bJiUlKkCJ}3M-Sf51$GjD+PQ8eJUz?b#>WeD#;_*^Vp1b-vUFRpyL(}QoozY1Rm zv(cjZ?_iIxiF(e3yi|9C!@}I+jJ<qL8^;sI;8T*UPw2@OAr2aRKcGe!+(@__xVbP} zv9`iV;LgIS;2y%Y!F`46f(Hw;fntB2?zaNZBy;`>tKU2dU{=37g<1WU3J(I`Cp-eI zrwhY88y`Jg7(4;2rwfBugY|S_@PlAIT^Rfb_^7zE2OK#i!T|^`37-O=6K0irQ}{LT z1z}dX%ff7AJ{PWm?D$5w7Wfz824Dlv4o0#in45!vBgR+=dipOkrhpU0&>V1@@Ir7c z;U(Z)VNL}u5MB$`=aj>p?ci3Tz7wp^DTg{szCNcMd;r|rjrz|J9f2@FEIbPyCj1h3 zjPQTJ?4{E@3+Z&>kHNPIe+8Z|d=<P{_<Qhj;UB=Og@1}bU~i9({sP`2{1<qqun(no zw{Q@AKsW*XgfLH2WY3=NaDnSd;S@062D$rE0&?IT;i_QnX`xT(sSbf%R2r%Qz9O6g zz9!64{gZG$_z&SCF#8O&+YZdPR4yN&-Acl&1&PA-z-hvb*#7g4h!!|<pDWxETp-*T z%y$x+=?88l%tvqsVb%`z;Av(YxVJDL!TO9Es4oK#6ZMtgQJRteYaq;_5J0CItfv%% zk&?zDQ7;d^N0>uQdX_KDuswK?>gesz?k-{4-6u@Dj|<c85n<XjO8!dsG>El6Zm$Y* zJY8_W=#m^yS8H1r^)|)EDm@qC+qbCMxe%AD(-bfCR2Aw$G}P#N9*!23@U~QW@;tNf z-WSP(nKQSkb9pecR#ngUWLd{Os#CtF28M|y=X=uaACU`t)TVq-vbDV#$A8kSL(QV& zJ%8qVLe`aLDpVheCl{##+;N!Z;QF3)jF~OLjhlfSfU5iBwkQVCljbpy^;dn*O=C3J zV534z{k*zr#iE3oW_HQ+2A(*}eGrA_CqpeO^i=5<gXcJQ)+om9#_p4B%(3MppH4BB z{UL9T&6Xc~Y!vb4vU5?Qv3aElJ-y}R{b*odr9^$0kx(uYqN_2Tkg`@2cot)`yJ&F* zSBz&iae#J=Js503xq?O<R}69_wjJDcx$0ekj`vm=a^<l{0vnky<SP6R(02{)*g?HA zG{&^}JoUTW`FvgncEh?6h#W&`B7v5$az~&%lx`1H0?!NF2D5VmJPhu(z&fbR3GkUT zJHRz(vjRNIYG!~-er5!?=i2nZ7`QVnz=b1I17YY+3GlTTJ8S#~3+_Qr!n4@=_z8KA zvYqjA;*{su)%v&@UiL^lCuRa&-h5d0oY?_(f_(4wyiE3bd6cQ=9EZ65-esy;BTsIG z+sqk(b@(*{-QbNCcp4lNm<C5(0XFb<pe()D%S=51?gZil-hp~-;B%;Zjku0ba>Y&= z0(*fr&@cig5Ee5q3<?&;e_+ZLyLk?^pJY%2Q((w6+^&d)rXW-ehFitD%#|<~W|U$* zCJh^5cA8@S=8s@k_(3Se2DISBkDkTdPpIL?>SJgmYU?<C8;-=LnOxVF5Pkyzi_J3G zd8`nwOJnuTIJj9QoJ_}Bnlp_=G*V%k=31NFQ!FK%L9O=YVz^x^+%#t0w)hG)LsaW! zj)Z}{@ZA({HJOSH!^>#3uNE4GJF3?jd(z_SGuYG3EZm9=YrJwb@uZl)sf;F`JPRAN z3~quN=(E+rCZ6e$XJOyv&5J|e0({iZ4+XedWpOC52hy{lz*$I#=Uaheh{XImt-w53 zc>i82kOJ2~T4@F5L;qvk?}GkS+`A)mt5;cpVNl<RJNGJj1@{-B|0?d6Ab*5=3Y`CG zRgM+l``LUXZtN3q(d}zo6B@cM_?j@jhzfV03;H^-d*dCYb~Qz8PN`R$dQuxQ>&))V ztXeQw`9An*_UH{C`cNE(AG7BU{N9QGD(vT*y(tE(c2TvOd3Kmr)VXG!idHq3y3)+k zIOj_^WQI%{;iSeC?OxcVgX~YIcu{4|c&$GPa_W1kPm$+%%0N2YY&10a28aH94OlRX zZYb3J$ySBUJynNscA=-b&aFRTJb|?+A(eJ&UV`7jwyf1$&Jfknr7)9E<j{~h|E-$A zH%hdvECsDfwTzngt0T=l+18(S$rsH%&0QXDZ)h3MtDH8T%KzsbLT`G%|2ieU;Xin% z*CPidW7~S3v;K+cDZeG8t2<|T%ByWfWql=GI(R;aDY>_cXJA5v9i7r40n|%_<A%K6 zhdSRi`QZ9UI2rtfa2ohqVZO<;qeJs-r+yR0Bi~>zo$9T?9^p1%PMw5$M6Z1+BN{9| z)r9+lQ-z0svxM22=LmDqv4QX%VD3ar&-nOnDZCEcUU(C@tMJ3%UZq0<2O;zqjmN=5 zg^z+q3%>xKD0~h)O_=YdvxF~z*-peG6+_^a!t55T7iNlX7EVK##9#|Y3pK&JgxQPQ zC(O>$<HAMYqrxq~CxzLGdO^4s_!Z%yV7C5rzZm?cFvl)<m3%tFvp2>JsWoHR_o${m z9^=`9&rWxZMK7b1dVMT<83R<uanSrYQ*9oHUPhw2G7i0r_bgRmJZeHW)o46=8Hex| zRZfi_k2dbb3em4jy-^HM+y1`Zs}SvVyfoeu$|!^05mTu2f?0hH2eA1mii+6hD`o<m zPloZU*y%f%92inN`hK4X6V=q<$_Z7}To`fpM8ZC0=smy?sFx@FKYA$TVj2|WsqL3N z8Rn3ZW)nR=Gjb6wm@KS$;#uhpiG=!Fx^*^RztMR)1hpHT7rt?#C-QG7qVqBrMl2SP zzxN7zik2J?Us}+Q`ApwDeE-({nC&#$)pTBj!cALeTOUAn)n?BZ9hOzRIj+f2LkA=t z9$Jf`Wap;h*SQ@(<~IDGp#g1<eM424>`671YC0LcIHg8T_6#rg7%ZC~GeOH}Qzsz% zXQ~e-dlIdy=K5k!O_<Cm_6$m|0B77I7r@j&P<i@cRN9OmcfUzgppH@bY{|Z2&tc2M zr=?|VP#=EcsrXM?p#S^ZDo2~Zcc*)D&3_UAHi7XIM@}3(cGB4C24ULR+eQvn)n<Ac zlsqxhv&$EGh-rn^gVz&e)EQo{lBFR3NJhKQi>+4asOdhav*qFS3|Z_xe-pn=hC9p+ zW;B`a4t%Es_tW*^OVMC<eIv{kL${;wn3i=r3Z`YgFLF^H>ymCdG2lQmd>7>41I^Sd zX>gZExlk)!TY_pmUsYd<`n)r!ikEu2SZA;`9q!neD{dKTyI(C?#@b#+y}b;oV^sRx zo-FKe-s5gm?Mn%2_T8Q|o2%%ms~uEY<<+%aeQ-D4C3bjO#nY_!ysDeWS5DQr2a2c4 zs-k<K_`O$+;r;WnY9;Tl_|y^H;p4@7@TPIHoN|_XZrZo6C_h-<l~Y(yu;yZFx;dg` z?s8AW6=};<{~0N>8!=-uS$c6+@Qq5_0wz#tIk0e}(mGT$o$p}~m6q9sH;ys-=BY$I zm(7ke-Z;wPrfVu|D6A~U&Fxx_;qE!BJi*A<RE@rQltXyr&Eq?&M&CRbu$b7{+A&vW z-W=C^(2nJ3Md_OdA5(w7d0eJO^v#10g&S`kt7wheTZG(4XM(+PF?gJ~kC6?p2O4ha z{x?%qS9{6_?t{8pdix2gIg}Din03F;PD>o35eq5MLrqxisbDrxi&lHK)x647b?Gja zxg1=km?FJM*a=%;T24@^^BPZ5kj;YWG5KIJ%6C=s)_BspYh(4bvBR)dQQ^m|uU&i- zSYg`K;fC43T!`>m@PIGJr80Zvm4*(7exb?tFfNU#yi8qR<GI_cjve+r>0#~qT<to? zdn+ncvKBo$L%p@u(=~55{aO(X{X;1I4E>6mLcc;nf5TXUPxV{pNzx6RxkksN94FJ5 zYqcvz`6_DNI!}6%_V<jo&cV`Xtj=gNZ&UWE_t)ug{K4BYRdu~*mHC$1zrNIN&|<=| zPa3rww01yVO4+A=TCeSvSDvnwF+0LAv$QT8)+=(&&1cb!RBWIYC{JTEM?I}Pt#Po0 zYlEjCr8&%avIfDOXy@1Mssm1A_um;pFH&|G>YC47RdQ{Er<TvdT^}sN_djm1(-pd; zRZCvq>8b5fLm%<%{-=#?iEp>3BqdUT(UOKS7WrD*sGcPw#JqkYqebEM8FII@Q4Jx? zrJtf&lQHbXD;aK<HnthUux9XcJ=N({ev~76PHiL6V6AR0%mUa}xH7o2a3Z*ea58w1 za4LADa82-d;VdwRGU+ip!n1^Pz_**I%G6-5_%6|4F<U0w1iV7H2+Y@Dnr{W(B-|Fv zM-$cCgE??d?gBn2+#OsZ+!uUYcp#gS=R_C+=Ch2Jhl5`iW&`++@Obb=;Yr|6gr|c! zKu^1Kz}JKqfPWHZbM}WYT1x%M(p%=}rUQA*hoT=Em4p+(iNeg9G~r6%TEZN=%oVNy zE)Y%uHx*6;v(2FU%#IGiXoMq1HxUY;(OZ}e*8t%b;9<h8!DED(?Cki^Q6}|t;lbeB zghzwt3$sVPSeU88Ry3YN&Wj<e7LBFg4Z>@|TZFfOcMAUtyjyq|_<%5<cTWgE20kWy z6#T64F>vW?z%$@?_)1sW=eQ`$TK9=ChBb{V!hC*yD_j<=_g!+LS*EvL0yE3>wo71U zncj8@%-U25b&y>V)}};ZF4>Iky9A9IV7>1WI329_T>^6ufunY`%xa_eT>=+^TZwuj zu-<kF>dnC%v!Z!s*{#Cuz#J5ydI#|E800^NP7ub52CItxFbeen;2EMm4LnzPCU}AH zZ156c_POsBo)2Cl%q+fNcm;T?@D}(V{dfw`n6G<8V;A_K@Z;bT;itjJg<k+aCwvCX zksL<mCGcy)9H@Ll_+9XO!WY07$q`ui5W;s9&>ci8YWytBa`2}xyN@nt(o8&9e>??O z09U5EH)=OYn0C{Jp=Hz-X7#Qo%(4<G6oG|>J3!JQ7M5;gwCA`*_g4bLzv%W#VEje5 zR|2pvJVwm3U~(D`?b4m;!d1W=ccpq3cz%>4x<D-!jXY>97v@;;YGF3Xdaor|ZV%om z>K(zmh1mui5bg%%uo*pL89F9B2>h(@5bz5wq!SGdSJl6cZ&vc_8=jBd<`H%A0=nVt zRQCJqXs4<9@1vvbsMjEx$5izXpn54?6@LI#mpTCv$701@#BHY<d{KAN-=Z{6rC-9W zu9|fTJ@l8=j!T|oOk_HJ3Gd7IAw4Rp@1bHnTs_)Buk)cNWIm~yeTcsHwd(8d#wOf% zP$^HXfRdS{N_d;6F7k#C43}|pR5otbrH-o4<(s?a^RI==TZK6)oa1Cz=Yr~$%btA^ z7I3{8T^8Wx%VH_=mcCB&TO4}k?AG4sne)RPy4josh@LsWFQaEpH}DS4+J&C^C@Q)< zUqo-ysc1UAA=$3GA-JoscH*^}tAWwm=8zs<oA1HR^PQ>6e(YJ&H3Gqx)fB(cPLu5l zf&&l0qSY=Cr2Tt?{h{RAVg~pOwI2$w^XhIA;6u^VFTj^^XKbK8Zn2|P_nC2x)wcRU zzpD3%=V1@K1Qy05@KRj(KN|J>qX<rH`PB2xKkZzp8v7D5)Zx!O*Vo+nW%ZJbFFa4W zBU$jiw5!Dc@>!jTI5ied1M{_r>TGhE*yLPr7hygndkXU@*-y9?c!+QZFf)U8Sra(7 z0bDZls;9k$3DSGML#dpve#6Z=?^T_?_sle3QO|u3@v2`XT=!(AG8s#+Qal0$)E%Qp zG#oYjx+gtzE7bVHP<qig|If=E4|#oUcSno)OV{zrdC0AYn&Q6|Lt+LWJC*APymBsA zSwEn7f3N;phC$JBKcE_HP;;Ra;MR;M;XeBy@hWbSuZoQ(bWU_!$v%VUrLA6@fVva- z(Gz!Lnlks8kI5_4)0EAcC8K}z_^ik@G_K}mIK&Zwn=fkyq`$|PdLnkH5bQ|Ys1Qk1 zG##(jv&Yl?F8usGzEl@ZqHeG(qi*!lH_sZF&~L3D(OSfG=Hh<y_|nUeqvK0f3Ib<G zUtyaN^~W<*pG@tr>j%1ETK~e$ak=xVLN(TeIh??Y3^8LltJjMCgF%X&hhJB0GChyw z$f-N_Ww0m0_8i;Hw1m;vSdK4Y3wO?2au@KqWw8_N(SupuHPE!Y6FNb~R~;t2vmT>e z!_Ttm@=amQirtDIBeph-nz0vv7AO5ez{v&2a1S<Tz(#A1!vK$=zWv4HRR103!~8MF znx|nbJcT??=SzIJk1F@8r&>ims?7Z+d%FqRnf-LpD4U@=|LUpGR4e_Um7p4;Yvr|* zzxDtoL9K#z^*3g=*`p#KOo)XZcdpP!?fBJGU>2(jzj~@$!5H-ioHU!Oa=&?!YQ-?j z-OU9sjACXa<KNtz1iOhGr-lv_o&&mwf*SstC$;=}s;@C&Pp^MAH=m&C=4$J2o+ah^ zC^mO$%@pm_K$uJHs+#=n`Im{o-QPWFk(1Qu{x~$Eji6@@Fe?myVl$t`Z&Wqw5RApv zxk=#`_!FCZlLDXlvGs0J;Nveg?<R%Y=;)xE6!uy;f+Kd=O)6FB$f%nXmeG+#Hz^!L zgku-qP^iPnAD#{iU~V>Apv;;OjqC?XF8$&8(B<L$I?K5BKYq{szjxjn2PPY+;$OVw zOM1DSKg^OtZl~lQk5QJ)bsU!&LisHoJaOoR36qBpE}lGjLdhMm&Z%;dKM~i`CjM3y z1op#l@uj8o4VquCO5dO#B(qT9dY+8F2roZU$z)#*7vIX+lp`aIxSP1FFs)RMazq~x z#iofC!q7+;W*3b$lj<z}^@OW{3x%tJn+d0YTMO3&cNDGzF8xBomVF4-C6ZJ0*BVw6 zTnnjz28N;5UtEOs7Z))8qF-D9i~-k0&^!bEC>g0jrw$48<>yIZ_Eq&PRhVHw&ruzY zxX_!AenFuCz91TO=&~?9`&^hkif@EN;OoMCxcn+y70kwh9wY-@!hAyOS*OS*`c)O` zg`D%km?hH?m>%e9r(k-Zr=5bC9reWwv!h|jtQt;R4@PrOWH?)`ot4#)Os9)=zOp)i zJ7%K%mFcjT*)<EdwIy4#oQo#LWh1p6bVaMFbG4nB){#`zt_}<rDOCr`*K4ZJ>o}Qa zGgT(rNye~LgKQ_=<^}_8)NrU+7%jwPlX7ZHwiCjNf&I`nJE*Rs63VM@pk!UhT3^>m zGpDNby3nbhy7D$e&El<_+RB?tov!QLG|>bj!WA%){Mwj=3`}-uRwbdjZz*DDvgcRB zP&v(ll}C?26}j;k<!B5ZqZ}DRzmiX!8~sWSP2t(uLf<@VqPOvI3Kp6`vR!vVaPwJ> z=OTx1(5>vqn`sSF+4Y0T<}E6&Y68YjVZ<^vu1UOD_J7*%>+p}eeAaw#yt=oZ^O^e3 z>VyK-%`V$dZM~RqsH9STXR~Epcd4R#6J}b!+p2CM@@1!5aW7Uov4U<^Cq7C@ww{Yo zS3SNo>x~$7t`I37Qjz--(7AW1#D)+Z_1C)zmCDzdoSpdhm6KnXn^&)1PC;EIr|9I= zFHo172Gh+*$+3pcHx)-rM;SDE#KbK0jjkdgN-wJ>=<iO>$Ed{U<Zzdp8@Y27fkR?f zKuJaJ{2MjEdfN>yJ#dF}(9p@bO9gv5<sv0$TVQ${OyAt6`5xt6`ZOomJ&X2f*cwLr zG}ay%u-!cv8ZM%+J$DfsFo&IKKxFQV44vazf}6vRipyQkhJNg8P;lp+fg!xgTHH_4 zUHBE)%MJ59L6e418hRo~Sagy%38Md92!?+n44D4WK+As%k|@T12r4eW3l+rnpGJ_} z{uiO^@$W#G9RD8p8tZ=r>4;8JG2-DAaG2Ao09><vu_jD~_Mwt(Yy{xxs`6Ow?Y z{|@+Q`7a~JG5*F3y`P7>*#43Db^Fht_3-#Vpp*U_aIAkIY<Ur2Z+;7y_CE$s4S!2S zF5-U_fw{x~sH5)d?Ub9yLv7~xtKxUIpX2JY{Ie09nf^`4i5dR)VPm@gcLZdbKOIq= z>i-6wO!40ebxdAr52M~eufuKU5CRhN9c6aMX2YcK7}1F3^i1E01wdD<TZM0R%BOw= zr+w!hW{6@r2;qC390*PwIm+<8OAf|PQJrsfszqArBuIj9roRT_fc_w-X1e^Fe`d7u z;J@K-jtFti(VtL?dl8PeLZYz?8)88G9+PH`5PNujKPI8Te&{|p=?`eZ31iBUKd9Ls znn_cMQR^Y=p&0emtxkpde^Rx+$(h(yLO!_QZ>c+UiJ|`>J^ZcB^Uz5NjYbgt?afv2 zu2!gVKux$SRAC@z*!p|vFSL1~Z4CCUCL`G}#K`;mYN1hxOZfc#&FfHW9OiO2{~)c? zG{lWG{Uf!|EX0>$|8$c>7Da|NO6~9Cq*&J+^+q43o^{4i-o9w5?^kvDI`hqnYJXoR zJFPs-?hJg_9?rzZAe#c$nFdDeR|svCU9m4%%GJ-Q6JUx3ek^2=W8+k_eok_;?`h>n z7SBqt4<o??zmTiwtPA|M9xByBkHEn|IUU5r&@rT~2uY!aYI{GYqV<`jj`ed=<32%H z0@chjaG`GKf}^hXb1K9&q+%_tSP=TzrONkr>SnA)J_mBNlWjs9Q4RumT4)=3h&uV& zc)QTKSXJELsSx4jo`J?%v0La-nrNnlo*`~_7AVp}pU^!wgaIM$!yRa$b%unvlT@Ik z$*+kcLSeerN(-YxpHiod7RH1wGX>h2OoDMCZetkeL?L2K2$f~LyJ~ZjLU&T@7V`>> z7l$nR+CvM|LvPT9J|?Tj?9e*oIu<#85C7(czGJY5n6n|w53zrTsb0*rg`sxLmJ#OX z5SE6x&1hhh`5<n~Lrv-Q7<2e(NGn5!>D&|@qqU)9)S9M+4WZS@(!g{rYz`e{#AoZ| z+!i`Xk8ab#_Rv#^S74qN9t^#MAO<2@*kM?+)E5JsJ~-p4#Xu(otC&X*bP^lzq=LX= zZtv}O{emDk+<-qZaFN9#TG&3ksjz9*h3)BqrG@Py#+`-jmw`@ljxKB;MGG5uxC?w1 z2e)xJRFL66OAV(8i4h9^!K97NR-FeqHEOUX1-&|?-Vm3s1jFVa1kI0NZHGChrCK!z zP0wkl#WkcWR_r6luDC{Lz^+*C<`~zQ?8Hu2ufpgME<B5CMx&uvo>&xDMCMsh*Pv6L zpJH6Wj^^EPu|gIyF4#%uVukf^HrUx@6*4LoBPeE1$J_~1mGlWNJsqu6IZd@1>@+ji zsD*=_mev(Vy*SwUmx=H7L!5@zM_#peh*OZg1;H}cS@f8rH&t;oj<Psra{^N4^C*|* z1}(o&dAuq!)Tx2FJoSg7Z}y_C`VVzRSkJrFGeezf*3*vqaHvxrUA|w2I&IAws`)Ud zpBbk%4|6iGX!eC+P9N(HuSy(_;9RrS$l*@D^_s0V4|k@T*(z>?)7dPe299uY&DLt= z2q!tr0%~6Juz;F9jI8q>b!voDLl<K6x`&0B%7fI8uwxx}smzg1jZEgLndC52%^r1; zRJ!Av`8*QPOm$ckZfC+7S>x5rkxp_P%evXrVOckO<n&g%M&kVXJY|h?QgcS39GLrE zOwV1gpXo&+n+II1!Oh`v=0W;((Dg8!n@l-P^%><<ugOjD&7-dR9I<Q?5A}}FG(XVh zUV%S#_)?PjXN=l9%IVONQ+7?iO-EWI!kK*-(tyoOm<ZXZ-wr<kbjCBi^lq%p;LNAV zaZI1_HY?^D%AHi+XlH@xRZom|BIUoO?qUa;dd-KqISvC98JN~R#;Juonlr{3T#;XD zFnMV-bQ*IdrTH5jZ;TwhHpVH7Wuj1e-{h7VO?BCNUl*;UowiCG>(n%RtM+4^D%JIi z-~?SDSqzQZ?9p(H{Rddg^p`9g>ohbmD12g^^Nu-G-9O%G5zpPN&9ZLB`hJwM%r|1y z*W;Z9@zt4j|FLtSUS}nKGPBkE2~K-6S-mvDNw@ZU)b|sdn(^GV(Tve0vnMhs<FA0K zJ<(|!;l8A1J+028Nital&3x+&Tv|+-)llS@DYJ1i8(2(2?iQB0g!+Zn0+>&NTzdfE zLHzshwv}0tIn`b}K9`2sl$afK<vB<>V5#pXI+c;Qag#7B%cI_z<ZM9Eo;uk{z2!mr z^p~3n_!QnBGt0nx)9^54??O&&4k+Y1UF#9_#)w5i=&32@=H>VpmXXTrfhsh4Hdn?u zOMNjJuQ%B$T<lb`F8WpNVka+4dvj5H^9qZe_U4kC-dus4*aEPh1+(xLwY=D=7{}+a zS=FO6)+k)19xrxM(zGiFwJX`$g~zlD*;QBp4(VLOalR#g7CT!_>ph>^I@MX&crdf> zIp;Ar&MOW7m{EprcNv`jDmqP2E;2YA3z@y9Zj?`Z)!=DPgM^w){ma^gODsP|&9gCT z_cW)VhHj_oy6E=Zc(cyn<I2o&@o{w-awgg$*L0^&wUKn8zBczfCb-mQMlvCvK`=67 zRJZ9)MJ!$(HysJ*SF5KxkJr%YnyAy2r$A*?VLnCW6_C+zs4+8~dgctZc?ODns(OBg zQy9lSz1bvoUJ`CSbGE3!OefQN(yIz*qEY)SMitL=8kXUlaPt_8cyu_d{Y!3je5O;U zZhL5ivIf>D)o{CNgFF6-8ta*2dXdE)w<2c2Ho8uA7^f=Fa+2~sVr|^RjEXwfp&66) z(GkcKQLq`R12>tdtBPkiiI|_WYL-(r(h(-(eH>owTp8&UJZrM+UNaf5`a1hNw}uaa z54392zg4^FQI2&zsla!WGE7sWD?f(?e=)o9v!=6#YEw#07@e;nAif&<X}N@|x~Fb+ z?xNCXJ9W)`)n~TTFv1;mgFP7pC#5t9U5>!HV6TdQD|A)}Q}7)frtH5}yZ(k$2wpI6 znTsgV@1E2mlwrGB<~IBoou?xd{#q7`**NMmCyZ`!C_3ThKXay6gsNO9VDvcQD@mN= z)UDzCfMR1A-7S@LYp~+~;6?oZgR#FfHE2y-N=f+#uw{t)dR+{TjNKXMEqV3{=V9+Z zed8|~`;1dJ)yyr~_^C5}d1MgMqIB$!Z;PeleO@Gc=@?%<GV+Gk05WO>FD_LrU9dfw zjD+O12zg<m{o}Qd%;7Oy=`62kb9k|@ZI<DeY+RpEz@vc|SA3bet|Jr395=%?lZ>q3 zwT8?#3)cZMN274@;Iz_Huf8O6(g3b9tQQ<K#Km&~Og%itZTR7T>8V$_tmieNhPY|4 znH=R`+2=`(vThsGqCAf+PI{Dc*ml>9@~7mCD90fc%&aKSC)bMdNTi5a8_f9MN1;ws zqlBCt<(fz;vu>0}lXIi|0XZ+qn~-W|ew4WZm03T^Uz7PU8kZNTX%<F#D7j&j<B*yW zlT#pY&4*w%j`9O!RvTPnQ6@P2%G91Lj7nn65N-qJ_aK_-3|=7I2dpQnKz$IH-(qNH z2>5>Ck&OS=|Ha#The=U<ec#iwv%3>|mSJ~+CFhL9CFdZ5AXx=PKm`RQXAv0?R8$Oz z+6E*GiW$QiFkn^;sF*MS0_x8MDkA3h^Q}3H+|T>Z@44UWdgp@ePn|klU0q#WU0r>u zjs?aOvEKLs*cqj8tyI@EST7?5`aBt<6j)W{Rg;t7kW9a%Qv=r53~>W^mvJL_kFg5% zOUIOdI|AQXgi7Wo<L<Cp3MDiM*1Nv=EV$H&Wei-7JEC;lx3aNr1buIjT#xYj#;Svj zjcdVO(h6{EsmXChDKL$G#wZ2mU&bf}P@)<Wl0KI=biSD45l=GKjWEMl2fN6)2JDW7 zz7Bku$+h@x#u*q9DlSdWQKF6Ez*xm~hp|d)y>SotZsT6?1IDToj~e%fpE4c>Z!;bV zZ+Dh79PAtd&fo+d3p;}o_<VS;?VvjGmGKn#dt;5YIolKTXT$%Pd@h_#vFc<lhBZ1P zUI>>nzD)O@GejX`DG@a-;%c~o@ojKZ<27)x@tv@S5tQgXa5v)z;a<jD;M2vlA^PdV zSt*|@*5cD)BF?u6>Q~0#go|ASFO(dv4Lf@iSZ$88H-S~FoxKUHX5$vqSCfEmFSl=J z*x8$)<1UTKRjJd?$b^U?1e}oxd@B5^DUF8TGS+3%sFN~u9=ywVBD}|VD*UCfF2{Gq z^WmS2^;kZd;dJN<0vhX5qSwIc&x)7BdS?^g3|BN>1y?t|6Lu5v(b)`ZR-W{A3ECJx z19vih8SY`c9q#L#PqD);0s}2#4}7Ze7x0<JU&Ch`e-EE;d=Q>wd>Ec#d<4G8_$aKm zOl9tO_<C`QlU4hFvjuYDmB!Sm&^lxG32ijiz5axl=LCfodiFSe$(S}LGxr{yGVmuR zSBrVTSas`LIIV>Al>E^mRMCDlt_S~R+yu_b$sAY}EoQ7|QW;}ax^l*y;L65bVfla8 zvDB)z6!Q?{Bw2jg0&3gc<a;8NyIv+&^XVqvBd-Cw$@j1_dZy{rgWY_4<a+YD`S!3f z?dIFV%AA{T54VHeeEWRLzZ-#tmQZilO}IyCFnpECN5FT8$)#@5^~dqu#tGyP80#|W zU0M3&;irt%Ja02r^ZZKM0<{RdYpi?PO|oZaoxx`&SFs-wle#i-#8}t(Ph(1$?-3at zm1xvhC7Nek4c6CBrIT(zpsoVc4ppee#yXo8#;SmAjj6O5_gU!c%uX`74xmvDrK9>J z8}fW9@Edy^Utmlttp$Iuq(q527FwhTJ;?d#i%BWFIrGTF$X7|OBk|jC9J@L5$ffg? z<SJ)=+m7RxjHUCDSQSg{|L4a7ygC|7=@+q1ML){Blyi-xlQ2d#<E%;-m0umnjh(Y9 zSZC~<Rl!`XkXH1|PZQAd{v-wHm2yjjPBGT?8)~eQ9AT^i7;Rhw9%oz+))H$<NA+f! zaZ7lPaa;Hj<8E+zu?6}P(15mfR?WZ0co@7!OsyFMZ!{hU-)lS`-eP<K{J8N%_!;Br z@QcQ?;ny>qb}wr?EMf@}9~fT_e`>rG)`uu%Vi~NreDN)?*3J{(1|K%Q1OD514eXp! zp>sFvoKnH}!iCQH6oD-SoL4IN5x54|M2S8IJEv6eR@gbEf}e+5nvNbM&M6i0_hILh z3jPFkPO0EMuyaZU{|9zXso?L_{yVQ!1P;Q^D;4|`e2yI;<k6xT$6)7_3LSlEc223_ z8nAOp1<QzQq3LVF!qvvz;Tw!KFX0wAt+O0KV3kG4_GyFhM0m5YhBzNIUIIU6d<DGC z_!`(br6Nsz_<q;qx56J8uY^B0UZ=%}_gml*BEB)!NcSP*C*dQ;Ps8$vtxP`$hk4YA zWt<r`ehtnuehV&V{0^+qD(UZn^=&V|8s+~ffd&?_7jA0&6<lomGu+YmDBQ#NFZdMW zf8b%pVH$@sjHB=vV;?@xSXMC;o%1PjR7haDMKpn(7c1ngVdupP?f@?_o$j!{1L$lt zNx^xvf;ErrW|M2e!X3uLU=77eU-K0<8>fd8c+dixqWPHdIC!h^1@QC6)8SW*H9uKP zhbqy<@J{1v;a$dh@7rU%7XH#$^Ah+PNc+#un+W`55qHB{&QEd;Nc?RqlbQ%mCCML! z<Hj0EN*O;3mp9%9S25N*U@c==*JxN#>3lBRpQaYrLqxH$Ol>+Ce-C#v*6?^gW4$L1 zF+KthH~tGAWvmGfV~rE=1;(1}Fjbr;7v%}ewg?$5%s1A{<fX>d;HAbj;cJa$Z+WY+ zUNYAh>m_reaWQ<aaR<1>xD%Xy#sYl^ylC7He%*Kgyu)}f{DJXM_*3K4;4h5F!QUBQ z03R`)2<z#lVxJ7>W;h*MNFZqum&1j|SHqQz^&(oscqLrVcr)C{_(8a{xR!fbhx8p^ ztlm*yWA%=P8SCjf$~m7xNsrgD7Qq8BG})LaOcgQ-)ra+ASBbWRofj*(8+@I~`@qhL z74m+tb7BP#fY+MNX|Qu*g?yCSf9J)Dz!>;pQyL4G7@rTnF0Rd+47|hmMEDcqzVH{u z{o(J8^_V_vd?Eb1@k}_xyJuR7>a{CDKztKi&RCDp%ElXD=X?sCyW!?0zaQ>k{2biN z_yu@?@k{V<<5%HP#@ji5XsiX^BH{w$k6>A=C_{VT*~SOp`NoIfD~yl8&dC(|f5Xnn z6s*rqYfUE(-({@t!_Kc%ZOXqU0q0nX9qPf(u@o$m<!!b@3)nf9Lf#g3j-}uZ@J`c_ z#n&gsC&FJC4}!loJ{y)fi%v{a34U_UrwA-0kWD{3ziy@*o-pQN7b<JaofN8ItZsN! zW4e%`+QtoFS<NV&MsNo)9YZdANFTAqs`<T*)9P{ew}5)hLyXn&9d29)9%bAF9&6kJ zzQDK@Jk_`hECVhbtQ&lVnA?XQS?C&LWnzVMK1BrY453>sLcQD7#>&K<#=0%<F|GkW zWK7|Owi<K1(96aR;Wv%d>wVAoMEGOllhps;ZGn@CIAA;!c21+n+;I30lb;29v?w~8 z@o=v3BsgiTo~}NTNoNjR(RdzQ-FP8fSDZ%aasmx4VkzwWL2)5f5<Mh`b@qLXYrq4H zi3$xfZVaDcd;&bixFvj^u}Wg1ac4L^-2%M{%r#bHvcPyCyu?@~ah37e@b$(z`<snt zz$=X}hSwRZYk!yV74ZETPP<iAN}WkvO+=|PsTJ^Zw!=#Jb>q9>oyMEtUB>sqrT(KH zfPa*nN}!tmt8qU3m$6DWE5-Gfl5Uk;?kRC|*!hE^Jfm<8$zeS_oIfa771sHKf|Zc- z2L<agIe$=ab=diXf|b7W2L(5Soj)j8&M!iP>;P@x(~Q;5k2LN9pJO}_c7CGRc_cj9 z<hmR)jn9MU8jpvs7IWX~)?IGg9uDBNB2*Ea(<rzbyxx>_t2n1o$OpmBX%wsjJD*YT zXxRCTg3p1s*}i&!y<&VJ?0iO{GX;Ln<kQste{KOik-j#b5C34SigVQXO86h+YvF9J ziB4b*oG`u<E^E9Au3-EmT-A6hT-!0_{|teK7V!ey%=k69weeeUN8_DvcjFJ>lZ?NI zhZz3?k1+lfc0QxXs2)yJCFlN(z_Xq6DFV3!=37JzzSKAYUvA7MbgQ^&X6Mz$+V@Ul z?R$^0_I<#ZP3U<swa<rNHBKw=mIcbdJB@X#$P7U{6vBIqE5KhG>v{2=v6||ijCB_r zHP&75w{b1l`H3P;HA<;`_5TT|=9lM)V%5wl#vS1r#@*po;^vvNZ*QDL-qpAae4;U% zP(Nd3?o{JC@R`Q-)c%jQKtm#&L#URSB69wqV4D7nKPZ?J$@qhURVvOO6kHy5{-9u$ zit`5r>%h(*6s%Hl{-9u$it`7RCQy@ra|i`1cg`OatPDMy&l$t5;g^lohRc*g@(%F3 z#+~2~jMZlRM_kO~9X@D04F1LVG&uc-1x69zd#u|*4M?u>1X#94N@yZnU_2SFXgn3J zZafRFYdjZjY^<kW3*$@Rwi!-`78B@f5!b>!jjxCM8n1u{8s7?^YP=pk(|99%w(<S& z`NogKlZ>B&XBfW-&vVYFIJ371EVPJs;LD9agqIobg>Nw458q<^6|9BlRYL!PHyD2l zZ#Guj@SyP__%Y+3sDGiY7B~t&Z|r&8qsAKZdCRx}-f3J8-ep_`c0QxXM0MEtjDqXJ z&Sw;?=?czg6x<S)I=-Hm{A8U^=+ozp0|H|(57!J0(poJPTeVdpanJ{@*Gqu`OS z^BDz?hMmtScr5IEM!^$c=Q9dsd?}rA8bv^pH@g>Rig7yZoJJv^1)pN_Iq*<p%>o-? zd<i_-I1P_8z7)RD_%e8!@ltq>W6J+(0+(3CweVu&>)|VnHJWvu@y+lGV~uP%pHbYO z5iXze83n6Jc0Qxv80>sT!D^DXYF}7w$=lBP6wRM@eqRx=cK*azJMT5t&IgRO^HDL4 zfjTLFAIITx8Mzvza$+^9{3;*EHI4O6I8@&P+3*R*O0=DE9PVjMa}gR~te(%Q#?@fw z>xqNafhS5%>r@O+H|`G4HSPm1aL%Vt>PKLyMGSy%Fdho8G(HvHXgnOg*Z2&0i}7gq zabq=B&ls!mdDU2r&s)Ze)c)_Zz-2`2GF}SrF}@o9()dRBJL3TU$#^w<)Oa2IxA7)8 z!gWwdsIwY3z7I}`(?mQ-pu9zFfvXs+<*H?@maBoWIxJ0%pM#5ypNBgbzXW$PRwLHi z_*1yQ@#k=Qhz0f#7;d}|9%cL;Jl6Oye1WkVs9DBQc)oESe5r9Eywtcdyu!E^d|QUo zp*jTCSVTj3qp@13dyO^kyu`R2yv<k**DJ=Fcm9sCMz=pQ9s+-EtOn|U@l5#J@?3vi zn?(eEw1~^$UyYZ+e;F@_wMLfo)du7m-vU<>cg*w&Y8dNz-`Kb&+|sx<+|IZ@#}9R} zfNqt(#@*pT#y#QFj8B3`8V`ogG1eV1$#^6@(^!x7xyEP1SBvQ=sJ&SZr%MAjS%mKO zyTn}pe)k{8j~IuMKWVIlo-@vYUp7`cZy2jv_O3C78T!bW_M>g+a|=`<V!v@U_#0z2 zCWnk0z=s_NYwE{q2iILx;0LQOOcs?qduwcCb&T51dm`2;#w@<|&&TBU>}PET1wCJ2 zvn*J_Cj8(-!TuLw1H3vxs~3?r4;HftfA>hR^F^eop!Q2h`v)`Fgg<>Wc=08qoq~dw zk**BRWfT7BvEY%HV*|qb9}6O{us!rxFihJ&9}70HWy;&nub^ER^n8^~lVF85?Sg%5 z<U_9bHFT;3i(ezS<C$Qmf^~x0ucI_En4wK!@B*9g&KH8h?WBA7#b7L3W-&gz-KCWE z2AeU#P;Hh3>)C|wdNnxw20HD6o^K*u7_87H73|AwTD?W6I9ROB@ZdddmIk%oX2-|h z3}(K~L3Zp2UexxHcY?wlY~Oe%7`r3(GTCqZPV68S{*~WFd(XSU#CM5(@bh5nyRq3= zQU=BE5q|uHV2QSWwg`5<7i(1aH!f1?kK4oj5>yG*mTs9K6FF<|jMZ=Sz+66^s)pE4 z>iS<Fb#0rQ{LL#e6F;xo8B2wCU*T3_D68)<rRhtrLhu4<QYhbQ(<~@>pG||HBb(&h zRSb#v8C#u2EB^Vka`s1?F{W@1;&P_a%@`gJ{%jYoW6LivInhlFwbea0WG05{0pO|0 zDxDarZ)E>YJyhp|$%GmrWa^=7F^(-bq6ZHXLr+#*Bv<QjvAIw}FRJmv|2Z*Ky%OdQ z4%NnE(v_PSddB~c6GK@G<cVNxr+A<Lb7JU_F7XXvCee1ircmoTHftYkeEhV~4Vh`7 z+ihCtXErUgC^Iee>qs!BN4#FRC?~i+%2JN2dc^bpEpWF0OmW*_@G{m@y`|)j9`R4( zIrZre9nKCuJ0;#O>Rg<Kv!4&D4v4q#E)50_h}ZOn2Ga(_Yk4z*8wbSeumH{z1L6(S zKd=|89scObH#~->DUWs5@1QvS-_?Hkcc75=W!SaA?~C9Pzdn7Q`MxY<F7`F&VxF&W z#TWVO*=er-1U;oW{>|vj_LmSl%a^s{OkeB%&+rHEce-DV*lE5N)eg=c7%$)YVWhi4 zeiam74*9afY02a}I!JysV)%ZULX<o8E<|~e+~pzk{L_Ma2gWCde~JcG2F1^=cP3eg z`p=^t^EIu48J1Hy3M-`R8<j7+kC1<Juzpbdlu9}1Hi!@YMrzj(5g)3jZYcgWbMyws zd$;(B9pfXo4RFk+9&P;0yW#w}W}s%cFuq?r<|E`q@l%3DgX7J;{{&kG$LnGx|Iy%h z(~6r&#J^BGM&iGch(A%B6JHTj9}+L}MhESN#4oKY`<3gxPqmannVB;uGHK)yv_kQ> z+1vYE*^0!s2D^vE=X)c9kwfDRy|uyRL*rT!bj#5A(eTk|aPP2qJFjZVfno6pEX5HF zJT2bL>s^vQEuQqkM{|Q~PmgzI644u{$EOk7Wq5pwx2@#<;qi%{cV0>5GvbrN-Xp=4 zBjXo(<APsC#z!V)KH-hdR_T=M7>qhAeq#8a+~Cf$;*DA7KX~`7c)OZTC6ObQk12;L z9kq*}Gg~JMR(YeO@u>Jh57&P8j*ho4>(r096!p2YO2^>H==k-l#B{}&cu!iN?PKCY z3*I3iueqlQ`x&GBjuV0wXUALAY)M3JBTrTGDc;1&&PAhaz@f^jKto-w2o|3mf1hX1 zh;!oYnWnYkocMqmcd}F7m3lU}r;Ay3nbh5%y4t5>Zi#npyjm((YZ8P*_x)e5SK-!W z{O^|vKWk?E&*Xn=cpjuy#486gFO6>q#?|qv1`iI%%?>_qUJxtUusFV@e_9{<OD)ko z%0iR9^wZbHQY-UZZr4)F^3_zaQfqQeW7Oz{el=C#g&CGd508S<?-H>+mk#N|YM_SS zOB@%=<g|N_+MWrx7qxec^HBQGI0b)ZthDwStF!kX<LdB1V?DioF>VR}X50>zF@P>q ze>mT*LP0>Cx+04>1FmL#4qV50EZoR=8r<Ai^|X!g0=Sd$LRhmZbg;#6U*pT+LB{LU z6P0Cvls3R4jW@yP7(WV+H+~$RZ2TlV)A$8=p7E>jLSqfFTyDGzUS_N}k^oNYz<UVD zN<e%7zRUP4_<rM~@FT`q6sHUTq_5$S=ZsH)UpCgT#~a3asd(2|-|jv#?yQlB&n?iG zi2cU>;BSlvz=w?WQBNQJbznWC|1>@gcE;hz$H8ueL-+z%AN{3233e+S!W#8(D;&xa zNkbj_pf4qT9c*fRG2G7hD%h=Lh|UdgFO%yn<YePDu)f<X9c*kuXNwspEu!R{(KxIM z>x{<XdhiTq9ZsMD0cSN1H-<~)Lttk$j(h~H@AFFZ0@xXi!;@fVG!9RPozXZv2X;o| z@I2TVjl=2^Iiqnny@Y_X8YgfA?5xJ&HSjh&m|m4%F;-=K(^!@9J>zHKkBwi0cN@O} zA25C&K4|<g{EM?h=U{sY{9zH_!T%Wl0_W5C$Y^&eTx2{0u4b&;ua5C$a3kX@;O53x z!t&^$bTqKg$#}U&B6?V0BN3+<m%zh}pM%dZ)|rhl-U**)yc?cq{53q?_y>5d@y~GD zSnuwaiPPjLPT*>b@L{==QBI3s&0H7Ph25%#a0A#`nZu3XyG=*8-vh?Y;YW?z!A}`; z%Z0WX>wP_~wS;v5-9m2~YmiTqXC+?@e{8%I-fgTqLUa73a}E5h@pbTz#w+1pjn~3| z8E=4{!Fh`EzmI^X+9{zeusUbr$KmqE@4{7#KY?o*?}z2<MEc*uO^px1#l}Cw9gL5_ z-Hr83=;JKW+4)Zb11v&TWW$W(@EOK37IT*9=<As<-sBD7$;QR-Ok+J0<{9^b7aE@o zYqGI2Jv2>VnFTZ{>;~hrVdp9irHQa}6$fiF&<4|yQJ6f;C?QP-ddOI9zt&fgTy6i; z#;f2LjAi?!6*SUP+DzbWi;%(BF5}1Gy~bPNuZ*9Ezc>B>{@M5d{JXL2w?gy}l>RSp zj<H??d}D03_!4D-e~2hDR$E@pI0Dx(R$DHwPD-=@Zed&zZfh(%EqRcVPAj;laW}ZH zaSwQ?WA6VG35>Fc{_uImvb&mOd=5Orcs%UP*g1fv{Vz26Y}i?`Bfl7SZsXvE@Cwse z3Tq~%GN-0|v$I6c&pafYdpKAR3FjUTt^se=4sb14zJ|ngV0m;E*MqgVxLD7ToyN`K zUB<29J;rU}FOAck34CLLli|O_^y#8-R_?znm$8y3ke4x5cTa0!l-k=@G}Z|??{Fw6 z9rd|O&F7tWIOIyFi?c*0puS!&Qz{GhF;-vCxq&N3rGd|t9M-^vGiisVKh5OiFEq=z zA*`j@Wzk*?Uu)bIzR|e1+W*@upbp_0<3aF7V-4)xYkUs8#aNGE=Ms(s%!HpYxgM`C z8tY-R-S`?<uO-UR?eK?USpuykp!IhYu?5~|tjDY7Q%bIW+>gc|z`q)Q1pj6HIh;j# zOMed>Gu{W6F+Kp7GuD$fUD*N$3Dh+H5!P$D64F!a1mh!cE8~CQ_QpB1o|*(Lef0-V zG?ragKVuCt4>oQLpPu1#s3`$?W!KIv;B$>z!4r(zz*CI%G@E7I5x&@1PqszI-QX*X zWgzCv>Pi1(c!kL|Dt)VFqUyls63|p{u{w}<8f%rNdyFrDA2OZ+ml$6JJ9~TfT>v|K zdst6SXKxQ*2|IIpcs2Z??Yn6VfzK>(FTCIQe%RUDvx983|B#$lC!V106-~@#59P)( zayFr)v2Lxh#$|(at!Rzl?Iq=MgK8_oWrKg9k~2P!znWl#w)Qu1jnK|u6P`IV7_>gW ze6Z^q1^}7|1>d@;bG7LoJgm){AnQ96KRqiL_Fa57Lq6LHdd*8Je;;Sr&SAmgABgQU zHW;&sWWM<!J|_I#oS^@~_yCrfyZs=loq}%<GT2Z)sBkD=n}N}ehvN0K&umXK8k~<L zyuF7TY|NM0txm4=_gN2fHgqVS3YY77^Bz{BJMXUiRQS)^g2<2YdQHdm#4MHvPw9^W zb3b+8Rbt&T!O%?ZyHB%&JxiDr-z&KI$9VmmnFC~t?mP|U3|h-4o2=mR_hbKaII==k z>sFc7U_&MKKZtFQBtD>(bgNATq2RAwu_|eeO0guG7WNCz(VrE4Ip)7ZlmS^{#PI`i z!w}^dG+4V%wSpzl_MpiS<p&Bya`zJF)_r}6By%Fy6Pe4NdJgAARuPIW=TG=S9Wd*3 z;o~_pW9GI*eaEbvQ4)V8jm-LJW!!;gAl2e`Qi(>i3}j4qcYG0lNc(I4CcZ-xmnQja z{J6OIMa71~dJ;z3{{|-CP!98O;zl}Ncn8UaM}L4UXVlx$tcW1D$5mkBOEMkJ?R}wA zQ*)Pll1t5Bgm!Kp-Mx`e_!3giJySVJG(nQeJ?kOqpU$7$QNoZvH<<lttU>xcCD;0X zBxN1}BhhwcIf>M2)s>X4wU?Tq+@!8Wkd^8qom7}RCp(qoZ%#^H=yFrd(Tt|lV8v1z z=3sD7kH=K($ps|m4jkJm4Ee1{F81sqFycQIRQ)VgA-PE9wqw0w{nvu-h|+4XW1mSR zk1WblS^NRM%{H}L`A=~ZlQ+GUhEqq$RaWW(IFeFFJ3A%2`kYi9baGRz$yGE}iG0RV zo6unaIr*}Sw_Acz8M!`X1>N72@;K7LmWRJ_FZDYKg+t+gg1w)`nziV|9vl3hT9Jx> zgfs9DS5-Fr>c}%3@joOD|FH5L_4@_gKabT;tHk{ywK=Nq_mlpSMLLAP!^xlLZ=tWL zwEhw8R^&!#{Uf>@mHZXt%>PYX#n%FS{vQkZTdiQM4pZLK4mApD{TrxRu!fxb6<kcM z!kLq%hr0Mh-izqfDY#z=RCa*|1zO_6ui}+(_$CFKQtDTAfu;qIDW;lJYhExasJS~< zF|UvE+QiA)73>ZA?2ffaH`8HTxFhv0P|w~kc7c-$p3~X1cG`UkZdXh@mv;XG^{f5% zE-;{Apc3um)CLu3imu<)1%?$|q@=sK!0>|G{|$^RxR^8XdnhIy8dFfL<a)Z~#un%~ z?)P$m^9stTxO=<6_<|R7pgzuT&IJVnlw5xom{`zImu{d_n_QqbO@D~@KIu#?P&dUN z>H;$h^icDMd#b#13pAk0LUU=&WSn2nPdknAG+}dL!7tJ~$5RbiQgDu9#(J6vxwPO@ z?R1`}&g-%Q^(_4Hp1i+aU(j7=G|ipsjRoBh`7>PLmIBScWT`sNHMFuoGXng%u7KAR zXtc1dKhK5M7O3Cv&v$`!1<Msky8vsBogGx(8*3U)MuL8OV-39Pf|+|`C-#`2Y+fEA z#hl1K^b_hR)bMw!Ze?or-s5VvW2@PF*OM95>_7I#YI~;#)xU^U=<6!-zT+zLK51D+ z-j}J!%art2y2DtDOfND1TZ%|r!4*s;|5BOzrw8dTVzox8o+sn(4B`dzDa2%1Pq&`d zBGdfI#FfYj^V&(4CznZi?UfW42zg!yaoB&9Q_SnAqKo)DIK{k9;;8>m@DEuIf0G*& z?Tb~dyOlEV)Z++E;J>%>NwEA#^5m6BU%&E;f-_L%u|9WStfBX1ux?+hWokdi^1hYM zUjA3TKiI!7*2H@zD7!yauIvoX&#UDw++kvCEDGB0k5%{f2dD3k)xw$Fy#29O;f|5u zf&H<Q!)?6akNvSB-lAZ@fmro$aX6TAAl4+@F&x}+Al4c2CkJBvNx8w7vATFq8t^3_ z0UHLhzl^o2Gl<-J^VF7S2IGsa)#=Pvu1wH1D|qwE*s16JipV>qKb`$dM6@y3P@PI| z);a%5^>A$>4-Uz}o*JwsKl3L!%<&1=aaQpai%_|dJ>qJILrwJ(oqEQdYO}jamVOo6 znG=2~5)5pZsQ!Pkx{MpCZ=&^JYL)an7+W6suZQ8~v9sjcpJU@9B@Z2qb#9oxLFdE; z)USoEgDx&V-MgjBzG!h{k8{vZFU~T8*RQpTk5@?j)R!n->Seo_w?O?g##K5vuc4;W z!TCEl?y-UQ^_hTsp}N~xFH{d0>%pZOs>e)a_$lL>@HXSx@GHjk;5UsM!S5M2fj>5G z3hyp;rlfb&0~XN|{?@o1{G)L<_z&YAum)(9p+0cwg4cRsD`WCg;c~|6AXPUW0oOGi zNyk6b&;ny&H)_u%P^tEi9OmsZ)W=vQp%z*4O7Jk_8t@s$I{PukdgVONxGk*ur+quX z8n{U-pqKC27SS8NQcU-qsE}&0SeN`JV_h0OWh5_v-Jm@zD~>x&-T;1FOuZ?DpE-_S zH0ET|q1P>-v)N&+gg!B@27h5(1OD1r*Y5{oT{6wc)4{sIx@q&taS@y_RyyU4>%i(G z=a-@U8xzpYs~uEaZt-jQMEC@gYe=G(nCqfT;|AD)TCiJ{1#STkHyx#Op_rmlDNZ|% z)i0Nv0t;Q@2G|KG(Zv>_JLgK{^6-tuDxuqrtHW!Jb-mR|Q=%&N`;1jW4;wd!^$}Y- zs?^UKr#lgN!2*3?^`JF^qYUXGEOwW`SVi}>aeep)<A(5IW0mOd#wWmf`B6IR-sTvq zGWrp&zan_|$_%i>9bq@X4tIgw06W|bb_48iPuLBx!~J15zzz?D-3l%6aQGx0j2fy- z;KtNp#`!}-O|F68&<G2#PiVBUihY8yDx>=IN~i{Wk+IJB5@Qwh^<t{J4tBG#4z|)* zCA!X7$GS`0jve?Hy5Ayn;75#Ad!IDcB~Uj}2dE3bSaN&)cvc+Si`6Z7r5zp|WE1`r zvz3;-=++6YYl-xYV7E561kGBpVQp@0?hW47W>`?Yn9W_ml;Zfo@S);hOlx**7d+4! z>7d}B*6}%fS)bE}(8}NyZEguFwB@z=wV-EPUYj2e&Tq?Wb9DyUCI%~zgs-lfvC(;} zZ9L`O5$q;9{C-{cmRzkJqNzc%c8KcM3&ynJ&3Q7i@YjQbh3(??c&Fc_xI-rdI|$~C zq3v9i72MJ#?|;4lYo+$??XefQC1a4YhLZ5+(k3^}tklle{^jcm3y0{l1Mjz2Yjey5 z=Sq}$zwIeuB=@GwW{!kjv<spCX@YZ^+c(l*8!tRMV}djE|Fa3sY5(<;8WWr!O4jwr z+n*I?iDIq8j%&*Q)81xP#@^;7v$y&1|FsPJp_B6D4fXA73o8cue~hR8HMe2$_3~M* z+qQK6i^Crk1l@j$S4%ITj(H2YcPG)D>KC5EA8)7H6-uo>F^n&q#pd5Zg`ZKS4Byfw zoIOsO(d<n5*%J8KpJYmVK5=eP;WMR!FBvvDktIlTbs@qH(mYSYS-r#>0}p366ILNp z;oPah75Wn$!(WCFoWWHzqHlRowPBI0R-Y0R(>Il@;?*F^S?rwE{sl0u?=-k)k`CAO zX&qn|f3inyMiTAIv1{QFbvjxxji~2r6^3HniO6|&G8l<%_JRdJ$1`3ta(1Xn`7wPm z$aznkOlVE<oL%C)*mshDCf56SHfi}0zgRC<$s;5mN>(OeFF8$Tm(&O8tYix~q8S&V z>|`fpA-N0Abz>dTWG!N2$$ca{As)(WNK7Pm+80VszAi#ZJ@!0$|D+en(^r#7?n?Do zk}vZol)RNcTDROIrc54b^~#NS`RtR@+2-atzty2sOO$hc?<*yrDh%cyju(xbO(3^M zMmco>yW;SuEjtyaevo!!Zz6%B)csOx<1HspC8fqVx2LCatC4z5ffKzCiK&zNR)N0W z0ya%jdBLH>@rn&TB~!VldS9VXoO(tIr+X^84k;CH?g$s?nCcz0_$6Mk%3x(-oRf7; z9hUY?PmjHBp>WIKykD>cJ2klamw0h_ix+JBC0@Jg1|oAmSjpd<$U6QOO1nUX6AIT2 zyd&`uX?<LcL|fNj<7!Z}jn$wCTG7tA$fJ5X7DoH3%OBG~dbFSNhzB9AWb_oV7kgjw zfj9CuoESY}Y$!Td9En{f`A~5Vwwmw==|^L=^!LmwbJ)aUU4q?5;uTJ-!8u3AC@ZN@ zR9<q5Vi#s}jMy}Gj7@g=j`=9Xrivpmb`Hg6NF^G(3jNqT9mtQ3mi~NQ%M@w%|25vG zXegq1<8G*C-feOs`qo*Yxa789<DI<RZbXMe9fB6Ua|{2Q#;Vi}cgA`s*zjBY+F()J zL_x{M-{WV5|C<!#M?2`TE2m;f#lPYQV&3(^KRJmx;cf-;I#Dl&am7$CFS!1iyjnSb z@;*BtJ9utiVJ#eg9L!DB506Y{Tu<P<Bbs0!HBTMmjLY`^!FAC@sjm-AI-iRsDh6ve z=Qj*DpC0_#BVMVbS}gH&cFs2x<jG#JH!o2ot-_;)D@)P;+rm{vf#ym}UD3i#*Cv{+ zem=vdD=04>D-#ro<Z6{O*TQLOBzBp|#yNS$cNG^Q94PrL^;yCi2D9PPx3~aV&YeU$ z{H`=I9-lu@8qx76)7V`t^=RaKHqqrAjN#FP#Lyza#alqq)JRFB{Rd$D3*{uwlMaoY zR_sdPbZa=;z6S9^eu@Km{$KnJ`x>>(@}HI=OvIO&S+?))6<=>px&A&K)V~>d%->GB z3<qk-u$*>Dl1oH#TfeJh>yk*w*Puw+*E+fje7)*i;vYaV-@lI?F7`F-IM3HQLKpdZ z@0shr%wBW+Gmy;oyU4leEMG0$OrOtk*jBdT?{xoD{!a6&auRrf(5iB|qn;*h9Au2h zLD}z*2wO|N(O_%2o`baXA0^2;ei3_ehL52To%)%}ZghET?W3i*7H0cHQTF^bNVbLi zdBJa~M74@Ko#<A*_J(3TiH~NyVaK9D^RkHw$y3R4bjNaH{n%x}u(F9pX|3mkS?0S+ zSmP%le-M8?|9J#7##eFpNNnY|iq;@$$ajWnRE-}Im67p4uNVz8YAGE&mg`A3l<G%J z%=dnWBdMw!H<ok(=R_iw=h#o(rVswH8kzl5k4mkcSD(ZRQ~LB1YwV3AP?XwCo?>mh zMFgs(Mg%SL6BP$;lR{tba*og>wNJbDcaF@Omz^|oRtQ`1mBh46=?N1%)%%cLi&MWS zaJut5(IIu25*XnE9aD#bTk{k3%Cu6pXL@&_-7OTpF?cIKQHLeJf6h-7dw&EC3J5I= zPANz%OixAyuOWIAx~d#+V^vvw{dngv@@O0^jQ7=GXzT)x7VoFB55>lbPZ4`Dt@sol zsJw=gYIWm-#gSMIc8U)b=fq@}5g#G_XzWRfB7Wv_-ITG|FPwJ#EGfm48X=31R(|~0 zb=qN!m}dBPj!=}iFr+fnz(iuQyF{_ODU8HaaU}K#wJkA2D$&^A{7uYLqJB)z^~8K# z#Z+t@e-jJDg`u2adto9G{wXK;s4&s0#p@(n#qakY9pWVZ_@_uM6w}AW3`b&H$*b>9 zIvV>Z=u|FIJMHeifgQ9%Ovm;I>l{-tT^WCfxNPiw@oD1x*jRGo4;L52o+jV^$OL;8 z#?F*{l%DlPp}b4kM3SwvhMcbt+adpZ{(8P%VHo4rxPP*pa$3RL8SE~XsFWN{Qr?M5 zHdJX_kW)S}#Cts$Q9e->yWlzH6P;<;A1$9~?9B=GmQU0#J4EWA$uMW1?ufdnpkjqY z&2WS4pi_lJMQ=fHT7^Wze5Y03liCIB5NfnASYCnZ(?58uLZWsxW#1d%DgWNkCOQE^ zIs<Q5sQ%XA*9wWYHD6J_H@GAs6kbE!ZQh;k22%&L;Wxp+qQnW|CRrs5iW0Lt@7&;U zMRs#XKF96WnmwAj-Nw4z)W9_TCg@)&F(lkG60E6|7#_~f3VyGYs1pul1vM%ssxif) zYh_M@5~!Rw#rr1MR5{U*&^whAEyFFsL3Wiyts3`oc<;KfPR<+J^iG|`^02O>)<F)n z92uNcCDFUyTLcmdRr_1lB`y-Eh`-|1vOu>=L7FQYYP~afxJu%bnq|<!H<p^NQ+W~= zsC6t*9V}3r7iv2-s97~pKK&sj9<A=~S*_1eApL^6D1_R~BTsmB&@t{PjS96HK^_=o zRV{y5Qg@YGYss}T-6ecgLiNf*?Up0Vx#@EW^t36^)d;noOtLvE#6RaTE7C=U+MiJJ zY}LfIiQN92S2#53e`m7XENJ*jqH0OYMu|6b{_FmR210{1-O6PLRl64El{9RTi10<W zb$*MW+c#mqWP6*$)veO{FjhJ^I-RrhbXoZ6mM<MBeM9W}U)&J7p7D&1y6>d}s3XLT zP3fnWxYVNgKVk|>KMf_84y;}#c7qc{>{p<y(+MS2MKpN8Pj6V-N#hE7(-mu|aJjLD z4+7&#u#LF7QM%FrR}Cwa4!G8UO9x!*!H<>>jy5ImlqJ*xE*)`g1(%MvYG|i)#8u-< zr6aB#;L;J-POx6Vl+kYRH^#kTnaWAt50-hHc!(NjnZzk@23$JgIuedj?2?a#^Ngp! zGLMs7HLa5IJh+DOGPs_xy2wq8Z-!eM-v+mXou_%-JY6he72L~s1MEg(IoL+njl{xw zmvkesu<p+>rvEtXMq-ga1*<hvMz_J2h^=m2@h_)C>gXv#mtS_$VqN1qj4Q%!^cA@V z#vhSf?E$|hkK^Zz*@WEaD>_os=T{jD>$mqf)-9bct7IKmPkSlpz<(I4;&{|*$!o!G z#1*as7fEh+fov#BxsEYO;C&$@rvO6Dja2}}#@hWPH#nMr_?@B%<H5#CXsno9s|tL9 zaZOmSw363`XB*dr=NmVIFEwrn%Op<v#jrjLiPIXSyu|_<BwuB$8ml)-DGh-)8>?bI zXna2WnDNE1p4-x22tRMU41U#kIsBIKT6kya`q&Q=*kut9!+VTXp}sVJ9sbeyWB91? zUifcg_qGtpWa23D0^=Od23g6R50@@|T}JnROH-;#L?`3=a1Y~#a9?AYO$;)Yd6ctU zCQ%J-oG&?#EHze>j8$RXz$$XpAvdrJtMPFb%32?*ApvKi3^#$Dg)*!LXSpS$MkX-s z39H+wgAInAg)%$_zT4y%!p=e&xki=TAS*l_e#vyyex&uTqlA_ac*pp1_(S7c;LnWj zfcF}&h7XHr+u4MEH|7T6R>{a!mvfBu2yn*7Kp|XJ@-n=P=^m|}2{?A^U6-LdfV`Q> zRix^m==()J+|gJGY3NGw3UGg8-MV_|kzB<-!niJcuCYpelCw%iN$vj(i)aqJb*+)B z{denH!=2#Lb*;JN$CkBLCRS=+a#<cOUDmo1e3!|UiTjP~z%r_lep9voPg+0+d(OBG z{IYR-_zh!a;$7n|@JGhoVA*9U(H`(YF)f=e%`e7keEu+2<KyKp$|fb9O*R3siq{zj z1KPQ^<i^e*7)BIoZgP$nYGbUXx|4AYSp9qLt26Fb^1$@Oj0Co5wHG7?(odeD&0WC@ z+B^~zq!X(d%zrpd=*1vwVFIt`U4vl@69bqnyq+NA;Xi8=33@JK(;!%}C^3hL(1}Y? zJ=`l8d1+!cgZl3gM78!}q@RusW-d-Ns;k%3(jWJ!`{}cqPOn=g80r<gusBh_(Npyp zByd$YBbU1V$7x`+ZJrT_o@ti(5YT8zA{E}zEaNs^g9D}MOE20yNa-`cJd`-otCu9| zW6JliHqqb{Hpyac@r7igE7~V$%5KghT<l9SMsnGQCsWgdx4V|95KO)-k@r8xwX@q4 zw{G5i#Xny*D0$_w#FX+0=hCA(dEb->y01)BY56dx%`nf6+(`cp^UUPD8MAp`n{f82 zR0D>2-l0-3%rhdmZe^l;hZo5ZD#JLN<A-(BxwB!NFO;(Ld>+<nq?uuz@Pn~nH~Xix z2sxuTJ=jELTv<AbGY`SBQJfPL$c*A>M&`exIOREP_y<HetyfYii7HAVr``E%eEA^_ z`492O^ZQB9-+*G4ug}*JzY3CUzkYk=+po?^<ocD#bJW)}Hs<G}6b~gC$&vY=zff1% z4Yx3oLoqDyCj|H1k*JWaLXsExdb6GDYe004KY%7`wy$qlv;2FJ&-6Qyks1D3q(0r3 z*~BzoZ!L`5XuvBoZWEotQB%<;)qjdjS3b51L$R?GcIjY?#(bi$>O7-)6UR*sMYpeP zL?9k>?>IL6qNj88z2(R={yd|*#Cfrkf=R0qmC_H9FGh7Zu;<qS!~V4#Ez6hnZNwi) z(@vp~-yHu^VsrfnCmZ$EWsCXCC<JWsULqnApQi8E{%WGJDI=4fuYtI5D4|9#5?|@; z*y4yV)L}mjvws$5<+n0&htMk?@${WErBjXPdQuLh)H#Tk4(;>}ny*e2HPDyUc#Vv5 z>TCt-d3sJ4rcP!bzP|M#P?S0?n7TSqv2__GccS+&vO1~q%5Ld6jvSZ8j~~a;XFLwt zG8GM;Vb=yKw|MEGjaFEWpXt3vIvH1>@lo#muS=>R_-A#ZlGiw>w1!vPt+_$BHHlW< zRl!Vxyw%^jCb6)tj7cMj*0~f!Ow~A1I)bx=h(zZf_#2%WbXl9|Sa-f8HW;H0SHcEk z_KMHcm5ary2CLR4DwMf`JSD~`QHEX)hJzQ^CTex=%>Mq2?+`{~H*hH5hF8>y_icD( zp}2H-CGr!xx$0(z2L`p*C7RXMhjN^gwjlY~bEqZ{|IT4Uv6~QNI1*bC%t1A&tCc)b zQ^#SL@8NZc+7+*1@8l7cWTluayOY0(tHf>z4z5cSH5`d9o=9~fHB-~bY_ft2)G8~> z!eo(i<5?&5csOXjK2f)IBWYA~!se+}RQF_kZxj0#mz^|YMkv|PU9vVQO_IZ1=@w$z zr3M98txvQ_>)DC7QXQ#xDvzs;w^9X8N@<)GZ>7@ilhPPyvYn@4+Wx7(5GC8Yz<^W- z9j=p88<dhG3H+C8pJAzAspR-CRbY7PpML`*Q~xL<Jrt7;jY$=&czU|z#%5fJ_Hu#q zQneM++Xcp_UQrhMxKp_xB`23SFjb*VOzAO<|59aca_R)d4DsIMcvDlC=%_<oU}j1- zX812v12H%Chtx18{DkfNlpg#zFdai+Vd@Q?(K(*3?2^<HWnrwhgTT_1=3?N$^eO_& zQa32=@!kUju1~dBV46GE8&g^^8vms_@mo@>b!}$4z{-?vLHw7hfY+qfke_-uFjZ)6 zY9@biV5-2nlwQklV5$Jdgx|)4QFkUz_qqp<-O1gvCmwuyXQFzW)f_o_d6=q_6WI$# zb17C_m};f(OqJYwT$OaJD%oOVX_efklUJ3Tv@ub;g{zYLGF9?poz7SC;DObkCIu$n zQbcq<rGW=i6>e;Lux(?aR-PIFJeVr0@znU>$Bl`Cv$f(uVVQQlDF<gLSf;)94#jjY zmgyi4$7H))rlZOz5_?SYPU2{6pSZJh{Jc4n$A-#u5$DD9A)riGaVpj}7`G`=z49sK z5AUTqi=x3Khxbz5WTA@pgoD+a5)~LAEZKxp@on*7_a>fkn}R>tw9Mfoyq*!AMD-KN zB78Y}RoC1lua}co)-CJx&hV6QaPnP=9^ub&O0K;tvB+a}fz;+itETr+8@!7n%C<gU z)^sjH=SS3Gtj6`LC2P;V{C}Cwc;&oc+U5ic8<bqNnNhsfO*k8GU)Xz@E^o%a>b`I$ z?}wD5*<r6NeZEZ0?6A(T@`KU9zc<l5ye}Mdxi?WcJ)Zn~<+F4em1lAhyb4*m2vx>S zpC0mxvh@6IHI_swzeZ-f16eNlR+mbWqnv-8rJPrpIccgm6MN$^{i7z?a!mh^<MjW? zs##Gb-Ri|-J7h&%5>+eX<nvy}E2jpD`x0GitW!bGRa6J6QQKFzWZp$OpH~%pG&{K9 zzC@Mqj+|gATTC?XypIP$-Qe~65-q$DC4b(Rm>u!vmdx0axY=u6S34h4cfq~>c`Lg< z1A8aSo3X|X=;Do6LG)9_Gr{tp%Oi=Ft-DF?M)ggu>gNqo379~2@P7#2VOfVq5;f|m zf_p<%w5B;x**Nt$!M<qlpGOi+)6bxpYW!DGsb)^(O}P6>r0g#Y*sI%_D)`|ljZ9iS z+JSi|xz?e_3J!t6w-W9#55>GeUVl!c$8Pq_8|<ofkBbrH4RhRcCv_<ANpCtY1O@t& zSKzKdj=K=ORs|a#O|;+}SMcGZi4N&bTn8Jdm2W#|ja^WeLxp-xqWJPomnV}<0=?y( zJa339Q2k@Vp1)Iz@WR{W*v`5YL%q*ZhK8#ghaS`IT}X=gqopw4)Pw6EOH`<!H$)sk zD&-rFY4_|JJo8wh0}HVH_E@4(7xiy&0NHy6N(J53!zsu6eSx0Xp%Y(M<ZjpOx0Y0g zD3DIUJ{R9JIJ+d#y!%#8ps-0^uip^notBoSE1KRDRNO;#{2Px6d$v@fPk0-TNqYAP z-YrSg={iRRKSJ7jj>Vn$97)))_7O>4f3xS;NR#h-(JG~f>houAN$bZGP4aT%W!1lX z`F}YiUBZy`oB5G*>A04hwkz>=R!O7J6XUY~+u`Yw>-Ht)j8AJ6wRHSh1DmDe$xFpF zPx|R?rF3{$qi3ZnUQAY<<-GL!o!h<C?cwL7sSXjMW23R+gC?hNN=IPRZuG2l1hxqg zr6aKI;L;J;j<8G-lxR=b*|}1^bZlqm3fF`iO9!q4%hFh^G}{_$n4z<=-u8RCRWVTF ztuM1`1+16Bfu__4KGpaP_)O#T;B$<p!{d#Yz>|%yf@c|D1J5_sh|WUe4H|z~p#Vj# zB66+^VU4D&HaYi0#^x2d&iEdaSBD=m*4dXB>+GL4ZUnzztdmrWuVeLs--Oc&3?Q&a z5!6STrHt!BxGwyi$s58y88?NG8aIdkHdc}9^Ow@m!SvQH?g7gbKs*@MJEoWtO^5W_ zsK7`fY8j7)8yG(ZH!<D{cNH^EtX|QH#uvkSA(eaq>_%_l%i+^aeiM9_@on(AjwyeQ zs!gznHL#wTN@ydjk9Xp`VL6Ww-wUfpBz^>5Vf+MqtMQxgYU9u0JB|0k_ZaVoA4*%` zD*`3P-@vjQ(*eGRo$W0A6a1RV)zN<2IE&lred8GXiE#qfYmd??fMxh3t_Xi`oUTql zQwkK(2>#9Z1UM4O$Xme)<6dxCV_7a%FdhO|H9iZjZLF?NL*prMGh>-lwsyw399WY{ zJ6gmNxV!Q7@JYruz|O!H{Ttz-CfD~TXJ3o_R@m9s!Yko%rn4Hp(0CoJ_a>e2of?0h zV}W~!xWriFCX0<9g0D5!cd1*A--gwNS3>W=n~gt$-GUUzzl7a_6!5q3Hq+6F$s6J{ z5x)}98?F*k>-U+lT0cF!Bu~NmlqaqVA2hB7|6;6`@DJk?U^VN~Zw~7%SKJCt8n=ei z1r|^fS<zTC1gabNfYrOw&L_f+jr+hYj8B8x8jpnCkTCkA;FC-~7FMrZ=}dy%@UYfr zT|>Z)4->Hk*7%H+^lj-v<7eS%#%jUz_?6BZup1tR--Z{P{2lm8WAy>9Gu{Q?WGoAy z+uisxJO78kT8mJNx5@Y*thZeqOs(I;#=pQ%7^@}J+pTmw?w*&7)e>$u*87)6`J__- ze`s7;_y1=Wr~!X%TnBbz$n2oj&n-3qyT>m*3MJG9d9HC^SYK`>?++Ik4}{epmt3u4 zb>m^M#>~=+P!rkMBF=!_ViU;KT)M?3;B(;4rZWz9i%lRuAMR`NiSR&U4ZodgJRNqf z6w#jrk2CokeSf;p0x}AiX1oxdW2|OZ6K9ptweVtNeH^>eSRco3G?r=7?Z(f-YmMK5 zHyM8j-{+Y7Kbu=dW3@U!6n?^3E#9-nYVlq&ZUApLo&djNJQ4oTcnYk^h)Po{<Y-Et z_zGACEn*q-AJm(r0=E<R#aQ2m{xE(EmPvqg^hqe!cn_R3{t7NImf@OPoC5traCMXG z{%>Sl4lXuM>pM^<3&{MWhq3PMQ;anib(nE4Snn#z&=B|><1=7Q+Linq_#!dA6+I); z#;3xU8Ov^ise??;K<Nwu%PnFg92lPi-(fr!-ef!-e#lrh3MIyRUT7&prKx9u<}HeE zhc&xaycX8nM)5Oh|39(7YedM7P!XTP-x|xFKoeOd{~rF;_$SycNP%1yvTi{N_%GNk zNCDHm&n!p*XTjxoF;hCSnW-$6e@69eYg$Al*eytbT<!S@CRfkaEl7d9DeM-cfYr8l zH669>CmOeb-GUV8s5y5FQovncw;%=F9ZtIiDF|rr*DXi^4}#r-6!37^El2^M4bQRz zEP!P*rnAvRtwqKk!)`$e<eFb~jmbZQ-GUUzD{}kYnvthNl?kjirE2h<#;sttAO$<L zhTVb`a7WlJNCA(4pEmu`@C(LjtX?x#W2IFgl~FZTvQiUY0Dt0E#UL<=z+Q{cXZ^2? z)pBVRUOT8?__OhB_&4LZ@IS_C#IkwCl)lUW62=Q)w@?LgHEtD5eyQ63sus8mu5Elh ztno@Eq)ug9<5h5H<BhOJ5TtW2JlOad_;lk};IoW(z~>sPzc>L-Yv)f1OtA=c7-tzD zfG;-IXM;t?-@y8Gp?wd*D~u1rcNqT(Z!-31i0(613tM7LtD4R@cO)To7+<jnbrRn+ zrjr=jX{>>wUB>Do?lC?Y{?b@|#P5vHg?}>E;$%mSFNXhi%>A!#2>K|avsngf9bs_* zmp5JmS2dP(Vjbf<;l{>y!7Yu|7u3M7(zzGzYJ5N3*I0eTq0T=eO0o|aVG%FDqm5sK z#~FVDPc{A;o@1;wU&GltnEHi_jgP__0Fzwi0oNJ-4c}y(Rwr?#1+w6E#@X;)#tHa- z<2?8gV;S{7X{>(abH-ZC>}BI3_zmNl@Vmx!;E$YtMsio5z~>gB1qAjRt5f-n@nHCn z@#*jpV?AvCG*;g+%qzUkcrF|@z8KaQ49OS3g~pev|5wQZmlILLco|&J_zt*<vHFND zjnzkNXM8u@#rPq(m$B>&PBt!q2N}!c;54z?|ECFzv<TTBoMZe7Jl^;<c(SoRNz62s zS^qrakKske8X0u{97$gW@z<I>M!!N|q*W4Hq#%8p1vK$sjj<LabIu)6(&(6T?g-1a zV2kPWh95WX13zm#9Dd38EO@)ITxL7pj-)dQ{wyO;hb|_t&y*Iz|1n+)Ys6bQy%zq} z_*VFD<CSnW!<W)o4g1FH;C$l^aFMb4f7OijCAp6C&&bYC6L5|m;n(5jrnCocWBe1W zu~HrEDBQzXU9~>OVfqFGjn!2<%{UH^G_C_{g1^!ksjks@3rv8WV@M*@eVS?V`S3hr z=`S>11Yd5v7+z+41$=|?mGCXb*TJidwJz8O*tP%aZf&-RTj2+dSHh1O>)YX0<F)Yf z#<Bo-)mRI3yk-0}ywmtOc$e`D@E+qY)c^a^0$Ts;J7bxF|73g+K5G0E{I~J%aD=bx zD#m}{xN$a*;*_zzmX|k{&0-bf3UDpQy8j6@u!tIPQ)7LIDK>5mJ1>+RtTWur<UQfu z#_D?YH`YQJLyXl8bKWW0SEdZkJ0+}c*jVSEk$@(rIPa9Ox@68fC9H0k^G*p*gq?Rv zcp-eL9pFlMsquC2wZ@uFaHH{B_%>sG?ObD=)_PtWEui(h?lpcF-eRoJ36C4^fuAw{ z8h+7OD;~dY{0qFpSe=^>jAb43sc{1s50;t!e`5m9g(YXEUXOEO3Acd{+YWMp{kw5T zSWD^Y+IN9-jJw0W@o-p!o6@-uE;612S2JEH`_noWxRQuQ#y7&vjc<k97_Wsp8Q%-{ zFn$g0WBd+0!1!Z$nDIaG8OC8ASYyO$|8ohPXA$arOf)WnryF;G=Nii?!2)A-CYBh> z@$*&26XENPXTmodtDmsacqyD-X8}2QzRS1-zTa5S_eYGMg`YHj0e;SS2dqz-D(b`V z8^(GpziV8PCi^4fny`%b(NBj?BCy{g^r-yCcp&UtWRmDm_=w5Jz<(Mqfx~<!)q$76 zG2?sSLSuO&u57#&u4()tTwjYbXlHpKKEWbBfm<2t!PMFKYxpGNU*J=W|AdDcM`)Zz z7|V2Kv~dM^oN-O~LgR+=k2lQ%E#UdavV6GQxIKK0@rm#X<H7K)#(L1KHXaV&X*>qL z$5_vqhm0q|C9rG%<$?HVi?|ei)p#lVp7AyC$Hsb~>^8mwK47c|%D2W3z|KV`rTaMS zTx7ye!Ole{{EW}_&*HO(F2Qp|#Ef5n%NV}|mot6^u5A1oT+{e%xW4iG@Cn9x=(IBa z6mD<48}90u>wkd2i5Bq{+|O7pjt3hbf=@U889vKc52JI9HRIv}<0w4MxDcLWtOw8~ z#?|4)S`}Gmucy(K#&UyvopF8mCgVo%?Zzj-YmHmLn~Yn*_Zhc_A2x0WKWW?%-e#PZ zKV|1flT3_+ogYnDZj+rKP569xm+hd3)E?tm@K?t3VCPa3{e|#PCSL|;^LZz~DvxVg z?bvZlu;i5S{(-Wr|Ilh4i+&Xbi?x{=yr+#H)V|ms82)o^F!N%6K=`|K@FH8j`4`Oh zPY+|ldf@`J)&x&2@aK5X1+CJAW(JG3X%M`Z_8TYjI9Tb=3(5>jRbaix+6(>q*{==e zK^zQR=+_R{A8n3b7W%1h`_UO&(q6p2GLCcXH!UL%cA>;Uz9kLs?x0{1n^%L5Y?6mB zq)DeMsBe{BoGs}vz6_q2m055xb&$qCE2z@v_~j;8AAtoIi;Gu$Ublfav*hYNdDn&0 z-?P7W7k{erzZ?Hcf8j5o@XqG^WfrhLb75Wjo@CdM)BkfBMt%Ooiu7TpmaQ=<3{7{s zP3|gfBH6PtDQzd@<`ZutoYOCIy~JKrlm2re`Z$&=Nlrw0iiR)Iz8TxoA{`=kvD71x zb=pKDH)`XB^^ujSto!@1G{nh4qJLh!hU1CxCS1i|dIzC%6<YZ)i6zRS>rDs{^x%J@ zad1ZeyawLY!Q%dTT^m+Y<ifs0=+}w=-b#J9NGxVo+z=s1DUqeYxBc^)4ecrQrOL1S zs9GDKbq*zO=a08ca(yu67yC;4uP;rw8zOJz%f}L4uY^BWaA`2<l)NsZT*CJ#fi$%^ zUkUR#w}c;%{0`M_4a6!7YN$d=!&|8_r-W9P@?O!&zm8hs1sAMK@Q8w2gV=z)W&H~X zXEzSe&*s01T>BR316QP`l(!HpuT(=tzereH+1I$X6K4KM4;P^&dk5sTi{|RPW;j&; ze`jHk`fp4Ln48}=nEG2hQqp#KUOL=;(zr>Jrpz7}nmA{|)Y0Q-PMJI-G<Ez%qt88i z>daZw$Ay}WpE7A&v-8iMb?*4Hr;lwmcHHb{<7P~4*RoBU(rw`8>hC)vZ$b8q3G>E{ z4hC;7w;~uiGVe5h;*`nf*KmI(OfI>9WL~Obx>zO2`>lSbi@5{!n<?h4KtB!6da88% z#^~zk%JJJSri-FqS9D}upx=qdaX(|qF*MLv*H$Cb`C5%s>5k6?98WZ^hdeDN6Vh>0 z>0lm@nW=QJTBqfv!?1Z~Djo6)@Es<v47;gx$g9D3n_THX;HJ+J(SU%em=4wmc2nu# zrtr%qFNWVV?f~mErS$v2y4S@g!~Zd+fy@|eARh+*Z1Rz?hOgZmFdm;7!wj7wzkG{e zlkqZwT=#`;W9^`uk@>5R>BD8bj38G@Xee7cg|LRN#WH=+@U^%$tgn$`oxQ$5y0yi0 zma?@`gwE1UlY?bJqTy@Fb;cKp?b=T}j^`M&$xM?&N10x1a%K8TV`cg}V=|r2ELg@4 z%C*M9bpYjht+8^gCFmtrt~Cu-+ys8uxH<fUu`;dCozhWr_kwX3_yaK&Ru%A5$CQ6X z0$*4J&)Cf3Whm8ve=vCi_^@$fSQcAKs3jbtYKt}FCC6Bq@Qw96%Qsdgij2F%)iivq zod*%nCrj}VxT*1}us&HzJ{Im^d;#3ecp}`}cp9wFm(rgJ4>7(79&W5B-zej<iwKOh zz-93Gl2<Ou8<@j1mkJB>w4U?%Y{Fkx3LamWr$wuB7a^S(oUYBtU=y40i&cZ8i}GfB z<AW)eA{`Vw%O?C?;~=#-uaP$?=(sqqHhq!Ni}UJd%W*WzzDP1HcmPRwabae~<{uX4 zrNU1Y-n@h-UX7ss5~AKK3<fFKE0{wN>1sAP4|2hl*y<tI2M3qrRS5EKNFH-i)*_IT zvPg?IEt{{{UAMkhTyo(J$)adl_7$?tDgA{{fsXYC&Z7wE4eV$0?_84<SD6QSZ<;mc znrMm?U4XEJQF9NMJyoGd?hvZG>jG%dEhnOaWJi4=&57JVAonue=;0YUN>+cN#*(ZX zaF?W+)kO4MJGPogd2Ty;1Pw_gdO62o9?CcD8hZw%Nb!9j>1b>#(*7MVuK9k<Ly-<W zh?ZoR)kIp)LEA6Pat)2XPo@2v*kyq)TZBvenecr7PxidnmzBaizY01RIge;_-TESP z{N3ox_D2#s%hwZrrmv5#GkiU?r~4NYJIx<PEYnB&lTgm6$BBq`<xeX2Ntvw0zV_(V z<!%*+V){goYm0Sgq%HT=b<$62{z&e2aXi+QBFWvMC$%4AIz+bzStfk&%4FsAMI1lm z%fi6(pF=6^H&*Gng@+@4ZIa9O^+7DhuZv=?KZ3J~`XS^ozdZ+LO{OOZunfp(((pA2 zEaZ<P^PYbv0+s=(i5AO%%vH3$R)%~Hta+huJG6ptS0-zv^>JEDfyn4TpL5evAh)0& z%9l9{OM(0XNAiC|#8My%L<`QJ6JjY4v7cX_qp}i+c2DK21z;tRooov8HN3@2ATg3D z%Kw%FvJyyB0#)+$=`hyQEt@c^M*e7>(23qmqUz+Iuc*G>GSY66f4`FJ@2w-yyuelm zQJ`gh7pa}<>1$1K{+kM%?x}=3<fnAh5iZa%|Eb`cJCgOvXc`EsgXqIhw@~=wp!%w0 z9q+-Q*D5A4oEcoC(Dq=}s^r47zAt-a!fM*Q1E?3Nco3*Wic|*h-{h)jRz@xzZVMGf zg~5s*nAx`mr<>V#pxd`1MMj+4b-%9Az_8o3l0MydQ?fkWmqk-rWkT*~Teud)xE@~R zmdaO$EN{%QbUS3Zt5oIkV8`lYMQ=**&FW-jFBasiVXDAW!J;+H{@4`UwkBDxtUHG{ z-Bnd;Rb#<BYmyC!{e4YxWBzl>&O^wlFwn}z*9BYFCeNs^kxlQY>niaUM})>$tGcv~ zy0p~CAgxyGl5JWymU3}erJ;_iw{kp!>Q1@X6@WLSsw=)?R|bdKwb`s-)w*Q+3RS2; z-n8R()i>GdQ-UAXC9AL`Z(@D2ecLOP$D6}?)ae0%VK0w_OkQqw$?N%4HKt75><-XQ z;opLb*C(qra+hjtro5ZE!e5sO)YDVW+Yr{(3ojqk^0nZF^~slOx?C5!Q=G>MWs)uL z>DsBkPO_UfB&*d_CH9J3C7wX`s_xXaEAr+dUaxTZ;6EFZRm$pvuy=(^?JvYF-wev% znVfo(o6~hrmr!L^-JR5W`W9{6(OpCr3Z{)a%E8&hk5<qf<e-jmwSwh?H}6c2sW3!E zI4DagwRS1RDXFScf?gYwtt*_Ys&l)GbmzNLBSl1BzcJa|dzr}@$#T@54>u<7@@@|n zZc4U3Sr$3oHu6o?cFA4DYkTHmZgaKH8&X~OGdjATy`iC|A8VIASzG|i!E5ZoLH^m4 zY+vsqm6X=uq)~C{X+$@ZUQR?s;0*~C-xiFzE7>sLo&F6ulIAJ3;xfUl$jd&ZVw|t# znnJ^ox118ZcUQ7&;~RDSyPdkU`@7`-re9Xo?QnO_G9*D}ht79%!drsLcPA@mlAGXS z<Mgda?v}fgHNB0&lXoY3CqLp~+0#6Ix9#v?kldWCneQP=oV9}vdrEl=bv`BNwmDfb zoX8H&+?;G&q<(B(XAL!_Hn5xf6YBhJPOxfovZ(S%_AYypo?d55L(h&(GF`U>?`%$1 z8SojB#F<i9Aq97cPQS8OnGqX~2|DW=U1FrPo;W7#<a4<E>97AQz|UmId&t@e*(Iml zle{S}_ZH4S9Qylz_uf}EI5iTj8a(r4vdn+CV04R;wofJBjs7>Ui|*yltq@(~#bn<| zkm~5=l<asld8Ai5p=v=L)3278TCCp`F;`5#2<201p<Yf*#nx|-m@1~9dMTxr>np{2 z<>L2}m@?CEq$&~pcm1wWy)K|Duix_us4ve?-&0FX-J7Vkm(R#A5?9D@o^Cbkmo*lv zJI+t0P?}AlpT5C)dXM8L*Eyvo^R>B1r6%*UWr^Zd%P5uSj7wieWe`-#Cx}Tv^<Kt4 zVx3%jW1UbhV>RIYjMdiYQ6>G_@ae|&;IoXI>-^8PfLaYbmbHT(jPt}?0+rrEW1XnF zb&~7kmKp0E<OX9MSQT43I`Asvy6^_$`tWAh`DbiI;6aOM0zYQl9Nuc&5`NxTFDkDZ z_kiCrR;#encmTZ1co4kDcnJKh@fmuRlYyslI+}>1#$(|>jn9LVR3gnP(65G=3aHCb z?>KH^EVY)#dT-PdO8P3rF2<@-y&O~iH3;;v2wj^q#nfsY;A~@6at#Yfu4{jxv5I|x zm?KfSLrae1tBk3)AsH4)hkRsKeTMb?-sE28NKrfACne*DjkWU=#@g9gsH3BuWm%+^ z4<!G<SaKN_Nv^Z}!dN$pjEN-I4Wd~+VtonAEbmM}73X)0s0k}qQmO;$u_9Ipxt0)a z0Oy-rb;zymjJye4-Q>;Sy2h>G#>O4s7S0l#9Xb<eXA!;NF2=p#UdDZ3bu5*M;jmkf z1Re_yGx-Ggd@=W=PHd8KLwJU<GIWt~JGDP<XptTC%6*wdbcL@r?hY?E?g`66Ne58o zH2f&;3$His2j6Wx2!6nLC@kwE>7NEaB~B9<L13FjjD%k?9u2=~JRN?|Sg+_G8_$7v z8_$E)+0_B&!`~Wnjv1GU$QQxCntTbI{>uWF6Obj6c3uj{jIV+<FJJPTVVSXt*T9vH z*Tb?hl6)g9!y@rL@Cn8b!L5uRf!k*|9eRR5SBrQSKH2zHSk^~M=uKGGN8<P3vy4B6 z&o%xWR{u~sd*CU?``}r|2VhwxN#|>Lk+Vc6@H2tSEaFf27I8u5wsfu$VcMvSYeZP> z!DiFpZVWwWOjPJGW8HpkkrRZfjBiTLLyiK^Sfz_~ZPZnk0k0yyF;**f$XEwEVyuJx zY0NGm%{JD)x~HSYI#{VCdUd#x$#qNDFs=v7>!GtmZ%)8joRei`qO+7>Wx`pU!^%Wo zlPeR>;vBg$;VjN!wT5S!P7U}x;|8#-kCdj`24`>%x8V4pC5qs=u3TSbTo=CHSWl{( zjn&B9VchipA?`h(tE%3$-?esj%HCPKL4bq=2q6%VK<K^qP7sh@rGs<?1>8{-5Rnd( z5@~`o1+1~4fP%d@6f7VpcI*}Pd!D)8h4Y;8-7)@WoN@2n1G0Ya?0wBOEBJ0<Mqr<C z3-Dp#PT)s`Srv~6Uju$xGtz%Jgy%(L3|L=vhyYCi>#GjIta7Kt%slW};Ue&7!mKr4 z3*QOm$|Xi@4fwL~1~6AEQGF9Qi7SgJ6hp`$v!TYXlEECHpgLZN7Eev(-E1jfy?`9d z>}V(ID9i5chEQi=>?P{#E9k}KP-i(9Eb4J4>2MJmfO#S$x1RDh*WiW13<Q@z(F_B@ zB~7K^I?K&wgSQLg;ofuzGps@SrbBQP{D5AG4gvqHN5n!7*jqtP54;uRwBW5EF9r4% zkfR(~=V%uNh>3Smn7ul#Xrg*H_($O?;NOL-vi<)@gzC`XGA3H62~HKR1&#@`pm7-! z%`^e))#Tu2;M!D26~M#dsj*~cO*3I;O&eimO($|3h8XG|qQTH{i4raItu<V@06a#R z9`m$RnrRE3D%>4>GZ|55cIXA+;2>Bp2nRD2^@4CPQ_)r>hcd!TVi=@tTodE4d)1Pf z;kmpgfYM>rJ0GL6zjagF^D&THU0s5RI|*9X!oyN4`6yB!^RY`6)P~U`JylU{81<{y zAi`*+0;nGAt)>@*d--1Ot&ZVo=c`B^=yp&e_*kwE;o&=5xS=le7O38J5rTWwb9JG& zK$WWpX*upafRXpES7+<NouB5ZI`uJ3T$DnWnT!4UK;+Dvr$?5=A_TnxCj0Hd5 z#2qFMH^4CQ4^32d0}KpTSDhPRVE7hXkbsA!6dpWw=@>MVMs{L1*F9x=ii$K0UpZwO z=SMaS|Mz<eb}$Ji<4=xzPr>+cHqsu4Mo*oM;nbuXAYn+iE+7B>)&jm*F&*52dRJ~O zm`6oBh4W(n*INsEY6pEI-CGO#{jYB===Ps}JqE9xHgjyjtl6Vx&r+2RrhTv8T$9#B z6(*J$ytcwu_p4Tqr^QNUHN#B$|MpG;pOd6krKFZsFW&4J!}Gk<AhA)?M)jKL@%a`d zdAB%g!*Q<qwYjO~aU|SX{P%vo{-7%Z_1p%5f%-8CP&>;%YuRD@H=hpaWKB7VT7!Ig zoF=%3IH5f2JBIJMdj-Sy34Hk7^TGYe$?U!A@%yT<fLz;vz~B&iSV>-wKS}=k@HfSG z5pBP})>yFbbvTgdUaH7}oW#V&R9z2m6Wu!%%hN#0O;n}ViGdaPi+TPcIE_(#eokVP z{wOR2FiJn0Q=P%FP{c{da4#PG7=LdHa^1ng;6vaA!No8;Kgd4ljluqC>23(V1KoMS zwg~gwU;<RG4|0k7oFMn2%ntIqd{(dx{>}_?_34ZtyPX)NxA90Cej0uS{K<p%(&t^= z|9096ro-m5R&Xfv>IJ`qkQ-#z5Rv!=29l>Un6R|^6fN<yx+pQ&5YE}bwlI9$3SQ+? zMQfZ2ExFq$`ABal;v8)lNItq8=y!gm`tv8i-iSXr=y0!g^6QV$xYJCXUgKOfdL?3= zQm-nM0{%dQ12BNg0%%ybcEO$qkT1wiN<y#}T=fSR;BR8^7nn&3vbU5R<XC@7kmC)3 z;1oJw`MAp<&}1Zp@Dpm>TBq98i($xq-=^O&2E#sMGfXiC+x|e0tH);2%!gXtD#bm- z_JcORE=%Ktj|UmcG;R7pMl$VZ_0d`<JJgJJ9;CBYnTaZOol`!8JId@%KE}y)zKf4G zVl!2%bx!@T4#@<cYh{{>uX8d(QCivTXNaQR)Sh+D)s?hTkyfe<<??#CvdFKM`(>_C z>Fb?)a8TRP^-hNCOJ^Mkjt^xlR$r`lKEUdbXE!)c`fB*qZOYk)1vv#9o&EMJ>hwk@ z&(}CXC2VrqR+>bwzw#Y~9|6Rr2HuVq;;eTGWd?le+D%TC8tlN^XPE?iAvH%9*u_im zo~m^RlkzM}R~{_aTC5Ija;~yBtJ9mDO7)N7<yLS9)A4Is<@TR~5_<OyBg(a{SFzR< z6yuNm1J(Md{LN10RSTe1kstiUgr)%Q+NsF-(qn*nRR9&s<Ih`a#%8B})?Va2?jNNK z-$Oq$o1rRg_s653I=0!#D&Xo)?IM?RY8ST>=%NO?ct2I>YAjWyZgFbb!&KufPQ}&* z=vQZO|DwG{docuZ)(p#Dhsg@OwIOBdSgqH(+$xY+p0V7Z<ww=JElv*RSWEEe#>M>^ zBjAU<&Bx$!y?z#o*A5@uN_SxQJNmR!>kfciqZ*9i)5E%*M#ow9Zf#VlD#f_i@`x%d zc5>3WE<KBLYj({9I{Ox6t6|v$wXE2wQCnwm+XQBD5Z?t%9i7F<UU>Dd2JQTjq|OyP z6?_#!8}7oH{jFf$Y8Y0P?s6(dxWX-cwq?f?7}%w%$6Zbx%$6*?%gKp91U)9o8m-5H z>`X3Vx7Q}HpmU_LD)ag(l!0pY)xHJboGmO>#}l{;1?gqIOoPQ6VKw6fQ|P#MDj!xe zUZGRR6UxF^H^`a%vaz2@U=`yU-^?$sq6Jrh>u}w)aAl5c)*K6yBiZ%Lsja$fb#mie z_?pp{&LsGkL%kQ|be)0;y3Q@7{$^L7DS8AlGb+)~Kyb}w=0glrk~Zx}waDc6fSs)6 zW|TQ;Xs2koC*-QbB@ET<em*^5pYxddeyfwyZxM7emeQ|!IxJ689>~0@=VuhZfb52? zo_4JYx~6W}TzM>HrhNk)wr!9acT?lHIfbR41XuhDY4Z_*<L3XU7q>YD=sy0j4XKcg zR@P00d;NRh({#wLPxoq{_Csc@5Bizo7a+N@Jfy?rL$^4yD`R<B%h{B5tnb%yeaKbY z7_sJyGG{Kc>ODVmUEQ_aDc@)~jJbh$PX{6n*$u>dIuHk_ud~9HPeE?HN`154sh9H` zSVxeG71>vyYges;N0m9Xlb)v9?r`elbA-zNSUcAUmC2nqJnOHCWEoAFN8{R`X#MT# zt{qO7tBaWa<r5iilv#fJqHw+h^BKC$E1$?l??KqjP}C})$hYO&kkgS~u04KiGhec_ zEBUJNPTcuAM$O;p<W%YpJ=dkb{dDPOF>7hF&#EIkojSgx1kCn1m1|$1VVwfkC9*Ik zq9ixo%5<EjW#8(N^k;e^%Vssz@@_1+Oj2X-c5*6rfKk`#5N&iU<gA%vQHzHqc7;=m z)!w_E%Jy#c;@wWgYP+tOUZhQ*q&%1&ElOlP{tR;Ctt!0Bsa=_$!8++_NGCmQU$qy; zbkf&T!*)3}FjKi?7utu8Fztq8vvzp~<n&qf@YYLY!MlqhnlD%L6r@bvylNL~!@ogh z1n<%jY>W@EtcjMrRqKs}l-(Up)WQF(Q7EfAq#I~xv}GUC(mqvvw^If4cs+I_EFVKJ z9ZT>m`-Jv9H3MPW0qc;NyoHprktrgtflLpd)w(Z3%3RIT@tl@_g?!cXu$IaGhW(;e ztc%a>s-2+7a#;;;qJ{X|7tJ0TKlROSC)uv1enwa-_lCg?jvm_|C-OZwA95yVz3g*| ztoskECigf~T5>^DU@aS}AQHJb`$<--Hb|ks`fN|3Ikl};Qxj2Qd(@?>R%nT%lkRcS zGUrmgE0x#~YQ5%sLt3qOsOTPCseEfmtvya9CwLKRICEg(wu>cQAH<^J(p2Cg^uXov z3ls1s2Rcta<m@h;d;yKM&wBTNJcCyKKbSI$9SJx44~%(BE6bJq@`7_s=s*2HQkY&# zFBx;nc_*P{^BL!Z2)>Idsh9hdiK?QrDLEz2e&syWG0snKZ#Imxr5<lJc&EYl8hqGb z_JlmU+&|>;O9pfMwWt2B%NXsz@3f(D&frfC{@P$}GV&Z^pUYz&8SF79cRl85gC3VL zID`9sJPr2NJkB?`zQNpn?U~_*Bahn|%#NI=-rwM%29NYu&HB4^W=r-4Ju5{9FEyAO ztvxgBG<v*Uz4UkKDk|xp(&<&-GSp8Q{E@+*sNVmSE*JmVP~yfT&pB>9@|ZiFJ+5qU zeS;et+|S^F26Gd$=gze*yZO#OtEVx~V0K|W_2mY$BkQSigR;l$*LwW0!7m#8s=*h6 zM!tV;X#8z3HxPS{#tbfFFwgPy%w!wP4z)M0T;Jek9y9*jDC`;1r%dA2%U@SRojq~S z%m{<W89d4083xZWn0<K9ojbsBPhe-><E;koHh7=G-0SO^=Qb*jpE3A3gZVk&T_bY( zUyfVn{uQiG4d(ZPXW>tSxdg~lPcoQa6rOsP!8{q(Q_nNFwr02d;p(n`4RL#wXQ8FR z9SrVbFh5;9^Fs_CZSXjQxz)-uKO=4k^9){K@T~@O3zlbD8N9_{ej<7IUmrC1VS^tN z*6}}PXq+&Z-&USOrwsns;PVE5Y4EoO|7!4`2ICVger0t<7%y0Fr9}lYdV>5_HkjLT zJ@tHp`R(SZw==k_!95M`cZCuEfmZ}f(UQ?;;BT_QGY#hUTh9!)*?P>KO&+f`SQ)(4 z;GN{Sc*c)PZw<+#1|K!}8G~Oj_zi>KGniXzJvaH8>hTW-$N9bLX(SpPGB{>%hQSpK z=EtkI@P#{NJ#K7pbA$PD3p2fRQgeH(XMuM}c|6EqZjbfU#~3`>;Av`Gvrv_m-1O=h zU19KggEtwx!{FWOA2<=`R#wl669#iDtEc|D!KVy9WAG;ie`fHv2LE6%KjGoN+bkuz zf=(iS#e0j1(haU;a212Od(|^v*We}ww=kHa0-pJ+xeeA6xP8^*VFr&knA=x9Gcygo z-e3+hcxILx%-yS=y7HLu-|7kAod)kS_&$R<Zs9p}%;4t?e#ziB4Sv_)kHB%yp-&7A z4uyE?KO4*;5l=nE;HbfA26M-%XTFlb)&6C5L(5Po&aoBGU@L<;#^R}SN2<qz4Canh zPkoHR6AYea@GOHlN`u8}ZXsOa3c3)kFnEo@#RhLTn7dHDRc{9j=CF^ae%#>a4SqSw zLWplf{<!nh<5LE6yvS4k#^9d}{>@+?x>la~B!fc+$2?~IIRNEZ$TPUM!SxJoYH&+~ zI~d%>;NAxJHJAfkanIw4hQ@S*XB&Kz!M7NEyTNxF%&{}i{ksj`|1Za_gZ~N^2iUw- zi^mOq-r$!F<~W>Z{u6`0F!&pT|1mfL!*6z`TmJO?i04pPYv>|jaYWDN7(RZv2G=yW zz~Dv(H#4|{!CegQ9XEu&1`jrPxWOD!^a3>7;Q0odZr*OF-)ZnVVIBXCh6cwdJr52V z{IJ1~8T^dF&l&ux!EYMOQBTkP&r7jyCdqrr(D>0{4vTtbk__f`;+}fUU=Evl>bVAU z_|#Kxe1#GJ)>j0q_c6Ge!MzOTkf^tWcC^704ZhA`4#0Zm7a6>a%oPy)tuQp!8@$P2 zj@)_<9WwY4gC95exWOk4<{+BqPW+4^d}8ot26I^0vvAqq1dPvm>d6MD8=Pfu6@&9! zcIzJpkv)f+8Qj+3jt2KOxUaz+eD>TKXYh3f&oFpln!2?^sBC<xp|;%M?FR2Mm;=?` z!s!x&pECGqgE^4xnSamVk6m^X;k=>orNQ4C%rS7!A-}<?21g7oYjAmk^9`<32L5}F zHa0Yx8{E#|P6l(}-LB-8;XwwEG<b}`lMSBcG2_n>d(WZU3|?;VDub25TMXW9@IHeN z8~l*L&w}Hg$1fThZy5ZJ!JIv?vk_waJ~#N1!9N<z*#$crhVcs+9Q~K$R@%RURn6e5 z4CWZLoefv;YiKa%B<#wrdKZIx8{F4m&RKZoCu(-fpEcdkm~HT4gO?e++TisDbK=6z zaRap1;6nyKXz)pXpn4WwF!*(Y-!_=@CZ72(4gTKXpAEijFgLn;b~)!l*6}ZEXjCw` zvcdHXZe%d0W9%w!jJq0KXmCG+hZsDf9AAQBne#Xv&oOv`!9@lyG58LHIRWIkv%}!M z2H$&y5&uW72v|*I@Nt7r8q7H*&x11te`4@w26N8IGk@9O1WX>;afy901>vy4T>j~) zXBb?;;9P^N8_ek~&u(*r+ZmkE$q;%P+(#Ylh7a}0hSD^HuQ&KcgBKaR#9+>%d12XX z@IHg@Gx%|r-Rk+2q4BK2FB;6LI6K!ZhvyCc(%^3m{@LK)4dxV{=T0O8{(C}ML!-RG zl?|?HaDl<~4Q^&|D}y;#==s&pW5$1oCxAy7JkH=r2G1~fj=>8IE;5*tlAgyK4899I z(bL#rXdE#3kim}_{J6oK=k(lp-QZIOpHT%pQQSBM>KXmh;ADKLdg`eLmoqriV9uI) z<{KK^!r(RrbMn;Ii-M8Jygvtm{tY&GxWQu$o@g*<T|K*TgBKgT%;0qfZ!F*WU(4GJ zjk^tg*x<(uK4$QVlJUJlhmzyxIs1#rTK>2e&c-w^e>~*E+v3+K0gUMw{`7Jp%mwhb zl<F8v=I=)`Mm71%!NLG<yI&tNMr!!`fQ+F4{+e<HN=ybg-lKqz8vfcM0N#kVUcH9? z9e;OI9UTY$z9!?X#a|gtI-<$sZyXsFl|NoO=Z(I6Nk-)P)3an;Q;y$AJ^3VGSTAtG zNxnC_bG8Gkp!wq|c3uzYEpj##@hi_^bm>_1CwuR7vNY2*InFCB&aGrAGQ5IJZy{vm z<vwh0Kj9z3NGZ!g7Eqlz5)?*6tTMt(`7B|KU+Nv2G|vR9F6vCAd|}iTt2G%8(tV!S z5ch=cqJf;avN4esyp4%WByVG4C9t<IF$X+R?B;=|3D*E~nJnGU2hSI72)<dk8T%GX zL}&+%JB2%d^=VPC%ykW$M7;-?>nZ7IZ!iy7Aol@tl>+%1@cqJrz$L<55cP!cNU*yv z5$VsQ@HQs0V0#-AS(wk#0@55`b?y~BV3x0MM4d(CN8xNRch}Q=4)`D8Trf|MqIxxO zs&I91OmFdnMokFiM58vif^c0hmkZKz12C7KksE`#o{)@Ww76oIC$um!orRGY?gi>l zhcT<Ks56oSgyR_Uac@wEDlJc^2AGz4q&k_F7YNgGkudG9C8H$LE>A`Gc$+W_;BH~2 z+yP<M#{0d?&ROe9L?aulH!{Le)|O{PJrB%fvh?68@N2?MEgqdtb*9!CVW!qOVW!YU z;Wl6{Qlt5HY=8cyfXqhQfmPowGiE_yRwpimr5Uy}T=qn+0_M_7az3~g8TF9v)EA~Z zJS2qbbf>j2-RVe<Ln9YLSJ9wD+zHLCo^)umFddp8%)&TTn8`R>m{pW#CD1ObXpt~e ziz~gUUI)zMQpokd@iii_UTzd-;o2(9q}wIj61-oyBlxgz7w{v({lLeBSruOtX7zhr z_*(GWF2}7I5H3={i-GTkZ-m)I|0v9A_PemITEe+dPehAHyDT3(6`jmBBPLu3E+^a{ zTtS#^LlwQn4;C1@8lo{3Tp)ZsxS{X@aC70M;I_h>!JUPR!M%jHfq94x1GEdw>o~}J zz@vosqx@MDM7S5s^;9%;2s~T(0q~8&4}pt>9|7}(beew@%oEbdPk`45KLy?-d>p(@ z_yl-2I8F=CK{y~9uY$R8g6eOBc|<z-6!=NukHF6ee+_<B_y_Pi!asx02>%8?C+x!u zPT!~lHxq5tze}PKgofV82n`3UH!_0Lz&^Z{7zplwND<BghlMMG(}XL7%M0g%vxTvn z$I27tty;A-BmL_@s4E&Rz#Yh_Z>)aZgi%|pLSgn(cp)Xtuyq?M%(vxeVOGTn!Yr^; zg{y*R3s(o<$a9bAP)!I$!nMJAvm?|Sfc0iaa3k;*G1CIPQ@8_ouW)DZLE(X5?(?Ag zgTapr4+9?)j*o=!tO%pQFAGlqzb-rltgp*K)R`(@P#s(bd`XxMk-jYl>e*l(!A>*P z!0c0!8RKMOMmVIm_(7u<1btl&xB#p-JA&(h^=3zK6L3|r+zMPE+!fqVxI4J1a3Qz{ znaw4BR~tM~*vIx?Z*YVmKMai#4aRbkFy5ZlY+(m{qcF?FO~MGDds|K#06!kz&h5PX zZ4pLyz&c1~vf=kAnU{_6_q1rx4%eU45DU@U!WF@%g_)#hg=>H>2s254C8Ja_0{SK# zFayd%VW`f4@`N68IyfE@Asa$A8LuX$L^WZ)`}2iU!S#gk-m;nqqh?yIgc+X>!j-|@ zgjw<ng{y;kx;p%d>o=0#$Ow-cLSqIs5Htp2t}x!P)<R*X&>~?LIv%x7^Xx;c6Rrf_ zEX=aCL%0!mk1)&AefqK)SZ)U4LDAq_?lIwB;G@E0!6${sgSniN9!~<lA<UX`N_Z;x zL*Y5#^TKn%UkKm8_WzOyWS-MbM{foHDZCiWPcf>m0XxF$z@>#1I74_lI9GT#m`AzO z?jCSm;lp6Apo~-FAqe^g8}Q@c_G0KLSl?y?_2b~dR7W$%tl_drGTIhvoG@S6Q-oPy zd9FLnR0rQA%+AQI!gb)k#rwHws3|m733ml=5FQTZB1@VX3EnBp#%izd81O-1X3ayw z6Ty!QGi#0sPXj-z8EHNf!W*J78~mQ|^<b{nq{qyTPlTBrT(aqHa{g18DZ#H~s<U8n zDJPk=AS9d%E-jn~&d`_5zz~wcsw5iq!BvIX(&^i5V5SqeK-Bw#dFZ^iySj^TGSqts z<6&_fD9y0p;yO?=+knYrG%!5h0^9gpfiduIutAnzxxt39StMrID0w&7FkihJZ0do% z8*JKuw}|-;;N8NV!3Tu9g0WWAy=<Td1fFou5cL5+DSQq1xbQ&m+hkO9#^$sz1A11N zZNNogcF%thX3O}yFxvw^S~9w$kNAj)&>k8*5}z7O>MFwhz_o-2gSm*5W`=^B3XcG{ z7G^<fFU&STUn+y@fZFWdDFbGMrtg%ALtyi%FO>nOf%T;_U^LP0r7~b<!Hskj%nn77 zFbfoq+^2dzSdlBap4}zPY~`tDROic(Ye>mxaIN?u5m3mjhlSym^@MOu@NwbVU@j=7 zWj3YyA{lTK@JCe7cH4#v!Yqtm3Ny>}-7zo|26H_r%wui`0vD9hGGmOh6*a?MD=b_C z%<natsR^!1M!jO;ttm{;cw9f#k=0gXVLU9ZA*DJ?etTj1+f`pS0}XoIQ#2U+QDmeu zJ(wVjYHm#v#sddfx@P!#T`0_?=2}tOr3Wj8nSC3CS%Zp&tHvR07a<?~AQ?p$4~q*# z$;_vt!gT1QF!TN;VW!X<!fZ>pR+M&GEzb!vo4yim2L2u#r=d0wxImQL9sHN@XfTh> zr}`vtY2oSM4B`1;9-B`yH-W1N7l9j*5lWW)7Q!rNTpvnxq(t26A_7v(>Lr{9<^oX~ zss$b_%$SW7W&s>0%<4KrxEpw$aBuJe;Q`>4Wb{N><JN0N`ZGVahz9dsU%diD+2H#{ zoq>Bon1MSkd=>aP;aXs>38e>2-nWEXg5MWz4gOfT1NgihDw#4lv?c?m75sB+sJHLs znX2%%5D!7vc3X(&;a=jSNVQ&!$1b%J58v0b)Y-)_(?b<3f$F^~&d06lH9i`sN=sqp z#9TFfDa>HcE<}5zirkLJ6g7g6Rq7BPzW3&BSOz26s`oM|W~ps>_)gr2QxTv#MYX;| z8(qmqn);ZJBdTCI9#IwNV}W`N58sJ}D*Mh*FW=`2)pR`VTy^wLx_*<2u7FsmMy!B% zHm(j++@=0m5$bEdrTVT6RY{z_1FeFZ542aRZ7V~02<dZtY*Ux`=%>o93gsomk-?vb zREJfe92_1o9!iPh`{8w<)~*Uw@iian-WKrcs!-JKsXm6beVa;NjmH>Oz{fB(fRDW@ z&PT4=!v_)!kEAKTU@R#~U2YOgSI%u=C#7k<2KDRLZ6ZfH)K`^vrq#fe2CcKwDy6PN zp4p9Uw!x}y>u~1yN#K8v3RnmUd;R&@iK7Bm@{y7VD|jR?<inrXg^K=UUWJLrWGdPz z^&tJ%BOPwncKv<$uziR|BOF{Y@c+9b9aPT2w3pSirQ!Pj^)QE$PRqi(@C~n8-<dYo zPEiF-Q);qY-WjfvnCC<9OdUO+R>k*1g8D8wwVLltf_lAaN;Q<9_=>c=qzisD9PUBO zzBD<?Va<xLag+m3TJ|-pr}`{Uu3`5mxwInOB;flxQPtRpv-592LxOaDUrpQ?E=cED zE=ap{C?@&Y|4m+oKfX8B;f>)kjoAyABNQ4Y0h9Vtlc$^|CNCoL0F=a(SwI}2Fb|D8 zj!^hBpe}C=XT`ajDyiw$&<p;8ASZ`y3{@~Ac>HIoKc(Rshz<{rvz!Vr8+X{zzsaG) z3!M$%1<r@a`1#HNSh&&I0_SgVIK48@;Q?%OogAoK@7xL9InMV`pRLbOp5+`zq-Lf# zJdtIFGevFN6s}cyKg{Mj+@XkIzlZPyrr!nsQ~iO}Jo~_@ufEw7?q;7<O*W&D%v3`+ zhYQ>DkeNh>2LdNKZ1|HMZdOlmszN>BaF7ir7jQ@;*kl&`4_}75KXu0EV29@gSx$+% zv^iW6%}aPoxPJK|u$>yRd9y=G4Cm;khBZ6U7HY_ra7N@c>esY+vu=7cD_Jet60Yhi zovik63AaX=zT6TXXMc$km&1eXKh%NZ@UE)c;CY(U^*GWg&<(bo?t2)+0B@UedXnux znwouAxWJd6tajsxhU=ZX!c{^e5Z2Hvo_U-Sn5h!ChDX?ssIgna?J~Gat9qml&$0;c zT&PH22G|Nbp^j}0cdk1V+L1wYIvU_vp^+gEfJ+5<T#(CYf%b4bGLm_p9yqU>Yzw!` z=1~{6!+Sb?4o3(Q9KPrM&QYXpqE+q%wRv0kW_zs4+8)lwi3eS`hnxGpODS2rJv`C& zHBVCC?+6dGx2oPd!;O&?OLm3}VtP;c5nl+ApMwASW7Tsz!?k>El1hHr8NSwrvBA3# z;jU`gu5cenAM6S*x9h2iyThAs@Oi>L;ih!B)ji>^c5}7#p72=v(~@uR374`<{fhA0 zNr@{Edv>3!CZ|=Yz2V`oHDfOhxS6ds?uDg$)F*qx?d>O3wSD1n>4k_|psKwJ(JFl% z(nbH_>8iW-h3n=2jwq+*`)tJaeVW(<SFM)5AhNG56~Cq8cx1fQ`X=SukE3_am(<!H zj>S^`W|CQhe5&$*aK?YOy)s=Lej@z;!j8=bC6|tbZwvp2J2tDUIWL9(Qn%Ew>#E@= zOII(+e<gfl&-gf`jg9Q$ZzUNi!ykwBZKOMYyyViGINgLy@Fq?jn6=UA<xd}Q&CJ2? zO{$|yz~9eg_Kxu@W<IiSi60v?Oq{Z_h(j1DumIvW3JL5@obtoin>am6W(O3%83-t+ z1sOhluL78UEEIKiDHjQ|FQg~rU?vB=nd%4>J6_v;@Sj3s2=|BvJ399Yw*x;Q+yVTk za1ZcP!t9Zq5bgthQFsLSbz!#2`d$V2bsJdUs{mfg_@5U;Z0mWN3<I<r%tn;F0{pA+ zD)8UJYruXKR+`~kJSe;Y92MRO&J?~2Tv_;Ta2{AsmhOd6OEeCF>kF5Fd3XptcnsWH z_-SxQ;pf2mE(Mr*1+4E<0KW_7&F-}O9++nlkxzps34h4WvYwrT#sz5T**WlcU_B!T zz6@R_7W`=WRtYD8HwdSIc?d5(2!VGBbD({%a60&)a3=U6%}D<W5ZLU|at`=e;cDQQ zg=>J{70w6iBS&Gr0azb73g!_Ad>PXn9_sL|Fpq2cNq8ps58>Hh_b^Ua;K^C3sB*Nt z9ITHS1+M_>V@AQ-z!k*|4{@(5d<2{?{5-h6Fz;SzEc_9;8yQt59sU*y$2q`tjR^cy z&@*)~lnvH1b>J#sJyQp+2G%om;2K~(QwMGU=Ew^@U~ST~bKs_6Jv#?(0oIdq;I?2) z&S9_wLVE~$b`IPbyjvV91RoH-27JHpATW=Nq1~b2Cxyp=pAnu2)-!c5GaLMdsPl`C zJr3HvmF>?*BCyJ_H%E=t;BSRlwSE)c4E|e~)rnnUn%@p)gG9auoF%*;oFjZ6xVrFz zV0}7h92Opd&`dNQ1-B7?0?gz4>FAT-9>T}KR|~T$4ir8C9xnVGc&zXXV7`&*&a2?* z!moqlizuLJ&4+NiF!O1pa2N1;VSY&S%o&>R1>PadR&S4RKk$9R1HcaoGn*b0o&-MX za$M)lNzu3w8ZQYKf!`2j)|?XF0%k{)f!GQ@FMK!n3*m>rdJ+z1n7TiUIvc1zh0lSL zc#I4k`T{}-Z#MEJus%){{1-Sw)B~tOm4wTJs|vGWsVU5vIz90QyPTcVr;LJm^p-wl z6x;@^PZ<Tb=TTwoIMHL?2&Io11@oI~u&DEkX^ij)@HFAEV4m7VyA!~A;tfnU7mNBW zV0OuAhCTe%!t21hz;SPd#eQm_{{wUGaiU-ctdA1~^YyBa69q@XPm6huKj{fJsHcJ7 z6?HZ;9|*Hu`9wGu{JC%q_-}nHLTzaLBwPplhcFuuF5O_@S^@pSZNTNo=z!3(3c^*v z`UFv^7l3PsI){z)1RK;jDWfOYQjz~nAT$?4^q{RUOMYizHa<Ot$AbF`PXZ4Uo(&!^ zd;|D8;RWDX!Z(9&5N4r{>+?_%qID2%6O9evJB0UwR|~TNSuf1j^j<RZ2<?$O3kPQQ z@mwXU!&&Qb;Sl(kFthJj;dnNL7e&Yce@Lcj{LUNvg)sUa?lGe<gZ4!K@s@}rL4jNv z%8qb(FdH7KR{-<dmYfZ)n8NlS0`n|aH1fba<%;T8f$Ip@0yh$7zP1o<0B$GT2+T{7 zX_w`OH^q?Ip!E}O3)VArQ18n2f23#>LSwRUU+_#}&P&V_9tgfkcrf@@VYY6|ghzr` z3A3!|89aD49;|2TA^`mEqnWq}dZrG{<kd5EVCJiysRJYR-I+Qt^H|T+fsxG?4?f}I z7yPq6Av1&V<HgAye=AJ)e-Nho@kF@hEe%K&X7<N~>1a7&_Rx9LGR<dzd8P?D8(bjF z`rS~NS=m~+Cb+9`Z7|m|!mc}6%7aYkP<?0&5@w$1nK!gB2(UGi>R^^?j%|<`P(2F= z#y@u!4!}aEC*i<ZU_A*3t_IeVa9{>#Gf!xtLk!V<bQDFG$?~8u+8nDyn5p_A8O<Ec zykqbO!f3PHNi~?E`Oih2sr9XJHu!hp+(Za}1xljTBby_>w+q$1jU&A<82M-82oId? z-Xzl7cla7r+ytsk)K?VW9;8|{g*Z~((G=p|A?gE&zK4dW{AN&|pyoG&-P!6TK8jRk zb3CGIG9P2q6MQUHsVyRNeLoFTx3+-I3!~KAEh5+ZewwLzw1f+}YD-I)+Ni#28L4Ue zRJm4>D)v0pyj3JGaVBb5h8j<mJJivJ$>mDTMsJpd)BD}k#yx`e#a5B%RqwQMCpbM# zTi|9`ViH1I|GwU+{H-I^8a71b<S38#^USaKZ{`<la?N#u!44|&q%RYLyYpK|@{(Te zg}1tUo~`fj4)t>DNcDe5KlP!ijqBBK<X(Dam9%aX*-|FH21UwVgg>0f+vxd?r;i2x z%Au;6$Xpz%x*CT59UeW0AY#Oh*G6F&kL4A^qdb-!!=r4gF+4heM*Q6AfB{j!2*mu# z?Pm}BEY+u1Fs;f@a8_<TYe$dVqf$9%n&6J}eUzeBT@xuAPoQp!pWP%}J;kupzYM2? z0jT>M90elGcSG0T^gJ+?_l4lXGn&C@AMe=k@zs~qa355hU-8GE)PxR&E+h0-=pp>E zL)&RC^f&zq@q5G{DuPO4=#FN1B!wPfu7?tlW+@>q1Pz3~fi>J4=1*?O<=3HI%*7Bp zm+?>+xO-FRM3NdY0O2o!n>U2|;qSZ<k6@b{T87|UAIe3t%n7AIeRha<jL!-c!ugpY z9*8p|bO&6*p{(OzG<o=oa69Zz8B`8o2~C69(^iN}mY%gj_0S;J3uQnpH`Ez65sPaO zl$7aQo(wyy<DF=!4z!9ALtEgd9l8Kh$F0x?Xxx%u`M9PiWiRiB32@zPH05!A=?4eG zO3D$U6-+{CQrz3wf>{Vs%JWRjlnBp1OnHeM4D!1r<@K##CzyeFro2TC#UnGvj<Zru zQwRqa(ej7n2+Bks`guK4D<$RAFRu7`(eU$21*3jMB+#G%+zfGnrWLvuuGpbAKwoGY zf|(HF=$}8-0*R3r>Vw2c3N3|ha;O#?yp+(JNQ^*;L&6v_-39$X6Z+?bS!{yE1L<@h zIAMkK&>Mm_97@p{@U278Z}Tpt7}Fz|Y}2e2<GS6TV<)qu#NLD}!H^bGN?}|z7}o5> zZilJVV79g&jXmR23kF5f<ELr2k<HJotQfy}g6<7&*)h&<2Rqsg;9hR5CqpY2xW#Uz zP7j+YU8fW;a0~X<LcQ27I1}t|cYvJ+vF8w;-~gNH+bqUR2oBOh^H?RMa&U-^#f<q@ zi&9hPTxSJ`YpqtXxyb+ESS_@U^<;Qv+d(+j1}7J*)`KItcCs2XIMTp(AxUi>tXsmT z21knQrmFRjNI|tq@Mc%)5BnJ03P{w{pO`9EkZ*OD{lRZ+wQfkHc8F=1`U@8`I>D{# zwIPuzgThRsUl_6S`e5GF-^p3J2&Mk{3xZuS))Wq=menE5j&XsZ2$f?TTSzUZb#hA0 zzHX+Knr^d6$c-hc?n5KhBFAZ<qE@RD`z=Wo4UMEnI1rSYuN9lb-cC?^hDPets780| zYNtBI5|G}h4YbfX)`B_>wec>o-;y^BLniWDBDIB9D~vJmQ(J4HU+g@BoZ3bU17lzP zD-4aTq_^#~&d69rCPjOj%OS_ay3n-_S{N4#QKyp@CdA4!6}#xXo)nu;L6?HKH6_OL z`BHmpb5moZsCBj79pRoH<10V4uNG#<{L~p}vr^5A<x*#e-4~Aqu`zUDr2QTY6vg;y zkviIDHr^T=%OH%g*^n)baS37SINJwddF%ikm|%~|!*f-PgU+clbd1);Ix)>=X<=h5 z6U8!hwib$G`x)_hIyJY)KBq@FYGFr=AHb;#w6HVwE3-MSg}W`^O96G`@W=q%FsI%c z9;xCx7Er$pk5p>>4CAwyi)oYm>^lVpA!gaBAG4^q1@N3v05$6Z*lUDW0M9e}EP%I< zh*YVo3*h;EZUKZw>cwerJInHY$xy#ajleLZN7VU?sT&-qJ{%Fr$zknsf;zCl7>7We znEe#=9R!Qx#et5h^2kWJss|9<P&2yX3w{EJL(N$}{lN=VZ$VB8I%*h<W=}!Ngj&;R zG&l-QgxZixv7v;NUQMkV8L4jPsV7H9YFFbOqjq63t9ll_x35m7_gVbvw)-Ztre%Ha zSFur%ta=<svCpvt*snvqBG1sa&+%<iksoUIIr>xaG_p)Erbdj4l&OC>0F_VZMa33y z+dfas#&M;e(yhv2I`bLrB8YrccsoVy85ODHd)lww9~H^0^A}xjnM}P*ejIzu^_O<5 zWX3)R&b3L_O@5UzDtC0GK`e~{-AcdM8dd!yQB52jsp<PGS#1~{Src!El()-kE9_%@ zf&X^#8hminVwysS&T{#2E$w}I?L8-aYv~}kG6yMZ>0o4P^Bj+?1?!fbrOofA{5S*R z%Fj|}p4%0&bfRB`LhZRz$9M*kVYc8!U&)DUBg1T5W1BNJvcmVGPdzX;axHq3WyeKk zRnqCXSeKdiktI#up!-X8)wBvu1=QYgk&3Y&15mtOSKeQdWCg9&sd14?tsZ0U+@TwS z?~r;0I&RCgTfCgL$z+7bzEjIq0k5;LS8BujJS=Fh8jO!rkJV%*7Hj2X_|jCV>&8c# zm*N;2jxlF0aiv|s=ZWg^@sVnke`a(C_^3V-HVf7=2m`gu;{^+HOY8}eS~f0RD3}<j zVc(<%O^mc;Hf@|3so0kHdf=>RX5(Ufw-l_UFYUCvkMc?Cw@;w!Z&QAU<)ed^FG6mm z)UOjGciDs0`bls+Lmi#uI{x>h$PK<PQ`8NUBMp5>w8N7lE$z7ac5>t?-|0kka7ttW zJ_>4H7pZzR>zjQ<=kGy$ow()0m0zRG*OmQbGTXuLDD#yiau&M6wb(S+PwDc&(`ITt zmaKMO=a$6Ru8T~BH%+HTI%n#vxTs5o<bx+nS6ik=x?`2c#i^*dGgNe1q)G){Lmy0J z4Q-cm-K<%beL9h;fYGx*{i<+UWFRii*f%Yb2@5BuMW)&nN*YXub;fS^j7YKXW1qS_ zBT^fyA8O7-Awz;cF*DN5PE<*=BJEk`y3dN#&IvJc-BXzUnPri_d`a0oQdl{fLT&<U zTV_Q{hBiVZ!!_4cMAr$#syqhV;a+5i)5+$$y2C;IaXRb9yyHGN8(4ci3_b^AY3!9* zopR9eO3BfM??bBU>fGsPpE@`@l3~wP&(DrD?@<%3q(pUT?^g+i*#4w3;%V%nTAdz+ zelXw14%Q^<Z-t`Ou^OA+wp5H$@hOx+t7Bu;dk#`0Rn40dsb@D-2j<`du9^CC4mvA6 zRQC0evi7Kw#@9ziXC-&X2ffc)^*=swHcx$%TPnX~_}a*#sQPAof>Y9KSLCVx_%_B8 z=f23Yxp7YNd$Wy0nIS0j{ILh(%`g^`5ljC5BBS*4*NGJZ%^H6k9`j}rxs)3-iTbym z%&#{5ngqc3w&(8>*}Hv_Ul-m?;tp~d*APF!ye*iQ;i<O;vno8b*|g%P&y?fWJbo*w z&Y=eU_99}O0LTU(6wU)bBwPdhxE*&56+k#98co4$Oli3}_+{bNV0P1~-VV&k9CAl6 zCv(W1!54%%*8ZjN81Q$(<H5fOPlW&0Wf3NWeaHejG#i{Ed<!@%ybR2@56!Fsmls|K z&KBkuNi|`7mS5SLxgT6l)Sm)30mtdkX$Y-E<5RG{OA_jzgS&}3$K4Bs*?Z|H%rW@! zWaK|{gfsi(Trk&skn_Md2<L<2!nJ|cZ6efx2G1d<g(l$D!W?x{!mYq}33mkFE!+jn zYEQd`;6uV3D8%=?R%dp2TQettk85?L|9l9~i6JKME5ggcZwapfzc0)N;bY+k!Ji60 z0{%+)F|apTd<6WfsJ{ySOZZ)ILLAkJp?(iSK==$eBK#4U7oO701+X`B{3V#*HB|o& ztnZsdm15)5gz8{ux%W+iSz~$q1l3s^y9vjcXN4lL=3FCO5j<2l8$4P#2RuQTc|2A4 zDlkW$=mGP1o-haY?;xZ7z!03ZMz}I~qu!bcjT#U*@<2oNz<Mtyn0e3DMO5zuept9G z_zB_OV17f<Ods%b!mL5B2=is|mhcVW_l1i%+WfHyw?N}l;oHD^|0W#W4E|o!i^1%4 z(6e3O6r?xD=Ci?J;RfI|;g(=;`(_((wy5_5=aJ*E%#z7r13EMmtY?eCqriG!CwL5) z3qWXQ9Jr(K6mWOpX<+Vzr<pn60m3(fhYK$S>xpBSSqF~mnPUhWAn2K6@D{M%;|bmh zzF92q0528Z2VNn30K884Ab7LzVeoe0N5S_9KLx(e<+#2h<3Z6l1r2s18H4x1$AnoU zo)u=J^osCT;J1YT0KYF>%9cAR;Z6qlQ&Hy@zORKjG58~IKcr_|O!<dsaFqeyh*ak) z13jY*E&y{lhU)deX~NvjS6-NtgxSK~!2D#Vc}^JS3v<G-p6~?D3^ozrI&drD^<egg zXjy@K3vUNsBfJkhRG9ZijTU|YJVE$T@KoVrV7=WFZk_=13pGv;K7??a82SdhT=)`r zjqnfPjlw)XK;KCTyMKXqiTXcaeJ3T<6Vb})J1N2Z@_0nd1i?py9d3<#T7(!ho)_jD z?p0xS!uT!1fU-M$L6~p5Z-w)~KMB_W{~^pn2`qF{XqPXnB;k=@M>Fz&Gz2}n3`1kU z<;4)cUn>jqkO94~6K44K()&8Ww}9)58NSGx2`>TjQg?cMC%6w8ofEc<T&+p23m&Ft zh#|1ixK=dS>P-}G3)ZvCFvGXp98vEMo-fQ+?`Gja;3dLrOY}@L?2Z7h74^|zE*fJX z;$tCjktBr);N8M}MII1lBXhrJ0bC+{EBHy_<=|(8SAbs-UJHIr_+BtSqUhH%;4?|c ze+th-I42q}fiDWb0{%w$P4JJx?|^?7=9}{$;Sa%yc<s^6Pr#|dtoJct)_Xlm4Kt0{ z|EnMxth;)e8XDcfdYT&C6RfAH!G&NwO%1*ptY@jg{lR*c8axlIXQ{z=g7qvlcqLfR zQiIok2hm?{&EE!LgaqPl@K|Af;d8`=vDpvSQ`X?aU_E6Gei*E0tiex$Iebm?N5LD& z__%P862-!0!8?UBz;Qig4MUj_^u|#z-~D>Z8k`N*Q`X?BU_E6G&I9WyYcSvOFN>p{ zz;6m)4Sr8}AovsEVPHLb9YOw&fxz(shLi>H7vbx`mxZT+eJQS)+29mmzRSbHH-poJ zSui;+NjF!4vxT>VbA@+;8|$r^Q8$TNQUlEH5!dIE)4*MYv%r0YnL>kvD}%XMnC6*6 zV};ox(zDl4Zx7acPQk2xbH&V9ls|XVDKsX77m3C!@a@9$z+9_M4{iZ(CnJ>1*L#F9 zOKROK%ske!*D%9?J}&AEoZeds^_pPrCympgS`a=ELj~aT!gax43bTRwPPiHP7vVPG z%fcPOKJ@?SW*2aZa4#^g<e+*VaGG#G_-~aL;TmXU3$qogCVT*#FMJ=kj_@I{-a}dn z9)a~#HaG;<Q`ul7n5Ad3!Rg?kv<qfOmn*GHm16yeFiA9Wz%zt%!SjWgLN^ODg_a1{ z2j3~&7_5Ywf_DhF1Md-LYp7?n5r|FT2jikq4B;{1-Qc6b`@tuL4}xD3z90OC@FU<; z!jFPK6n+BCv3|ywU9OA5$H9M)QE0e85Q7@7kP1u^MjK+qgqe)#!YpVNg)_jp!d1Xm z3A3!!5oW415@v6h!?g66H3EA}(f&hVqoFsKf_sAX=2CDWSZ^)`_XQ6Y%R|7!g-3#C zkWp6|P`$Sl%#y!Q)U&~QZz<HPf%V=}a83B{ZZ3t;4;p%NDVT+ElUQbby_a0Zt#S_t zBTUw#!mM%}+@={8v=hSlU|vc>_1fUqg;_q{C39<jD+nKmMsM&Z!mKL1tb~>afxi|W z1^$N&Uq^yD=}R6DP8FU6<|QUnp8_r?JQZ9)cs4j*MT8q6)DT_>=8Yz_Tm)_?d>goh z@G@{a;T7O6!fV03g;}Wk3*Q6gg(h@!AD9z3;JC#)Jy|qZs(GUc4LuH?D|`gJP?)86 zsqoL>mBN35*9#}w_=pkaV8ssMAb5{(2z(z`o6$3F;CN6p_`&d)Fux0q3iG?*q%gk= zUK7p-^VSo(!*7HSg&TlB7v}un55ld$mxVjA|Igb^XqhAaA>m=*(!%4wJO_+sIEbDt zyb)YY_#SY+F#80Yb*K50;3mQ^fm;c`0qy{f)6hE*x{1bn;6mZk;A@2WjWAUBESR^R z&@R^&=*_F(Bp*IDL>+y5>^E}FM8G!+mjM?EXR`mlScHnuST4-I{TgA8WNj4Yfn!^R zYl3$P*9G%76b7g<_<msySd|Em13xJ|0sM?+<o|34FNg+5sa_Ml3H**Qw=SF!UI9KQ z%#8vUg+Bv-Bg`F6KMH>f{#}@3LjMR?OhDD;_di2j8A7TskK&36R|A(5&Ij|x6q>&Y ztarhJxpt?PsB>L@ec|QcrovpK-(Gkfn75?Ro%m)514Q^1JWBXGFmFkrp&!B53I7hB zCHyz|Mq!SG+$_vx^Sm*Ic0*vjBNog<tu~7~m(cIxy)ZPyA(8{4!O;x8BNpmh2G3hk zXl4-jDdDl;6T*|gF9}ZvzahK;d`fs5_(S1?;Pb+V`ThTe2po9$PWWl?Pr|Q)lkqzA z4lUu0DP*+3R%v0r3wUD+)!F{@#uPGNLcAq~2Vk(1(ny#usupC9zv1<4wG$2YOgahY zfO#_t&xSymu|^2fv$4WR7>hTf&<s7EAzT|gSGW#%p>PZEBH=dR_!1G?LD)=22(rN2 zg)4*a5zYnQE1VC0K$tzEM}_NwpAv2kenGe`_-*0A;E!C6>+bO9qA>;<KM3<}_M7kq z@ZZ8)!2XCE(7V7v;ceik@H^nL!ry|kgwxPi<p`GpSC4dd9b%hbTQn+x8whjvNi*R( z;5Nc++dB!fZSPicpk=gsn(xBR>bE}8Uf3Yr`RZtIJ6$P0x~PkM3{{Q$;;~#U;p3P( z#m6p{*AI^#YAznW&zGy``@#Ops$74l=Bx3199AWK^iavy;4xhd;A6YmgNN^@_3F24 zU}K)@JOHZCE5*kVb#Xv+F0Z#A2x*r(#K%bW&%kI+ySJ)2C|U)9>OCl$m-yl+eC?|F zR4JpjLB*Fh)m<<6(V%G59-%Hl4fBZQ21D!8RMlp1w3^*UjfZHTP%H6BnvF^{U2d$$ z9`3=>|9)frf7#v~WG}*=jz4AA7G5k9UxnnuBEC_0{JV&6HWlp@zFM(}Z!sSnhT|i- z3?+YJYyC*R%Y6)|o}I!SKmT=)a}o7Z{QS7bV!I)DBtHSODUJAN0eb9h8ev0Y@BiJV z=Wq6vY55;+`pZ+kqF^btaai>Gk_V=wU2B*092vdS_y4@v`5t$(^DDC1`D5AaoUS)J z`##5fY%=bu|F%(b^vZ7MTgF6<-OgBJSuU|o-3ASstUX(`nmwW9<1x{H%BSk<Qh2V# znTYx#9?gpLqX`*Nf@1w|Mm&Zl9_gBaHV_#RMIH2A!bka)d+7sc)sQD&pg)5=;ZPdZ zQ?iS#7giohf^4U71CY6Uns*TSYq1sZ<)S4_Oy~g&`4%7mvYWc8T3r+^7ynAT?&n8w z%A0W8pH%-37!7cVbW(#SfpB6pbd#E%0|qanO~yWInn7lBlar5QneJ`u*vi~sD)Qec z%aY`<Nwu9}bisKDp-6BlLdEawj3E>buUJaLj%#QqJ4f&)NO8DEDBx5B2eC0M*pNLU z$AM@$S0e~<=UMPg4nKByQU|wZpFx=CJ1zN|boj+}gL4c1&U3gcX0CG(iFUm+8fi4g z;X<a_&H(s2%i(Q0Go3<i#hl@AVLX;u^5~Y}@aN%bsy}rQ$4Z^WFnro_xT^YD%UOzG z*K__r2IV?i;Q*rbHbRj){c{8pc2>8cotvRkl<0f~KW(QNI>#-C`@e3%D$9HXJasS6 zdQJHiO3~EEhj4Rc;1KMj9wAx*js&G1y&32ad_(ikKLAb%ahYZ6OXOgH18u3V?*Ti3 z>k!e@x5%LoS6QZ>CWiytQ&rI|(F$=6e_2jB#L;$m<(<z8KMm`Cr}!5Jw;5t>IXtAp zMgh7ErO0Uny@TVo*{_H)Xil<CvsQF3{Bj(<iQXUG3MZYA7W7VX$K74;M4zFlY}b0! z_n}`^Tog@jlmb_sMm9@KR+Iz!xYn4l%#L=T7ai?4p_3csVJS{mdo^_Oqx&Oj3hdV4 z78$2Mu3E-xBf1TF?F_IP%Vtr=-WjBY=Fta2>OL6H`T+UmjMa**qmy9HnQiZd-8L9H zQRfy#bA2a*D*4uEeS4N_ek;U_jv94qG+ymE{PBkxa!Ns0fKVf;0R5p6YRO&RDR)Oy z(rwXZ-Fi}~FY_ZQPz4$xy&pX#z>)XR5QZ)g;4ouon9j4%teMwZp%HZ22~<XMhend4 zR?2X-?6zo?mfWrto|Ot$Qv#WYK=?-5a{?m~-S7f_Zbbu}U<=<wPD5tJU^clftof#@ zFK>%BtkwdIUGpLM8n6)GNM9PY0tN8SWq;ta1l4hIwDwfyYh*wtIN=r{Z#z9_M7-_v z{8I9^({nU5GV&apOAnN$d)G3GS%D-JugF+(g#eFricIBx{_Ma$+MRwg)N`$rG3wmn zXgS}>1oa2}zGe+7QuJy@FD1awf~Zc$U|<x&6z%6mdm{XZ_9uq}JCPjGYsk?6KboTh z$fW`gpaez-lG6fzB&(a2M9a2HhwsrL3}<$rC2b5P=LQ}?dPIjaJF5qRbZ-PXKd=x< z8XZZlW0h;6-dqx`5?X{X#o9AYzCecZEsa)*vz)~`)2m>B7tzJKxH-vB-B?$hlL4+Y zighEW1$f3&tUEb9a3gHRdT{efR)AZ|Vm;4*^8?(_7wg3acuIf^zGA%@jIRT{dn`7X zr^bC}m0>8(q^Mm>qwV5nlOZ_QLBn=-B0fIn9w;O@t&vuKXBn&|I_2R(l5+?-k?gzy zl@zA~R07VIsK7yIGEyhi*#Q;D3ctvAM5zXI;I&f~PTN-a7P?fb)debX@-)Nw6e`bH z&T**3Pgu_P@cg9ZY=JwkTh9CN=1;xr$-3Qko`l{G+i8l&PTOe*51&YIM#7Uf5}X$h z*E3;<+l9WU;nauXgC~)-Yv8QkUeX%wIJ02HayYPII~(Dv&*_M~NpQG5)$cS6SOXEg z>hL%TOD-9`8ajF$M+i9WVJPTyg*!nf6Dp}zdOH}xb>GZ0`(|ilY{MT>$k6w@ZB5kb zmTIvqS~0HRzrEiz&x6Zc^R9wxe!pwJ7=FPZbH+-?2eySfy|ph@;jwGWRd8)R=h|Yc z3WID&%V+Y_50`#dg$w1g*s`NL`u?(LG`flT@VeH3UWH}q_hr$XR{E00FA_VUTxRN! zf2G~b<jHaN*V^;UC<F41%iM)$f9vx5scO(2(d?X8k)-wyi5v;b{F(NCOzZ*oDsc?X zc9JUHlcKiV5zQ$)%WzgmV(c>K(oV%BZKoUEtdzuvme15lFh7aqHS=cX*aFcAFl`oV zK^uG{Nrje2t7hof5AZSe8QS*&KKh<HMs;5vt?c_EtfnrHrsE8ZCCj4?D(m>J)bX{i z&b<x>?UinN!%?g1qha*{Ojp(!`hbpREvV<}q<KIm%~;4)idC6Aqt#twPiSL{uNZqm z8+*?+HXO!cI*0?48N}adY>ZNOMl1QY1=XW>MzboPX8eaF^Ciuqo%b8FaA-1PF%oiS zy88Lf=(#4<S&9xOBN_D43cGj+%6hI2>A_?s9+#cCAw8JP;@5}r>0}jN8O`>68c=ms zM$_G}oJn9<)<QpTj2g5un$@Ec!|-teop}Sw)o{K1*#zd)4>Y7hcrJk<tN{P(X-_}V zrhTj1)E@_PYw-VXR2zi8<oL>H58L-=l8UU3PVF+0#h|P|8wN_V;uKFP#c;7Ol=U+l z#fVrQr!DMsKl7av$$2`XGW;x<oHng@CZ*)$>gX)njld7u;x^bp1iG$`R<bLpiEE=3 zYU_~x=4VJbE#QXqcR%CBkdDWb-<K0HD$9^Qv^M&oJyM5ds_u!*LXmU*o^I1`9$=Tp z>2rGq*07?9p{x^YrcFnaVTOq{OZN$?Lvj;qw#^`nfQ%rh@7G7m``}$@L$pRh`TG$t zyNqq$j?aF#_?FRrqsSI+ie}{L;PlW+Zi((;yCoWptKCZn%gT8J`<FJM<z{c%KAYr2 zn!U&JP{N9JR#%hXA-j%!lEic_&+O6ZdOnG9t3{cgXZD38dN7W%zTNRtT}f|%%(#7~ zB`$Hz(-rKZHvK;2HUmrgY>p21+5Oew;%FH+ZywckaUlj!P|)8kj@FEKgyZ(BK9=0d z_-_{vui%w{SGD19V7N9%K<3rNpAOs}VmC<02lI2!E`AF`F>Z-zpi3_Au&JkG(kOv_ zl7!WV<8Hb))`heq^>ra_f<lVC_N^XMe-4})g8viX81sJpUD24GHwDqKM<$>oNv+DN z<oPvH`xQklp^&|@HJW1&Qr~TjX1LM3RTsetu5S5lx(GJg<`uzZx(L=U?}g(IDT0Od zhr_3>_<ugz4aRNTqEqawiOk!llUd{VLl6<|Ymr)rwhHaQ=ai1_$z*2S7nwAZ<ev!r zWOl4OEJ7mK`H6L?&I~P%R`FtyuU`zQ7#4E#zP4`s8bhx42W=H3vMa~RF&CC^!vB*w zFsmz4k3^Q@ZZum_CudLH*7;U<sDB3xPQw4YX_$3>2hykJ927bGqK`ENmaKjFZx?@f zB`g<pZkIvsBSph^M-RnyS#PP8Gj$AG`xrwjy?_aF#7~#(Ik{d%IieHYHTjfo95Qv~ zJgN<5>WX<xCv_GI?r}fUGgC+9X`LaNIu_4p6Xi31OQ;XmU-Gl?qiB|9;B$QTmMh-n z7y-+51J-$pnzk!iro0aLVO>cVB0f#7feZH|uz6!jw(g3K@?D)o*M79^tMk0T|0uPb zG5guA#vRtv)Z2PF>^*S7E>5q`#AoC9t~P!a#j!0{B_PH6?1^r+KUH7viDvjvERy#| z8}ZqCZ?p~uL8kAGma*5U#e1V|(z$r2bWMK^exEaLN&dItZuhzBqrK58zK?M})V^r5 z($}L#+B*hcG1c?Muqxaatr&U$2~sAt7#4d!?Wp<tqIIfFgjsBbx&*_eStv@g^|K0> zpmC4f#$2j!m9iH{%Z5s`sVU9&$m%&%eZMbSCe$2uBXjvhP<VH;D!m^cX&qGIezb|t z`_+{F(Mpwh8*|ypRbl6qt6-boXjb86TDygA|Khq`Ub}5w-5TXKazirOiqdq{y87N^ z^}+sVjdDq7oufrvsKJ~sJrpijJ&Q`R4n#-PNa6i&K5MEzYpR@@np-OQ|L+5*>b@H- zO6T(LP)Vgr(K60|It=BX(`3YK75g=sS<?5<==O4Uy^^0w#b&OL&qvyO3&MAiky89U zM-I5Gw;dp%_~R~7ZxQ%HGFn6a_&M&a>E`k(Z@qSTxaY0Wj+0r-@jHw56Sv`DED^u? zeBoyU@Oy-u<MI-CYUjG#jpd&CjUPAd+tplth@9uLz8x9GmcRXMrcw6z`xqa2Hi`*< zx#&yS$Z!6tl!pIyzAK!-K)cPp8-CsK2C!?p{5QG4Wo}%sb(@JzBuF7Hr{-_D!E1zB z&Nd1&A&Z4kaIdUb*75h2EJOXul4T@<b(9v6WSF3~I2^{cwn#PWJ%c|IW-eS1=7a%1 zv1lG)x4sibqiV6LQJsm$_duKiQ_P22Pi_KE5^e|P79%cyWgzqlWN>A0RZ*`2t|?p> zTvxaOxUq0Ya692H;I6{m;lI^egg(&dFFXi5M0hNCl<-9Gc;U(5>xB7LJ4=`)>IUIk zz;WTFU{04YGP}X6HN*6N2ud^_0pBHj1iVN1Y48KWXTV2<KLkH5{54o#CIb&HfnOK( z-@vDYIaK+f@L%8yUg-D^_EsQcbXa$y8B)G!*}EsFfH?<8=2vGTsvntK%N*edxRh`y zFz4N9hEpL~!dxC#Kt@T_3ql%-fU;(><)sEXg;rZ()G({FFbh;qVf4YQzQX9$Si^)_ z#m5V?pmEzW-DFvrBis~>#l@HqMA2o9(yNQX4Z(VKF}N{UuPz3+25+Zja9glmT?}py zzE{*)xHz~%Gu^<C3KxR8QHSay!6${svHraz!gOfpGpb;S9h+04egpU;;rU>_x)^5I z@%dWRi@-k$F9GYt#W1rBY@v;y$9Dpggjaz%f>$aIjkOR;i^e9fUR@0Jo#0$i=ex5& z_+fA};U~cyCZh+>fx8L63@#LY4XhUt!_52Op`!jBI6hhgmeL8rHVOzwK<H=^_$FZ% zuBF1&z<RMT%y4>)pJX)O2)tdGQ)Lg5(RgIT{l|o>g7xuJX-I!IKKl467-9pWkDmfJ z0_)?az-__$_$e^+TOU6K?gTzBj&=p><ENm`w&aqi4+ZPvr=UIotdE}p&jH)|_$der zAta;0W=Pp+aOjhKE4U&Vp9k6CTw#{vtAuNU>j>8dHxjM`ZXt|bqt#BBEiCs})6JG_ zt$K-22<EX2)VKybSa=|Kr0_8CIN{OYDZ=x>Glf}5=Lz2ozDam7_*UWNVBQC#?`l{L zVU=j?1#b{O04^53AG}kTt>k^eY$YEOJ_&wYn1%6}Fbm_e!f$}}aaD-qd+^_SQ#9DD z^3FcS{v7xt;m^SrguexUDf|=oJK^8KzX-Egy)66>*oRh)Zn7Y!2#3L8%}9Sv2J<yb zL)F0?e&n<`s<XwjJIHJS>k6|4Y%B~bR!iY*aC_k#a980xaBpFjkN(1J=!URML=V`~ zjS_AO*5_D3y*rpAXf)FctQQ4?2ZQH|I?Du)@Ze1cO~9*!TY~kXV5qkS>qWufw&0y& zCeG@l7X?G3BUmpA26qPQMZsWt{J2=?2R<e|2K=1xc<?L2Gr(^N&jY_Nd?Wa*@B;8> z`mP>$z-IDm(O3!oQFsmbcj3+8e}s#{i79T3*-EAg?*^9=-V4qUJ_ODdW=pCsqJh5; zv;F5TYbM>J(5Nr`D!7^ODR2kj&%nKf`M&3L9qqC(juHMFJV`hK<!QPw3*hy_T!6NK z9EWATn{N>fE>l=4Tmig7m`$uc#|q}#fH#YJJMea4u3|qRTnK(dn6u!=geQSt6y`T# z{B03#gusIr7@LJ)P6hA+hz^Ji2inPfz&wwH+!y?pFdM6cfU7<b91tD?jtGwfml5XM zmD5UaCvM#UAxAV8fU65H2G<tmtFwVH%SUtJ)!=r*TfllzFaoy~tQQ4?cYyVxVDK)m zUK9-810Jo9pMt;wGC>@=A3RmK1Uy^#aqxWMC&9M}p8(%3{498-@C)Ge!Y_e~g;}<C z3V)9B=iWGjKwJVJ6pin}4-5YYJ|fK4?HS>Jz%K~<kY%q6v(Naha28lE5Qh6z!Fo|J znC0mQn29ql`JVnuEVKpdTV|ln0;O-60kc5qTV}w0!5Kj}zlVV<3117=m(0M-I54;O z)BP#ny24Aqye^gMSPK%jT8gj<8hTMMG`52KiuxY#FyW`b*9yM|=0GtWdK=7Rh{*4Q zX9=GHFD7TBhm6!(E*t@`(Tw!R_n@^=G}6Iag{y#f30DR07v_8Ypm06#aWWcwsy`>p zw*3|1Cg8V(TYx!HMf0t|AIC*#2jNp;R=KZ)yMn(LX8+(<;r`&igxUTlq`Hod0SAO9 zf+NB+!92)`9<!ElUWyzqhEQ3A9pF4+)(Cw=4GghH=o@Ol4}tX!HDJ~VeM1fSd2mOu z`wF<b@CV>N!WX~;gueje6chCSVVR}<TG99$JW-fmJkx}^fOn2C*96TM=K8I;FxTm> zA?Knj!JUl;Zx!wi^<Bb!*#7Sqfi2o$VYX<G2(v{yB0LKGwD7gy=Y_|D-x3}VJ}o>6 zd{%fm_%mU4(Y_|f5z<>B{2&^u!G8(w0CTp0v0-baZ>|CF2bU4``@osP>_Jr){v4bq z%=V*}@Xz4-!oPvz%|!SELK|TV$;dHPdh7@H6ix>B6%K$039~!Ji3^(Nn{BKxCvPST z^T5^_!t8O)bvbUah0<5uz%pAXPI%LyJn-$p%vXKw4b*Fc*Nb{X@D}0b;2py4!Fz<e zg6|W)8vLN}KJa7ut{ynbaaesF4){^9z77Y>21j3q13m`U*WrLqg7tMcV6L<NP#ir4 zJ}=B+$S;I1fG-Ju4gOj9doBq7Q-oi^cF2u=f)9Bw8~}%eIkU<o4@{x5V0~o{xC*$E zsB_tLRbeib=7rHT-xOR|xDB{5I8Kc&5L${xPq1D&4E6rtuA)8|TqrygJV1CXc$n~b z@U_Ad!CW^%_qpVHn(#vK9N|S=5I$do9njD#ieZ5p`j?3MBj7uQzXq=rz69PR{4;o) zFh{j^3v(;IUT6$A%Y*eoV{i_b(_W==QU4o4cv39106!z#8vKIrAn<F#Bf#$n^HB9O z!rU5vPMF)_d1wq{Uj+U}cro}#VIIczyIv3uL)<g}k7%p_Cx%_iT)dqsya5~&-ULn; z=73ct;cZ|ZmqCvo0@oBi3a%^60jtKs@e>eQitsGBy)Z|zx(dGrE);$Te2wr~@KE9N z;L*a|RzE?Q2eMBU<^b1hVGe5D7-svAkox^dCeh$X)-qv^Uab@60bW~$Yk>C(*90FD zt^<BpxDogXVGd+HEzE=0UlAU{1>x_Az&-PvRbYU|fzJtZ9^<0$Wbik_*MWZ&=7D^_ z3v;yVA7O5>PegBnZY}_)3f}~dk=gziK}Z*k?chqnTqagk_#tpjVUB9m6@CKTMEE$k zl`yx@w-bI1+@FkI4A9~#05Tp{e3S@fAdD9-2fj|Y0(h2iCGcF~%HU<>YObTJgz@gO zHVC6UTgAe7SUZK;<J#+TTrXq4S2VJqag>~gHA&!;!p*@i3AY5lA>0OhO1L}tLt(zY z&kK(Ne<93X(09Ufz`sP0|MUzG>#}I@!^0PK)t7<;!pp!>;dS70!U|kLm>;QCgxRy= zvLL#@4O}3+8{AO%06lIl!a;CbVRo~+3$tt0NBDJcf8lq*6Uf!wd4Z|I%!1j%%z_(* z5kIR)I0jw}j?;23gyo`91H4AK0K8F{JzXv|rTNC-ox;qHhsm(WEPFz@F8H``eeiR_ z4Z*Jn!=1SGmIxg6;0ggc#QgqPxC8i8;cnosgol8C5FQTZ0%zKt0Oqn1@-(m?Q6<j+ zrwY#kb9ZW~8c6?z5Hdug2wX{c5xA=GZQy+2rQmwPE5J>KSq|C@-vjO?d@p#AFthbq z;ite8<03o*VVW>MBIgLd4xTUkHuz@YQ{W}SAA<i+dFKIMMYX>BnaNIe%Ou&2BoLAi zQmG*%p$btt(m|S3X=0%xMRd~?MJx!Og&2AhMMOZiC@Ke0!3OpMiYN+-C|I#_-*@dV zfX8z2od0w0dG6iMlgw}RHQ%gR^;>Ih75)aiK=?HHZedR8E)(Y3!F|GE_SYU3Lly8- z!ZpBqgd2ii6Q;`jTf!HBKO@&bO89+y4*x8S*4S|3g{Pl5uum8jq><uh{SSv!7}CUn zbwFKm&FGM-M3@Dqi7*S`g~H9jZG<lbcNAv1=`PH2(?_@ic%X16zWBq$&;<@x3U>pK z7489^B+QECI$@3rW(f}j-z<D3_;%q*;JbubZpwvk0k0&7ahG?&aIZM95N#B`8@yF` z3HUML<=}q`uLAEDz7M=tn1${Q;RnI{g*Sr_3GV@ikBDI}49A6E1%EC4HuwkO&%vjK zzXitzqK}Ca4qjoFC!a9;{K>-X=2sD}2ChS{1^M%N7e@_xfvB-C1Y?v5*8#T{E(UiH zZVc`w+!Wkf_#*HCVU~lT!kxfZ2zLdK;rcIfq4(QfBMz)grU?%P&lDa5zDam0_%>lg zVJsBB8N66{A$YkkALUwMKC%tMYZ!R57#;vWD!duIU3e>aFS#}(0)FEh-Y?t&_J@R7 zkdFwnz<wpn0{eq7Yfndz^*<sV41*U2@^G+Ecmg<Ccp5lMm?gP}Fl)d<Vcul};Z5KR zgtvoR2(xl)CyWLxY;+OBJ8<YJ{1LdH@Mqx5gjoPb3V#6}Bg~QPB;lXH*9mhjVU{ol zwR43zEqjM%$e$xwB@SFNT_T(XUM<XZf%}CE!4C<uHjD^!htd<moR)oBxC3~Pa2N1i zVa}qx5f(!q81@Ta4L&415qw1Wdhl`K+2C)4Ia~Il@Pl9;r^iS6I5=K-7dR-q2V7Y= z%$>oRVmJ=Y75)}nTi8S;-cZ;HZZ6D$X$xU)0Pab~yP5*A_dAC#6RraL%Y}2nqe86z z5g;Fi3F3g}z?dqGH`ACdTnN5VxClH?xCDHsa1-z%VZQfEh1-Bv3wHzGCwvL(|4m{T z35Q37uL5ru9tYkj%)Y{IVfG1L7QO@gy6^(<yTW`UJ`i3FJ|?^Y{1v$i?tUW---*LR zV0R@rpzq}XCklJO0pTQYE*T=BpIXB7QyBU31>c<ksQ1h~==(g@%v7U4_D#ah!XqF1 zIzxx5!6&%fq~_pa?b@u~{=~;G7UUg)?KCxsmqqG1T&z<Om2%YA$vUx3U5+b`_m3Qf z^^4n;>r)uBRj*IsIbN;frBHp(%OKU}GX~wG7JUXk3)K-Ak#>V)xb#zVcqvqG;bQIH ztMWfb^q;?~CgY0zjL&@z*K(D7-1num<8|fw0=8wU*B8D?)?ugG2cvbkvC8}s)`QgO zFMTy}%;r5``na?4sV{wbv0veNJfx1n##*IR(g|O#^{|R=ZR~Wymt-ARY7i|C3|BYt zx@M8u#OsL>>TO&ho6{$Jd2tIL;9y*hxy#JL*3Hf*eP?zz7Abs4G$p1e`tbs5!bbJ; zMV`u$_fPs7dc7qOzWI+>bXyHo?H6BK_(%*UWi2PQ8qRL7dmk?qHpo4Pju5uj6*_To z#qOh}%gHJRd+IpPf<1MwAu7G6j;l}z(gT+`$2>e?C!37u_BxlvW4Gj^1wYbb^rHng z@t`I7YC$VxAjUZvVXRAZLYD*ab<*W-TwIP{kq7tPhy`CU_zo@})?$w0Z9s%Lf;b(G z*uV60BNe`4KtI@P$IVIcj<}Lp@NGB5tr|8D{0`eZCFgp(l%Msx&gOd3G@DD**V=dC z|5UpGUZ>bR6l}8H2sxW%H$pzHu^)x&M4O6A6YOu1rSUeG_r}@$vdUPShe%;l+)Kzp z+<;w3EZ*Vl6JgRkSQFnK7=nQK_5k<R71`e)jqF0Z9)jW)c!;ZW%x&<8K=VIgphZYv zdaPXx-==*pg5ui)<JD)s`qG;%fV*@10N5EGuJt?R8w31ei*xrXSi2IqMZ)<4+2fgm zw4D1Ef#W@k-KwmKvy$p}+E*paX)ePK!r8P(;YKZcBsj+AQi#KDKw;W^dE@M6@aVL8 zQi#jG9m%-uw(yD10`O~_u7*PqQDOi>a=6FxNJ@Jha&Oo?0?V}b!oo5VTO&G$yZkFU zuSNp+$U#el;3m3LuuJ+G?k(L8lN%y@yhXRuq-Vod3(>gaO^yy6J|0TowzWZjHo%>r zIo`Jte%+Zmc#^LOk+^fsI=BRVJTk^z(;Narif<;%QmF~89-~H@kCTe-iVq3krNRN^ z<~wl8_E`+n&b$$JwR{)fwalNI@2BTW%unH7>~k|8y-Z5Av2QVM#N9_5n)rI(^?^S% zjT3Y3VcM#>FUUKXV6H~UGQ;YwLZ(04Y_A%d{$lfh8g2Toz?YieHT|u_HiSDp$zFte zy)nuD440ir_BLD|o^IJULqyYOTJ|6$_uj3RZ6Vr^?y&3|;C>j_?TG&bt}S7{bG~I? zitB1z^KmaP;<_H;U&1vF=8tf_2D11bSDvXk9rAO3$D`lkyiGU2qkhS}7w~S8`D(a# zM|>0Nz<78Rb9_@GrgvB2-y6VW4r5Kj{S4wxi|<Kw5zhy>nfPAxVR%*`t@z$#%X25W z4@Kwj%*VaN_a(=AteC+tTuM)Io-2`Je7^;V+T~eGPyLyz1WzjM2hiT{xtjI^X`f;w z&OmC8_>m)!vONWNZrV@626r_VAzXHAYLa*ssBnxwExZpoa3mD3qTiWF&NLDyFu2+I zWm<88+ORnVY1)0^)w17!7-H;G`0p^>JmfCL>{|^k31bbjKV!y6Baj*MGS)*54-2z7 zgvHn8`H=QQnc;ZPBZ$BpwhH}Q<er7k9L`%08Yw$fZHGVId`NY0_^)chRZ`P1+33dO z?|b~2<y=C~(Ww|_Z$xxCY;#!j;FGZ|r1@v{wZmUGgF9}_7#+cA$RZDF;|^`&tC#z% zx-izC;X8yIFkL3)&6)7r=hfI)e~Q)CQn$qVGtH4|L##hFtna0xgE!-aL~^iI(l9$Z zScrHEc1|ZI)k&MF0-5tY-8*YDPy5K37&SA;5t_T=pV>vbzpec<d>04ZWAK+_(Y>o9 z5Aj!rIVlfk-FJ7ey5pX;f_GJqIRB@~E5K%5iw}w&Dzkh({NwI>IQ_Z2gK19O!F096 z=})bv@1TvvJNS$#Xc@M#m|`V7mYfcV#cXTwJfe$e-lL8<{T;0;v8vSN&#kJx54EPj z+3a3NM>f>raX)5{Ivvy$mp`-gF6Mcy$(F`E0hdDUYpt%p3U&Ck`jHjt!m!q?N<WL$ zUYEa?^_g4!;__#iKdVf)KO=)>-MqnKIpT%{7V$I2vfTK{0JndjIXH>8zr>*vJZe`Y zxI{mtXo5?$L<>)_Breg?HfpiNnj3W}7OMg+xEm5EIC|TtgDZH->7&xU{&D6ZHQyVR z=QgjuzPUsl_xe+jQ)j%tsyRyK#QXnQliQljH8IReF(Tw*ky-vVW>%t+u8E=Cc|sZ@ z_1XTa^$HkZT?}P#8rHe*;>nr!>Ikj`=2FAYTpz<WXB*94HPH4Kr$5bd^0~I&f}o`- zNa%9-xfn_1UKe@D_IEVRjp}rQ&S7ezzp7tLJ~@UD`Z?TiZi_h87WU>gH9XP3CVGVb z$P<3lJ$QZ?3Qkm2ll-lduZ91lR#`~9`Edv%ie+!9sY(8tI6q@;l0TzTEo9O+Xca<n z)EguiEq1H@N&Ymeu~Yq!<j*tTQ`LO_?1Bdnxl14Z-Wda+AlHqImMq%NYUW_t=%&0? z+qlRmpZ}2G$@A1KW4@}^IGFJ_RQdBFID0+cbH2*<YUU(ovRYmiijCB(>+cj7d-)`E z8X^Zv{Fj=l=ks<#q*DX`qE2BB+$wbM6Zr`6^!Rh&u1tuCze8k}DEzWmGEpM=n?pwN z;_nl3VwCexVVWEv;MbFkN5~)hP$nJ+e@$6dse8%aLo6~FLGZ^lQL3~vJ&q*F4F9lj zGMJ-E+H)}XPvK1PbHZ8RmxQyyuL<Xa-x00>K3H)Wdo36~7Kb|EW5T82lfq?SE{`(d zmf&B6+ks;sIofvtb974X3)W|)<K}oXnY0H}NIYSR?Bo5{5(5QLB%B3qD9k%(Cd@l% zDa<=)FU%Y0B8(xK(NnlSm`kNhtRa}oqhwa9qrhPr%3zox4sF2Gg*$@v4g>h<4c0ph zz?_}BQ~X>8);kPfe>Hfi*iQzp7UtW-*Me!S1#>x-yq<F}+r_W}4m*V(1n(B!41QVo zVesq1JHYP>?*o4z{3@8|VljaOV6NAaKLN9<A|C~_SL)|soL|Af1zS3N1LlTQerGfd z%*9)B4p^Uq4yLHtO{G1{N1kvQxVG@c;QGRyz>S1iKG=0+*goJ^VKH0^!^OfBFI!Q1 z8U*eoJRIC#cno-mFee1qv!{QSr_sVQz!QZz32?3O{oolD{x`zF5d;Ho0pBW2QFE&; z?IU0=_L3h1FB5(Oyhiw0@cqJjzz+$(2xh;4VP6J6A^ZyXX?++w9A1ZEk2t&w=3*}c zd<f=ZFPYEm9pTTwpOfQJ^@6$Gm&`Yai@M}gFgqM%K1z>pH87i3+UHVUmBhgJo~MG* zfzP!z88safs4vWSmt#iSvr?)!ADuluj&f<w3W_I+ky$}ioR6Lk=GHFSXM=~3x%Qq1 z0~dJdz=XMwOKuF-TNS`;E!l3-{z5SKOpsfE?<6O%>xx(L99}9M2YZf9=!ZA+pfH4L zgxO`S*lWQ72ASg8DVz!3Et~~@SvVW~x^OP|UEzH2`@%KAC&>^S?Rmxvxe@r6C`0!S zh8R?rbSMKS2wwya3HJb35$+GJCd@Y?Pk1!Aw(t~iec@Zcjf8IlHy54{ZWW8?&x9Ak zaIrWja980~;9kOO!2N|E01pw~1inI;Z^T&P-QdZ>FM{<B2BgJ8JzMNg@O_;thHt@l z2>$}+R1Py2gNCMDm`fWgg#%!2d840n@J8WG@K)hm@MFT9-Ps|`EfUXy!wk%|wHL*K zv&pXtb8YQyVa_JMFU$exVd2)`&xG58*&$_|RCD@HcqsT6;Zfiilt}uyhPs#hWF-xg z;gBeN9XKRB9b83tAvi<099%?BiZ-teh51_QbI@TQ1h*9XTyT3~7Dm0}Aqn!Y1H)iC zAS7OWgCk5b--4@!Gr;48`4;FeZo^Lwn1gEiXFN9xvxF}YZVJ|CpTkdc@G`My0bf%Q zxD^cdi$fQ%KKmR2x`XxE=U}!G`s{P?P_RDx96ScB&proF1HUBk%mjZxMwcrE{E2Wi z@aMwe0vNs$Lv8RW;X?4Q!mN}W=&v!NmSB%?M{trbUrT+)Is6O(r;GhCaJKOE;2Ofy z!I*r++&co?07J1jEC=he%<=Gw!5wK2W{;)2@CD#L!W8L1;S0gTgjq9QDNN~(6=u_X zt*~Buy+I5VFFz^7#CQkug|7m0&_w&u;3dM>fmaF70k0RH3w}_z9Q?5G3h?8?tXKX? z=Gw~|81xnf@Mf^y!T{b1eoX>A0@hm?V80W5Q0$)te=PhO_?YmU;FH4dfWH?$0OqH; zcr#yv!!fR?;U^e4J4FYsMg@hv;L5_Ra59BMV7-L_{y9|R2bdU^l~0jyb#O!B9B?z? z0<hlA!2Um%vf7J75x9$RQ*dA5X5c}>W#Hk$t-x0aw*ik6?g*YN%!=rG;r`&+!o$IH z^<nJD^%xlDi^D|lBH`&^4uE-QoQ7K?d<S^F@JjG@a;0dyzEij+B)VIeZ`RAg^}u?^ z1N_%V{bRf<4h_H`2(#_~M3^P{bK$PwuY`MmPYL${|0>)M>~Kdj#J(htcVgyPXCw)a z09OL*!+5WN0Y@=uPgjGpgjuoZtq=%24qRXCr-GXa&j#}(IVLa%+)0>kK@Z_u!F`4A z1P>Kni1ee|91wUt95|Q6h}c7&CcF_mQ+O*_pM4HLJHQLYeh-*4Weoc=m<tQ!H^7{5 zA-@gYAbcFWMRPG)EEpaW2Tnro5O#o{6=n&4UbwQU#!Lych%~>;|CG%oo0WbZg4uZ$ zF0<7#UZ$%raj`z=t;$yWxrB84YS@lZ2YK0~>aM}Xp~ARW-}F=a*7&im)L&(;g<qE% zz1F|X+IN{sS_k7+HE^AOlG$6mwGLq>tGs)0S*<4B>#u3;b*pbmJy~W@J$J7^FK${> z6cdm7=3al6b$J`LqXg>!b=Lcn%&DsRdQ4YrRwH<+rEcfNuOhr`R|k11Q_lNvS+45h z5_|MM)P!p9Nl!?PxzC?e@$Kv)RaTOa98*}o;ez*b^3BZ13-|d0j_{=p4Bn4Hh=VNr zJLhMyMm_W8?A#bM{FbvXE@u~`I3UBy62E_i#V8hTEJiJZu(25R056VME(l{Wid{Or z7{vj^nJ;H!!*v)Y7Ahwj5i2$pzGFHNdoaQ1Vw8z2$^sP2WsK``{&zU;)+sqS+;H)% zMJzyl1{b%D{5Xmq03x1`=+NjDpodF6Sb(A*EI`eNgZBo$RV*IyY#S`Yx*E1|10IFJ z)exCUaz4h&!p-ieb2|}>73Aouj(a97oV!=jyFSv;`2yMF_9F|<ee8?IyMMJ**(QIb zFhBL>e2;egP&8}T1c#^i5Uz=DB2^>t6dy%mC;Yb(hrv1~k<&E}e2)_OPHe`UCB}oD ziCe&~!~k5~i60_bkHLdB4Tozi?!idpbc2zo=YSGf5nD#m!(2~uxXL*}pZGTHjKs(B zj|)5*u=0I@7+bm=W+ASA-mS}N(y!rXt?P<6*}Zl6e_+D4Hn;-#F0?B_bG*M39Wr(B zBtLh0yK>D-U>Edr;mlRjoZAGZ6#qU%<0>^Dgdxq3*Vk~#0*@bgF<h<8Z{d>dXKn40 zFGc&0In?bB`BU<FIHv0oGZwKI`#)gVUM9ua*#9eC`e;KFe<QW`A*}H<V<v`ayXKfx zgkggD0wOOntTg4=j5VIds$jFf*xF^Pft&r+t4@Za>&?gTKhCiO|0~gVNDINrRLeH| z2Usf&b$YWuxiL$a**IFla90$b*_c|ptoT#g<Dc1-MUJl!Vw(gPC&iq6nd-8|pOQf_ zn*AAm3I0;K-e?Y_@ktsJ)toJuA2-y!Tl~4Et@ds~{ypmW7Jn5}Dfd?Yh4_5+#asOy zs?<fqW))6@>7gMjOtYN5*eqLZ-s-Ole;;o3Pp`6s33$)=OV<95Mg3j(uz!p>MSbzG zzf$$}ysx@Bh&4Lrntum<7M`^zs2|CD#9!uea*${lHUIWBC_h12HIns|zqKQ7{J_CO zhmKP#wz~2o-#?8i@qA}TBU#V-^W0{AwXbck%7Vq!Dn+i{>u-}BZiuH`F&oNv)x;h0 z_bD0OCjO>V6liMsTTe#2z~3f{(i3HlmN*B<A4f$M+({T-jUK{GqHmNj8iHYvIB+n+ zUJ3*A<>b08*#{mcjD}5*oM@j8zFzFJ!Lx<yf^QP82fl}lRCy08gc<)jJsS##APlU1 z>4{Hzi*PEKi<Pv`1wSQR2!39;KA8GE^ivAvZWMAO@O#3|z^t`sUk3h$4C!(wjPauw zm>3F(c1Q!p31@++=)(ZKOIDO*W++9NU9WWE+Td(qW}=306L6t0GgJx=GolM&XethE zz+7vieLFDM^vGSoTo@zw0P{;<<ep$^Pmue92MG@b4;Q`yJXUxjc(O2NOv47Yqv*hM z;c%PqBJe`trQpTFtHH~K*MrvzKM39+{1AAvFx#XjgtvqB3@b9a6a1>Shx~WL@V0n* z9{j#AtKGxG$HAWop8!*5f_MBC_&Z_N_Ig$o_P>B*@TSlYdsQA`?&V4n=9r_3o(+X3 zwozH)5CrE7r-JJU=YUIuIkUlSGfbc+_#$DpdmV)f!R!*yPYIYE5i*rc1__6|!Z2J6 z-N9_k>FE;i1mVlTtm$dbnT=b>c$fH2vr9mRQ}jF+Fkfj_pS1UaR|xYp-b#iCI2mX+ zFd7!a4sl?8!YwhhuL6EixGMNn;S4aBTIr`6_<iB(;KRZ>;Ln8fz-%z+zXn*J=K?N7 z`q9rz!cYVUeTWOVEjSIg#{liYxx(yb6$*C-Hx}*&ZYewntY<?J_HuAHv7ZIz!X4wB z3m!n`r-|mlFjO4=0jA~(J>3oFRu=Ml@KoUq;OW9F?KcW<1<w<H1gvLC5teU(o+Sl8 z30^9Go(2!r)1+|N4Fk8nFtO*s+~UGXXg;TZp2N=x^SQnx%&PP?;Uq8>P8ik?elL=I z-2aQitRD$|<$u6}YTVP`phJJT3Ve&Pz^NQH^jkd!*a9PZ>M`GO6p^obeCL1GOjA|9 zhwTn^<@Xp7%u^rHv|ZIdg-dTW>y*D{?uSUK;)jx{f2<#AT^2PON1LeEPx*6eEK9+P zC|Zq*AN}*M4*c`VN}az0Rii_R#y|LztS_o+Z8m>9@f7uf5|OUD3=dXPbKwcfaQFOx z!9*wZG%vH&F<k6<)v!4nq3R$=wFRdSREg`CjVUZ6s^zvr4f)Z3j+R?lFq9J0pi$|9 zgE@KTyvSQW`U~B0`s@f(*^WS3_%f7Vj3%DJ<?LvJ%YPV6@N8m?CV0||^(B%#b8<Y} zE(|QFH-mu%>vaq)W<fZ5V8Qu1gyz=>&pA0h&ao0Xc3G2PEeFVBeI<<U4NJeZA92Y6 z@(YodSm!L-PNJ=AJP?Bn&htRajk;iNYQ5k@c@yp)HsNu_yWj~Sn!!_CqoY9Ycw`7C z%F_=986$8P@eWrBJHa+9X2X7us&!$zCxTpWSAx}bb}4w8odv(w+8yzKs?7<dDfVj! zHQBxiIh$m2KI<BL7F;LVOA%^<O~sb+_Q!A?XV-@7So>PILd%VZs<{U2MPl&|cb}b1 z`b+qQmRkny0$OfOQsA-3eiMPR?F-?ATetv$++#STLZJCvHMKe43N5!2a4~J}z=W1t z4|OOukbVINdG77hOEElri`-Am06IK8vBbT58#t=v=6-?f@nj;G?tL4<@t%iO)3`uU zcmM<2oABSXH^AAle+0+aa}c$|wh>XReGoQrHajIwI}dqx*__mL+x&zJ^xINk<!Lw? zo)S4%=<tqZ8)tKl*|7Bi$Tqd;px@?10Ef5y7do#-0?=>k4qqJpuxU$r2<|Pt4l{_W zk2mLan)Gb=j>5(pZ?a8u_}Kn>ZEeu{ZQcaU@xD|<=FQZ>lYCsA^X8gdX$tx{E9b3g zvK~x<IxP&P<^mYPX}<c5O^%KC@goV|3jMZ5bdh7@eTx}g2a|#<^j|$;qT%hV4Mjc& zy;bPEt)ZcpRwHWc<E*8(k2W;%tz!h2nm-`brv6bAuQt2`po($K8Sp1XVCS7+a!sks zu-viAb_J@NPpf*aKrt$*;jTco`I@@L6_^^HhrB1nx97TvhZ2hKK*Ryn_!r;lDE>P< z8Hgvo3m>z~^9n=~-;M0{aN;z+hb{^U6UPrT;(O|%0O@nR$o)Msh=b~9GHSk8cIhqz z!-HeHXkRdre)?UE`*S5+{5(B<i1-pZFb;g<fZUO6dK$xjLMNtUdE$_MLTAS5FjDU0 z!_G7L8sc<ljIsE@VZmpdnq{dE+<{6Zy%E~1Vd~pTOGC6~#4?NMI}6@mpiAl$rWCPs z;we8lRZUMI$EIw}qZSthQy)_OJ%POZ<BaVG3-z?Y-jrF+4_jvFbbqjP*@A5b(%#?+ z)H1uOcRYb~^9Oax6Zj}^JG1+u)}QLA!?r;wf?sXRT#UhuWIUj(_(0RZb-bx@Y^&Ht zndMM|QeEQ%$@x01<xJ`$cq!DuS28p;MRM3H=U?G6bw_-l%zQ?@5+4Zqbf6s!)DwRQ zq`r$sk@!qiwgY)-d^+a4yiK!viH`69BQ(1irI)Dw@R6Z?d_x~^MZ?4OJNn^!R`{`6 zWd|BUuls-<NQtI3ooR7ZooU4;1e#l3OSMi26xGv0ZJ|{|Ip(j{m5-#ANjcV|S*PDx zKQH!IsvT7869Q?NzI!$yFrz7_Z_K0mk#j`Efwo!BgASt4;HZA~D-bSYI;DM7r^8+V z;#IQ}1Gm?_oc90JF|d%cK`_hbF$R9704}`CcEF73>Vl*|2J{2_Ck1kw_JB1s)>zp1 zRH7-*vMW+<tDiorf@sQZb+Ji7Vodp|q`>3mUUjW6km}RP<Y;Gp7zN3!@#$oq@de7d zvqx(#wanrK7CNT6RL2}GtxI)jH5ziHX3n;F1H<$UaHn%M?fpjWohp>g;i6OT?GJPc z<l}*uSMrUH&H|JaIn*|PpjG8<NYOdgbR+8*{fY#=i?k41B*dtcK%hz2<*;)nnQRuO zC8F|U(-Y*|7-V~5v}g-=Uwc|`e{ZmyE;Jb}sj%$M()AU0@&<Lw(&`trIuOXT>cm8z z4FqCs7thqOjMo1}hpEoU3RH5R@3h4kr7mw|Tg^b&5xKiC@NJWDcZwS#<*x^yDc*Jd zILTKrBf*m(D|EQnu2kr7O(x@k@~59EgvVb$#8;uW^&FX11AaV<%?w1j5nrbY9j@1D z2t^%+Ap>TmC?6$r76CuD*qo_gl{QqkGWZH%j%vmTXM(R0&H_&p&I8XBE&$)ec}Ygf zfxaFxgNwm>$P8`()<b4+Bk*zw%p$9Y%&>0*)<b4+2e2M8gFAsA75^O7JSp4@yi2$b z(l?$L1Ly15&1HthfZr6J3_c*t<&zJEr-6?OGoCMmXMn#Eo(*QthH>5vHt;CPD}iy~ zFb!*9h!=--V88HsaEkB-aJukjaJKLsa1G%X!Fmc8alQ<u4lv_?1+0hI;7`GNhz<Un zvle{$=;<psbP)a#Jdlj%&+<4-m=)R>VV0vw!l~fvgxRXh63zhMESv?tT{s7PmuATA z0vPTQhvwjlG4@4Zc3zl?mSC-+1m-h-lJ*#vF+;n~;oZV4r2EP7>;M>A3zE#S-Vw1! zm24c>vlejRoAb3eaB$B#S_a@taax!!0-GY*^De!@yi1>OHE^<Ub#PVTTHrk4Qm|G~ zLOkJyFw_$VPHXA0H?jsRqdo1xZg3Z2-a$`c-a&;{5?}G*V$aN7C7cc(Bh1XrB1@fd zvpzpn47ZB|3afFKFp7n-Oc<Fp)(A7mdSOaSD<46GEGs){52oa_@)4NjLn|MFnK`X| z1kUEHh1NcTAr}rGNZ>l)W5R{t?}UrM26Dv&SWkF_Dbk=YC7LcwiRKG)qOeH#LNL1s zex3x~5{72t&>F1ILxp`?aC@=u2<{@>72HGk5-^8(R3hQsbNou?qZu#ELOMm5k0~t7 zj!F0iF;GOe2vbD!g|opN%rH_)Xo+x5@G4<SiyKJjhthgbxCH#LFeUN0FmFtspX!7B z+r#iG9gsC9{I)PluT~m@JrmYSLtrMRm4?7YV68L+rr5R85V$dzYU_-X)iZa)kb8n% z!mMor`utQljDexDINS)%6kZI@6<!ABej`S-8qB^qc`aBg5P=^6UnKUAg7rD6uzw7! zm4?9o1nXl`!Ed1aMbAlv;cf6B3H&a2xbPA1Rl=-3#|fVTPZs_ae7!KIVDveuh?DwX z9I7*;abSH+DwtEI3t=CogAayv^n^N<g+iZ=3a$d)BKDc!ZNmBBr-bW)pAl{ZenGf7 zn1e9Jc`^7c;ZEQWg}Wnt<5My8h65)G7@$8`pN9$_4%X+Pf+v72XVlM3us#nJ_Oro> zVm}8Q6228&MfeVIHQ`0zJk5F09x`VznD9zC)Dz}2Zb^nn;?)b&+||Qbu<9pPd;u;K zt`ELkm{q|j;fCM|!Yq?hg`0w>3$t3dQTRgeJmHq$JB9g<Ky?UHyvR!j7*>lz7w~<; ztO_;>4+dB03k?JB6#Eh2-NK{5FAB5#YqcQMnn_@-76fLKqt$}IX{;=@UJwk~aL{@| z;M!oV7X&T=YqcOSUwM9Tkskza15Om?-Bc3h4WtQQ0?rcd3+84JhP@12m&~t^^A1YH z;VN(w;mP0&g|7p1%*wzwf;$Q?1a}v{8_dm~^s^M)UwAoKpLkjcPaUjJJO!h07-4<n zDGVtv%wzyC%Y;7h6wETAPdo*)Oe_>XrQpTFEECIxStiyBvrKR=1LG_MKPucB{A85F zdhKYJIPfLm{!#{@h~5+)3O*oA34I{U=lwMq50!WJ!#R9f7_E*Gi{_qwSQ&eT)4@J{ z*eD#T!H_Htx{o283;XKA`QQR!mXEr^Mc@))-n~8v6>;+JFBJQB;5Nb?z+HuVGtypS zU;(*In35PNJP>?!WCWCKZ0xhX|Hc4!ZvTXf^?57RVNQS_yS--)Y^SMXxLCVdtEM*v zI$1|st9iI$pZNZpVEtknRqJM0Z)m5c@w%hEdJ$L5N>!N)=M5dyRdcoP$L9u?nVIU+ zTM*?<>i$~-laOrnc`#k2#^Yk`9<6rG3)ILNhYVKyP~Ykw2hk2tS=4AuR)Jdsd9icq zqD4{7Zw*wpo@x-CL7#eSAjx{AL39S4J<*CN7}DKPEid&{QqRK^?sh-oFvqHx+X8vk zsq0m(+XA_EOH?z<kyI;qFII^+c++Ap!h|o>k+4xbcK2*FOHrkr?Y9NaQQFzz@+Lb< z3yT_ZGTr)lRwU*2z=O`X=5gq;nChi}U^bnrO_)uehRDy(rWaaldR!T}XUwM0MlA!~ z9L|_v3VlAZjwy7`y<!TT{Qy0MJ{m<3L1y6c2OGs-Vk*&T^XnLCR5u4RRcAJemmmY8 zr&F6gD)e-|)&|F2=&ie-MVb{G#qUKn&TJH?wwY`cU%(8V*(lCaw$E%7=TOD4`ND?n zSqO2xJ(mN>>+Gg5OtaZ+UTeRO|5NQcNN$SV1?f$;3y`x(_D=Y@#^%<giFPU?nqUt{ zMC0uN_&?63dfZr>Z55`_x%v>@DDGy{2{oXfkXg?M_~+bCG(6OB)@ncwOneSh)lU18 z6ILSDip|__%VzF1ivm@`+mH>zt`BF^z66=E>`~wt`*DiE=BEZ@ZB7`**?c9P_ASV~ z%iaikw>=Gc@feBa$RBoaa}B~~8(`SI@ZYpg!2&bfRJO+s?%8yvdWvDULugKL&*d43 zNuR)-JGeQ{^6@^fgPWcWUk+~M%nt4{IRD`e?!EAf9o!6_<jcY>U<Wq~UeL$mbg_e* ziaRO3H;^an;I0f0X}%Q<L;ao%!^rdna0A%EJqS+OzIAk}*umX|JGcvYXV}5bp-QnY zlliFF!TmNvR_x$z>rfes138JY%=QGc6yD1WYpLqK7<1Jt)#SyPx!$cFplP#ubunhH zIfakU?{37!!!qY7-G=*y)HvYrT)?4@y9@Fi^t9t3!1F4S^IW`$UOX?6JCaS$7Tl<( z^D2f+7&vmM;ps|tcxocAp6=v0kAYly^zLaFe1k7t1RG3&cT}(36G(19mhOX?l_bMm z9bQtrSF*f&sIlQ4rJsoBFeKp}Lw0!H$5Zr<rx%x}8hI)ciuaVOqVhoX@MVa}5#L}h z-0i2pSlr=bx8Fy;Ejs{?vDt7s>|c<}SUdpSXp-HYM-%AcY<D0+49JV!={<V&a3hA@ zg*WZ;u+g-;k=>r-h}7=E^gVhS-|neiFAt=K%XzD|J}|&8Ls;n1)kdTV4Qt@PyDI*< z5=-XOhM$d1EM*LahoVSqK(_RW2#F2J4o^?Sme`0KXC(fBBppf3xFm1ih^(aA)R}$S zu)jv=U51?q&;6e<>`A!pGi+*p{AAb%;CQoX--b{tOxq2)tTgS;uzVcb#3ATcVr<U8 z?oY5g$6!LFz~*B7mS^xZ_+-q!4t5DmD#53IqV_BabnG`19!%<SF(;S?o{3B5ZbW5H z;&Z|Tc(oT`WiF<PZ9Ch2vz%w%XYoeO#azGd2+Qhx6U`;`$NqqkeL#&{8feg!9X|68 z2cPs8u+G)q<~wxkNGEp+-S2d)f?Efgy^LmoHV>kC9J6tk&N<bHa$i(GE)Arm{e#xu zIrv~-hqaN9KWI+FL(my1S{8W1G)Jft%L5J2UgfU{)D5$<X*P@F6X$$wO`VTsam>e~ zG!LO9n#ElM_qS<2iMY(>am?2#m~-`gTom`T7t%x)Yu$n;Xts!B2KdRmd}d%h9CPX0 z?5qRwG>hCfnA5K6%@u+B%pPjSN}Z)`D+6^e)LBZ=S-KjsjAkiCXX!SYb(T_emN*cK zW+_$2{4vbAqg25v#CC%k%*$AH_o_f$pN`a{BYgt5T=Nt4&Z@v*e7UsAYVB$K>IzRq z+S4lBCp>Lg4Nn)V&>HQj<C+RjKWb0+;bwC`QMaxMwDI%Ear0`*B|42>XNme`O`vr> zR&cRn@u)FWzXsWJFVYop;UM^Qmus$fKf-#avo<QK?o|EPVg+WCnz1$zYJ+#!@DF0F z-=M1)BpAg*5sfq1^kU!;Wa|{QE*cKMf%f#0Lznpgap|qzTN_BNG7cURnzTb`erz-v zln>gd|FQC|3si3L7BU%J#c%PR<5<Ea+EB;k|6<D(`1mf5{EKZ^jY33eGnm6PeG<aw zXMAi#N=C^}wR&BkF#QmcVxek`DU2W?n%~j%)8MYiSL*_y1Sj{aSjMCOmfB%mRq&j* zYUJc2f$7fkowARNeKIgKE_Teg(Gy0iLoX&=9J%qCK&__XXCQ%!IeV&TRA?6#kWmKs zqk>k&{Jk#gDD?dCgpP{&drlZs%-?hTU$F;!9~pAuZy(a)^eoDs@n)36dbaX_I6z>= zhr$@08b^gODlxtg=I}u)>LH?PV6CSI&IUuGI)NI%IN?IDN4NxBl?>tIAsN;5oV^%| z>3}<Co!9&vZY|6ij1Iy~tebEixVLZtST8Oho|@pHV$Wd<SN9n|Go%+3z>U!5i>@fZ zZ~=IZcxnaKiwLl93%*<IS??|v?hMuo2k_Gk%w8}P=mUO4xIcKi@YUcQ!Yr1rfy116 z?gzs=bN~+qQ(1vL1pKk^mEdE-tnE(<j{$!#JRZz7P==idj){r#WUyO!Iyg~yHs@?Y zVweYqD#A;_)r6OW^MqG|YYX2CZYaDN++27&xV`X8;I6{^z!f`~-vsy9_K^Q!7+CKz z*FS(q3jYiqEqoe0Q8*R_@mgW-N}3^@44xxg8GNfS6$BRu=Y#JS=Bc8q^_)Ett`CD= z6aY5@KO&ymfVT^G1@9E@1Fl#g7y^D-?5Ugkx-d5oy(>H!{IT#%@aMu|D(8MBhI!yq z!d&y!3VF!TBCrGR3njD_oFM!tI7RqraJujd;A~;O=QV`i0T&7%1Ea@_X(&W`9EPUi z@Fn;nVJ^0^>82mP^PPmb|AA}Mv_B2*E6n$ty>i+of%PH+I1Q{95x^zjapI?p@Bd^m z@IAj?n1ij^!ac!rg$IGz+%W;Z+y4-z9&NesMDSYS$>2@GY>plgo(I+o4gBWCoiOYa zhjOr9X@EW7?U%)VBUrCAz<x7WFEoI+f<F*HeCIzA<}mGZ;m5%zgr5M%ptj_9@Ul^; z!(0NVf&IipVOBDF%QNh|fc2JVaCdMu@xv)^z2zD9!@%rmGoF#)`oiov>MhT(p8(cd zp23sAt)hOy`p99u<rxk$;m}nAbAnB8d4~NxV7=uTya_x+{P4XWDZCRrT6h<DqVTg| zs*^EuyTLPrUjWb1`>x^eG7Pth!^dFuT^Zm6_-^5E!OMiH6t_m0n#A`Db6Wf%;Y4sm z*bja}I0gK)aAp{WJz~fLbNIuAsXhFLFzbf>!VSQOgf9Xg5$+8>F3e8!*TSqDeia@L z=2(;QUk>Jn-NH1Cg25*aH-M9cx$}Ty9{RZxTwQn}m;)l(vp%RNOufev;XPozVqr&{ zTD@WcM*9?9u>fPPE^G{B02or?pjRotY-;r?1vnF|S1G_*V0JX=zYxp~B3uAO;Wlm; zMr&@|C0rSNk8m1znK0woOy-&A4E(4zM2AFA3N!F7VFunU%)tA}NztCnAz^f4jU&SB z$Q&2OT^bzY(Ldw)K{x|^nnPAP<iik)tdonuUSYQViIEoGV1@_BMGgrCJDYc?Exg>T zVk+S>Pj%;It6Ig&2K6;A);Aqg%j94u93r$J8MaN;N6EouI8bs{3QQ^LwUpo_>+ON6 zLn{1~se4jko2`ze25VvuUvlMOb;R1FaxgD8rw&A;M!?2;uc4ki^zX5vQbNA;@5_eK zb0vSgK0YZfuMvAIDk&VFW#+4xD#5&x(Xg685z7z7LjOKOJhU#08jXe1qW;)LtFIED zu&P*xFHqB}1asqBUc`+rQ3YL>dZ9}2Tm{{dgcNL_skSm$fL(*l(}Ee^b%?=a?U7}u zdd(B6j9{C1b~=%79Oef3B4IjFPawMRg23c*UdM|gwmsb(&U>PlD`{zBLl>TqV<rr7 zx^Lrf+(LJkgZlYUkR7h-mL^m;`>MpM!8@JH;m<M_FUUL?`a5SUsb9(x+MjQiUS(|z z7N~pEgKw)>?+i9nU1CFh)v|-ZEvoO=L0_anwcza*_Fgr=H8=^|IqNpU-nG^0_FEIG z$L3k+dZ?#9!gGBgMxAhabFKGc)V@a8>XxFyw*~X8qYhP=6U;?<*n3+rMUBo0`p#~@ zENtLRj%iS@NN>N~9(f@rcyElg%u*8zg4Nr#KnLQiv{`LHc#q;yL)vVGFnP;92c*qi z5s)@}2$1#{2&X4+S!W{19(AZ7Sgj_fhh>J=2_G^m%SG5Tv$9jP!Ldixt`V#n=CZ1z z(W{WZ_kBj0p!bC00c}R&oPM2*^z0Up0Q8uVRM>8X5ZCJo%<F7cgVSs__t)C@;r~>v zoIJ%|ia?X?pAc%2*5bX!J_6T?b~V^cu-77<@%DrGKd!&cMd7jbvv9`r>rrGOZooDq z#&bG1FlkP}K!f=p7#hse;jhTP8)35TF^B-gMk}X{nFV(q)488v*osb%wY#X?n!yHk z8NyVY#@Rq!Q4=rhc-6cK&e>X1GZ<*H0tsM)<Tzx_=Ba#!JqN)#fy(YkQVv3MgCvz% ze7)d~4U+V0_%I>)b<JRQ!A0<nEs*q(<fHZv%Ed+)f<D%bC`KQ_km9QztIBExi!3`v zO~5sAJRK`0H!H`ehie6M5(|+U_A9bGSY}vb)u*+B+2)Tbp?0v?{9d)F9n7{ov1(-P z;5@q{!n@mWy2kXZQC6K`^)NgB4o`#c5!z<|8%HkkR%}iaSaw@*jLq?y!=~~QCI#m+ zfVU(GE}oXSH*e`iIKy*KICw8$L~g1N1-<Q-)6W1z<dqrHK4h68<u~NLoz?0(!SrS| z5y&eup(Tvw(&!{&2D$$##O~44f!={kHr_Ls{s)mUGaCL!-C*_959l!dTl{x<dXi=C zbBJmRXERj|svFE|N&%QX^wdHX9QfGNq(WU9dsAjF^9neoac<S@V~!!0)4s3ClAf01 zP*2tkCY!_6n{|VotTczpEezIlcVmQUW>z27w=lThsvoNw)C=x1H$;A}7aU>QKQbrN zDTn%AhZ<8qm~MR?tL~^DEHz(N&(#k$sX~3E1U>Ka1Uj4N%)6BAQ&o$DMex_97!UMr zHL*BY*W4FbQyiQa>s*RpmND$#n%rm{`KobnM(p`kg5Gv5I(8Y@@{(=?yLVGb9h|iy z_mu@JTala=!Mjt#T89_+#~(+pCIrGCHH|qFQ3mFVMs5YZS(wf4?ZWNBcL{d@vss}3 zZr~Ndmw?v^_X6`d!B1FkzS|-W{ot@ocp&&G;lbc%gol7Rd}0FZO1~mJ4*ZrdyV80K zBmA(%`bg|=2Y)Ke9`iR9r^>B{fs<*BbS>C~B*+`UPGMG2Ty3HKOW=U;8{kyo{a|kX zrJtkV9N}Z&n!?|K`JpZPvDnr&5Cglw7YJv7Sp(A(hs5oKYk@lpHwIrK+!lPPFdOH= z!k2<a2oC^XEzBP9c(B$;Wbby0IE)2{g{OjV5N0>v4q^6gmGD2nON5t$R|&J%yIz=& z^g&_vdLI_v%Tt9o_TpW>4u@xjIotJ;Fk1o6!_d#iU_A{3{u!*NVZeU4v%5q;m2v%! zjDnm3QU5HQ3AXUo(LM|8(v041HVg^kPyh}J*8*1-Mla9cG8F?i0Otxf2iFpA2`&<D z4c1dH@Xt4;nb>y(w-oLIZm(xI;EAtF7jftTW@XI8dV~834**{#JQRGn@KxYZ!t=mf z=Vn+1o+`W;JY9GR_(tJ^RWQsG!&>m2!jFOVJPab*2VN36I4F29#(Y#gH58rUa+Np? zmqltIFCEl_!_Z;gSETZX>rVBg;jrzYo*Rx1^GfygaCD;%m#UNz!Cahci|3|VjDXe2 z^yqT?^&^5wW{kRhL@>{6q9VK`se`;+teltQlCSFWQm%U8Vjaj*(=SJ_cXCs_Bc|GS z(i2oWE)SlwkdD(Y{-w|BnS*;UlTl_u3%VQ$g*kA;I{IK-&UVEn(9(4A9Ya^_MqbWz ze8(U>x?;^~>2NNIUid^1fG^^2JHFF(SO?!q^sD$1Iv<B$S1JFYAFs+v6Z~f9|Ewo` ze0}JG^KAs!6W*qrR|VTgHeVGy5%cH0-nG$Q?@Q9_J@~s`Zx^SxlKP_5nPdgy)EzDu z+K&tR&-Q&q_`Z6s0z5H2;NV!pya`gM7;tcM?yTH7{D2s<d9h--qIFj8GT_jI5r=az z-5gFCa1_DxTe-96iUCI%FDB0S)&q_<|CyNo?ttS91qs)U47(=yOpNujLzUecyas2; z{OjmqRaDN;i<}RLoP*KP#bJj!(Iz1m?|~j&ymsxmql-V2Fr``{;VZ#sC9Gw7M#8%A zpDEdYPr`HmD<pjLqd{-%s9_UI>nQW)goO*zk8M)T9t-*-*)xK-S^qOqudMpt5KR1C zxjuIwt;_YfQfEtgR_Ze-t20txpe2VEibb?yAT8xu>XSb$*SG%HNL`({Dd>sB+?>$D zj4YiST>cm1=ku>gqJ!vvowO)Y7dG+~pp7|Ohp-n?QNsV-I)wGme|;Si!F<Ju80(Z& zAI9&hj}_7CW4BZv@BXg($ZU);X}lW!Bqk@WT=cu@<F~?H&I+29XPxMbkU31vUl|N` zE2ONfST1#(t&(qM33kM`h{|zM^fHN-rmGoDzpawBxLuA8^k!NEqg8VE|F}x-`FC2r zFCv$f2M_<p;<VzW!TVyx?;5<nB~K2V{!E^C|8L~U0T`ON|GV;3kZ09M%-Y~{e<jqF z(K5P6%IN;zmC+A2g>ugbb=>{G6Y3vKTe9n3^0%ig?}!%J-%eXzA1$)~=cX-H;>KX$ zZ<X6WoVI*!)BoJG<>{@zs~PI6-*w&2ZQ}l)?^yU1TDLpdrHG(QvHX9cH-Sp{JQ_E4 z($1%Gi*~{OxFf-#`G0@oHg4x%H*QO!6~`{AINp?sBPrT9{vg^nK2vdccAu>{>ht8o z6!W*WvF@gEuuvi05#Y1kG){Az?WWD6>0dj?tRo;+PIjD?E=L)^ZR?^#Mn@-lGp)hV zw(gSuxUKtJ>mARjQ7;5bbj1<DdPjyCx%8#rE!JOjC6+~{{j5m)?cYhe%PUyt&|Qhj z$s>mk9y7Ae=(?Hw)hlUKR9wG)y@n$8Kd3tXzv;0>CBFHM;P$^7^(~Le`Z<yHJHKlZ z&y21y^gI3T*=pkt3-)rfU?v9*6$N`3O5WLmtw+PAOFD7Ctu}t!iIZyMPdjnZ^{D^x zPRDr{Y&QyB-3dd+j2xpfHU>|gZ5AWT4+gvaRUhQMsuC&OYRTcV1HL~O_@DQaqwAd& zHS=#p%n5ST9e*m~8|eOjyI&W%^XOmqlb1%z?=w<<-}+r$q1Qy?qq7znU!3h+{E;{V zD_DN1%1{@7{8{;GY+5idf{GYt%kdP7#&p%=#ftr{kmn*41|wX_f^<d5lWA$XI9d1G z3R;BRQAcPEidN7){^JU|h1z-|82mSTb_=Q=dnkhSX!JDxe7JXBazE1|uKfNFTErC} zIt!p0adt3$?u6VBNaU=*uhH_Un2@7}-S1jN4)h@KJENCBow%5(!#eadhiUbX3cTxo zEb#NLI5_Y5qVoO}tfkQDD2V*?r{Kde)`{q_+By}h3LCj<oV)0MPqcvVlmh;`6!7?H z*W-Xgaa?UVWFVMshR)1<{$UAUiIS*Gcp-p4s~}p!|F8?fJ_<_sZ@VD3AQVdYZ@VB< zXlc6sk99#%!ec_AzhA=H1-b99>gV(Ad?ezWIkn0YI-_Lq|G2mt+W)S&tC*256GONE zRc-P&gnnk+0(tYOzmihDJJIYCnH3D>JL6t)V5^I%9;y;b3l~8p3yUf|r}1oEa*}1* zbWvRkMSCzV)}>fuI&;(?*Jd#v8tq!gay=i_3e`olstXln5n8#RB;w$LmXj5}#m&lc z#-9rzqDTCNtvB7^=w`*%2q<U#ZAJ=b&iLcE1JKM~g#=umBP#a{{6pM_@ZWPS;=-YS zUIg%RfjX}E3A!2<_j<%N`U)7|79kzZ(h@k^?Xcu;*dHRPIJ=hvYl(G?gt>6Xp@577 zV*qNbSwpaf=9)^~?}R3}byroB>`7-H+&=cLyvyOm?QaV-yxjWb4p3>zVR&vt$}V?< z_4M>35^^`B9;)G;iKN|)$POd^K^PpKaI+NTU+<VqwQol_Y@LdS2W*|<re5rvs^rx> zr>KU4om0=_f}K-WB8%8LbrLzl&MB(fVdvBd#DtwwkHQT*r`o^`JEwT+(3WSQZU_Al zs^QxUaR-Kd2>A`$2e@JRdOIKX*V)%2y=nG*#C5H`6aS~$FCmLl^lrt;c4Ndd$>xr@ zYwS#<FwuS)p(fZTz~gQ14IgLo0|R62dyz17gziB)-T}Ljm~|4d#b3%Nm*}wjaKYH- z7HX&q^}7%T=nKt(k0Sd3V$ZgZAVvfVBfLF^%hU)o|62z78L2>Dh}xc}eJgBm;Nehp zb9yK}^(n~O-hMTbHoV_3<Wn<%4(}ngBR!OCFNTA?Zyl`Sz3bKC^iWZF6v7*J9{!m& zzx`y{!{I5$Zi3Jbn=9L~_958B*~ReVw1?q2xa=VE?Y6mO>@nhhfx(eD_B}?<LzxV_ zIr47W4<Kp_<&z3UP8Ps82lc?5EPvJ;prnq!s=G2mb?fniulY$`KSTQ70)$QKPCtfs z8SJC%@KV<(sXO!T@^(<)W`wGTdACWus>1=dL$7`4oaFt5_Lpu3`@P(*66K(md(M*v zF()bB8n}<7A@rZ-rJ8ioFmhGzy~uRZD4wvB={?CL$IO6zHXei%N>n4hg;kv6C;WFM zDU}%thN=7NGB=elj`72W80JIz#q+L!B+SiZyb9xxJD2%rCwTHM2AfY%g9y^&;Uk6S z^9Sj`1#j~OX2bB_i+|>eWYfC>j^;~b%R7g$zD$nsa`&>?a<5LpOGQ<4AKB$?M1F-F z@AV+7=Btc9$@?$^yhcv(HefDZCue$JR->w+4jd0dy!mk^LVHIr*b#2UidHA)r+gv~ z?;b|+In#F;fxZY}rdeh;gb22xOPbb+3*l?4>G~T5m6CVxrm`)1q2wrm6zbBMo*0wc zic&`oolL_zo;V(S6p6q<#X6(%dQ~|qRMoswHOvYXng38%W`*+1hH61pDBE129_8f? z^<Gw}g^v}Uxz%Ja3NGtKRj+y|9ZR@fs)x2>MkO{owBL%2iF}wH@|f6mdpswUV?L$= zxuFSp+&W;k&?nCoAgo#56(u99J&FNrDS+#NS-sW9+)y)Y+&`Why3QP}uFMOK?*2OO zW0yr~AQF9iI?grx!3o>F7H#mb5aCqRWQALBudt<G?82;@K;wZkL8Bh)<;JSo`JsZm z8z{6>ItuE6nB^xBMb?u{?v%xflX?~Dv(<I^p=&DhBR6KX7`}cXB$`LnW~faY)u$-C zAXK+fD)UpIWqQUf{Q=djAe5iSZBb^+7*@3$$C%|K5Hf2Q#n}>%Bzm$_)<LzRAe4gB z_a8%iR;p7SD+o0<2ddl}p&XxnWY@${Qf7CfUdU4YYJ>{>xx9rB7)5kjVNo5WYJ}<q zc#w$s)j9T`y43y}p;k7JPR6NytRYGctJ*a~mCajK+nPu)5UZxt3>5?#;=u%eu*(r= zY7&%Gj7Ce;!!_|F6V?8jC=8qaQ7aTm{|@DF2D~VE(JiE#0&`ErKclp_s$VNq9ZDa) zYK2-<8V0XPlUaWRQTW`<lu>ep+Ego4Id~NBN6?$V#4dzmL!-26jC#Ko%HyYzpKFDV zyInjA)iR#8)XCCN`rpt4&OZ;ozU>K(&%;~2dmRnbm>)dJ=hM4Iob@8d8-~iydt0GC z2{3}syPk-RoNOKH(>%P7<psr%zv_I#kRX5T>r`wORAdOBKZ`}yA7$>ItvJ+gB{>+i z|AiciGLKfOIMa_C4=T>|<7NXh1u9qk@swmUH5y<onZt1WsJCyXMVTM^GOI>;201;- zJP*gri1Ksf%qZ{2jZp=Q`937fJRK2ckmGtoAv|Tl@U=MPgMSdN0X{8U8|;CE7-=Ec zCtM$#EKHRey(<oW8iMQ49un;VE*9<uZY<oF_g^N4LEzTHmw`J74+VD<9uDp;JQ6%W zcmjB+FlTkN3KkOPOEOvPnHIH~nIXPU)U*oIa1#t#)e1ZpyhuFV3Z`x-{oDawExZ_f zpD<siO~OmTdM6zGZvg9^aA4~6J}rJ80q+rp5@R^}(N1{U1&24qff|hmgg*s;D0~Xc zCV?3;QKhkJA;*Ki5l#jFD4YdmMNU8Y;5gxi;CRiDNfQ|S;=pC(O2X~HJimjxS6C+a z%@cBMaEUOh*e1gDz!wU$9JCQ`3hpS}60CQ^A)Yqiz7-$jYzG4sk(mIsQ`uUR`+~0) zz6#7!zG=_rJw=$$yCNPA#cvS%nc!Q5=YjPxdkD+Nx03dFHNt$m?iE8dFwY^NLpFG; za4z^UVZISNglmDH73ST)D9ktFRpCb9w}n}4zb{+{KCCwsBC+-`u&c;~JAw7~H*gp5 zcVgcU%rOW3TmiQ6itz-qcyK@%)w+=?8~|qs^S#dzX0=gMIG^=TT`|;w16ApH7+4{g zV=HnAn4KIl-)VjR9=I`>{UzG-84nWXU2+3F?Jop#bVt4zJWiN5Ihh=WLmwEf7YDxg zvxTn&a{$M{)4_KL&jRa@e8T<?@M5tq2R}eYHO$AlMVOCun{YN*?`DG^KGyI{;=t$n zmT(bR?^=VW3&6+3zAgBqFdq#S<e69xFt<_gKrK8WgI%EtrtT*hPtC|7SBm;6h;mp5 zXi7tJ)S>Jg?oLL3iIGy>zk>B9G}xoMH-?ElUUB0}VU~%}!fdN%l2fDc+;k4#rVjyx z1NtHQOgwr@0529#EKo~@k-zBoHPJXRLlN2wKOxKv>F;a8o|)Jq_Kb6{FeUMtu%C7E zCp6%Jxxk+bGechqGw>;42L4qTj~|EWM8iU=(Qj%Z9tg&$B=(iTJW-tSvrJ?O^DW2+ zhv|?BLoIP&O~=8WA5AUqpp|eU_+nv-lxJeo4<5h4^MJ^d&}G6*c%(2B9xcqmI8nG3 z(l>a#2m=?xVICP-qa^eJc*2Xso{}gR=A(I#oDqE-51+&O{5#mg%6LlbSw3DRXGZ<= zG;e=q{ixx6alpkmEX)9(2~+G}2>Vqy%ay72&JH<Mdb#COr$LeXZV%-rSo>P4*O!Dk z;ae8fmxel<gVcCjtkvz*uB9QIDAryDm%%k#4Os^3O&!!$7_FN+D#vnMmv>Y>czv{^ zTFvXej_Mm;zv-x2u0Sws4_tvr+p3RnvC2EC;+3$irDm;!Z9nxIFViE{SA~*IYjtPU zbTwQH)h(+-ldJ>7lw%Ey4%K}P!tNNYR<8-w$oZQ0D?d}N5tMBf?=mruQD3hK<;6}# z1u<P^tPNGSek_S<O7~qGO0wchqX(0HfiM+OFl5V8m06rnN!>?J3#Y2>YoT59dZ{{$ zE6zvrt_$VaTbrPYM`33D(Ncfh!*LN>5i7cPu!EYlE_CjU-|yDaqk7a-K8os5>#1tX z*&h~Xr~Jmigh{((UaZ*Y5&-Hgm|V^=yf|WO(9Pi#Wv2nOG+jBc{Ox+pG<tJ6>hoe+ zt#SDyJ?h5)*?Pj?)uaAGrQ9F#QA?!mg8M%ktCdgdtb_9D=Nm$E|7zOxZ|Ot*FKH29 AHUIzs delta 211473 zcmdqK2b2}Xy7%4Hy(iD!>^*^Dh%?N<40(n)gn=RF93&?J5y>DTf}0?SiU@A86j1>= zDu{xB4gw-(k_woR;K2myQA`-{aP<BEtDg=1de6Dvxv%%G^{v}$_3mFi^;8aBU0v0C z>7fA+eLP@A`EXH#`i%;k78PY>6=d=7{$^!0ZP>K25oe7|v@G?3WmVhs-+G4sQx8uM zwyd)UE$f@_|3^->YE#(4&!0N&=kK<>r&GI&_3xkI|BCYefNuC-#MXCfiuGsCn3(Ua zf9DMUXG*c_)?5GTjB8TX`VZ&CkFB_Wb}p-I#r^X$>{@(0*^1-&Q{sQi8DH?B72j<5 zzj22D9i{(4o$$YiWx~4$t$*iCY#Oi<+dTB2pWl6KCE`qqfAl|`;eRIl53<D*tR&Bw zyx^eq-*krmOCI^}4p{%aXV~>H(5Si<Xt~J>bgKKW&&9D;VENsD`YhAxW9#x6_8R^T z4i5gw3XWO$|9pnN8)tdXu-6dflueVZ|IhQ+IabPl;Y?k=%lap0`2P~7RruISt2X({ zIexE|Hoc3LcGEE{ZSi0$ZTVR%?Y;?C+Pd>r+7r{Qv>m@$X?vGgY5Nncw4=+dw3B76 zv`<%CY3D0jX+N*G(p6<EJrUQm>i^=*{#O<ve{A*kt#K!8-Mgi#7&)3)R;RR7Ww)P8 zyv`qazudvd@Nze9UzeGnw%<|lakc%o^2^oTSxJ#i<@-e{CnRrgRk?ATU9VnbLA7d; z71a_Vk5(&)m-~IA$cNR+IZYckj4b#jPkp*QyLzugRT!CG@U(h6l3Q3c{<k>Ga^ih= zMS2w0QX3<43bWLf$ODBt)Y?d|`VG}Bk;U}~*uMD4>G}iJFOkL#)~l|O4;owtZr|`r zyHfo2!bbnFRqIH-qW<b|WO300cD49O)uz|-a%a<;>c+^<rgQ9Ie57HsJasZMv{`+1 zc>7(=YAIZHH}9qpLVWQhXm5{g`G`_eBb!=HqT9@p>v>sG(#)<Gzx{B@ZAyI+8PKMt zdM>h{%^Y=K<Wid!>fT7xwlmd$?N7DcUnc%of@Rs(1GXMDJuX#mogNd@a_o$$R=tT+ zt{ye9-t{xaPM=Zlno-wZJ$}^mG4*g>f9>Qc(d!6k7S(UuxSm|=OuXURse0X~ajlyD z3HQ@7RiU0z>Q89;{~m{Ff3;g}FYR}8nLiVe*6W?jNTV^&Z?7{p(lz|JjUir)WsVof zr~*7rk&%f!E|Qa7ZtMe>ak(!!=<)<|$mNI0DK2j%r@H(BIo)L&VX6!(Y)sW?DCb(V zA!oYWJr-Qv<-OzzF275z=<+Y*N-n1(@@ReLC?Z#J`8#s9%M0VdRbBoe9^tDT*N}+R zs$7>FkgK~ql$`JKcH~5g<W{MN50ViG5@;O}X6C&k%($K-Lr9&kg&Dr}ofxR(bD)H* zW@aP`GXsLcOlVo*EO15P9B@_PYT$g~JaAp%df<k_h2Uo3Fav7{Ly1@vgF6V9fV&BI z0{0Of3LYpt5<FaZG<b~g81Mw)ap0-KlfkouXCi!St{9jT3xyYgmkKWiFBiTQe2?&L z;MKx+fY%D&34T;~1$eXYec)}vtHC=BBh)o8>=lc(;8%nn1s@cC9DGFh3GjQuPl8Vg zZv}rWybb)h@J{e~;a%Vh!Y_k=4T}NKJEmr^I8Fg$QA@}lf|G?m0;dRn0xl=~8Mw0W zIdHD<*WjAMzkurs{|atRMl%lMYIPI?p7yM+!fe*V$<n?@d-!@X+B)KA-6YH=zCgGv z_*P+7<U55~!6U+KP}+y`r$+@aJWdPgG<K8WV?5+9diZtWB*@<oX8eu{GvH6j=w#^j zOAmi5Ot(J?2igDpDh4|Cqiv^TxQ<hW{g7u0Gc}cj*|ZAC5W)+qu`t_xGhwEu2N@k& zF1WvNZSW9s7#2+ZXt8Jx9xq%1o-EuMJX5$Ic#iM@@O<Hc;3dLCz{`Y3g6|e)Q@l_3 zT5$LwF|b{35S|L&Bs>HBwD4^3PT@J=7lhe#4+t*+za@MR_+8<Lz$b;*f<JOOY&`<Q zIkET)_-kQIIaogkZw6l!-U0qycsDpE*3I76z)8Y~z#-u`!5P9w!IgyBI&xwWb(YO{ zFw_u>AHns6e+D-az6fqE{C99`;aFu^?S<381IgvxIy77ub=(>w%p2eY;S6ToR52hP z)+}K*mAS&ap)C~70xuQL0WTM>2EIp_6?3(4P4HS_R=P)p>w-6f!;EQb7`BN;7x1&f z-M|OP72F#BhKJ9P5lhzmv%;+TUkRsyzZK2`J8{s*-HZAO!su_pmR}5P$5~_~mrB)z z>1l0YdRicy1#U~OVp)`T7S0Cu6gEvxxH05Ign5%2Wf=L-R9+(%J;9TNuL92y9tOTq zcmy~s%sbv<;W6Mlgs%aw6rKRq!jr%c3f};JB<j&EFl-cyCEzW>OTo_w-wxg_yaN29 z@ZI3og;#;!5Z2(gg;#?=5PlH+SK;tF7(NrjCh!-+Y;u>#$WLakjsBF3s$j(nvtkB> zv%u-Xtc(?e>wvR`+0o?*Hv-p*Xa5gRo50XeESiFw3AX{42)6@w5bgl(Cd{6(k1&gJ zpl}cHaN*wIF~aOICkPK=|36g>qhK*hn7!c~VfKc1lB>GIvWPJ1oprx3tgMHHS?T^F zTpj#`a1HR&!nMGq<S<;aEj}+64Z$x9HwPaOW(wXC?hk%fcr^H=Fe}<e!c)NKgcpGS zCcFsz8=0L4j<AjP6*Z)j5q;QO6+E0R%v)!kFq>;FVct1gl961xZRg=G!gSk9m~Q*I z9Jc8A8XEFl$CErfLzs?l6b^vH!W?ug7G}44hj0dXr7(L{EzHXMpfLI(>yZRBW(Lf% z+$a{PkJc7p=F&65tkt`PYl2@Ct_^-&n8o*oFe~iQ?J;|=NmUynlaBUO`y<aEy+M5y zX>_coo!l?7<k&2`pkL&-W3$wn$n|gcRL3K)zTMMK>mMomP7ix%|H!y^dZ_u4XWr>) zm%Azw`)&_4GSdIuo@#dFFZf*(`4PYSBJJPnsXmRY!ta^LXZU?3(&+sgAb;}xp6XKM zAMf|Hi-v6PaeSOo%OcNw(9>=>Iud(gmijg_??g{LqrY*Yr(JMsr1Hs{>OH;gw#3xP z(33$s>yF6elhtFop<Qm)p|Sqd$mWwlJmo)sGA|~v#IlMaM~|dNE<v+RNhENpI-b-U zoyt>RMuy>cVq`IXr$(MUl^3%D9cr5XZb@<uLj1?68dqi_>Ygs=G-{k>W+HY(rk!q3 z_7;U+M#b0U#g4hxT;irhcAc)%xR?fC+*<cCf)^EEgiDNXA#yqPdi>Zv-wIm9`#KnV zdr+j(hdHWyr1gh)$8$VxTbnI29q?x!o;eE;>G{`R|HMPQdH&w<MMb^#Tw3P#oo6mM z3R!eZ+6}6rZhbPLmU>pN8y3uoX=<ZRMy8$5Q6KA%7N_N@3;Lsz33;lvE?ffBC4ICK zF8O-FlC+FSzq2V<@^<psa!yghEM0g<Qhwy=vn_ipK#n+e+(2A>zL;w#&$JvBdmV); zzQEYU+`vmb##Ow;<?-T+X-lCmZn=A53xk7}k>Yc8Rkz5*bN~JMS`gXv`H?@Fx7&Ao z@vRff;r^$Ve)B{^)yUzmd#QKys2|hvVkRRglE1mgUv2Vtx0}CjxcM9J=I?R+^y_eN z23fMqRQGP*c(VAzY8k%z4cwWu)D8DCXWZv#JbGIrtl`^tf79QmKTJuAjZDqYioE$v zT*e2XeJ_PhJB2^|UbA+=OKTGf>m;w~uD*+mypZ1h>)-cTR<S?1UDw*`Z&ALZw)!H< zhia>H<T}aftXx0iHT%@>`S$B~$JOzpmh=e5RM%5aC&Wa)zOWJLpKC|%`7u{n+e?4E z(e|TbHwU^qYjI@QFMT8Vb(142e)6f($kV^1+3RB?um954&v_Haj#-0?{X-<<VxvI^ z<4w7r!X?)CBwWX>#ZRnnCw}AY(TS*3>AdsWzamF{*<*?4(FywM@Yd=0eDk1!X~l`~ zz%GVPjB^!r&P4ulaeVa|kjAI7G5f59J#ZEu--Hz|aW7I3U(^zsR^nBW2ETS5or^g6 zeM!w*!H+-(s9J$6xDE&UfNu_bj-r|u;2m&o07DDwrhq>dxA8y_&Tb662tQ{BN+7u* z@D0446<CMg>jNusbD0@H?_kXcJR14%*TMm3jc-FBnHSgro*TFsu5Jp%!=E{UQY7Za zKpWW34pfH^Hw2nMGAqynw$}%KfP7|PIYOTi_!1GE9(V#iObc{~i;Vqy?d&eF$PKi{ zFVbHd@%2xA1upzP|4Po}1ip!E`+FDM2>$W+9Cbq^`%<r>5pW(8_z9M=fp%~e7np(w z#|N4~o)BmUFA}XXA;iE}W||Mt32+YA3XF|xyi_@%4dlwQYsN*6TpE-A3v9|{seW)1 zOihPwnd<6B7}8P$@Ul!T^%M-{QeTb?{l_&3{gr==Q`;l8e*2=#<A|>+RtJ!Sm~k2$ z$@#r;g=z?2byw;oWKAX?B4H?opH{_1k(s}DP>mzIfA3MR4Q}=05p2HdW6#A56{|@< z$g1`M4B<Gys>=K4Xkx`htBMp{t_rIPs`jb})Ec!=7b#UKeLbvqAQIwD9-nk~=m|<y zw2ue%Ql%QItMv0ql~ddFdrDQ$c#R3)au@RsIfsXaEc~1g>Qq}zQa-)FR;fj0@lf^y zG@@}Ufl6Zpl*dTs!!ig@qLz&B$1Jw`KkLJ`%Bxfi1z3iDP<<Na;-_l;ToY1N%WCkf z4mzp^qt@I}jpLXJR)Zh)Y)1`KJ@k8yYK}{aPYr0a(D>39dBcEK_Cj{FhVnLu^VR{L z1Dr+Sz*ZGn1sfqc7}5{=R5kl#NWbD!J?u|HIxR+ZQ|tAp7?r9VeSM5-A3o0_JFaT^ z@pOk$DPR;Tr5KMK#Fou>HHxzVpAXb&l@II1IMte(7++PX2q%!T?Q!0x%Bw7F*SrYk zCZ@d4nDX8Nb6zJX`ViGS5S+;|46CaShp;Y!%$opc1=wzE`>BTcs;@oIRrFbTv&8z? zKe3Lt@)nBqcmKpX*~+^e)<fZW4B~BqMu2y7SU(xU%qzlz^-yF<P-z~x!7r>Ma}*zL zp2Dft^uc_XoAfy*=@*c+O4m-M(pyl-LM5-V1cfZ-ZZKE6=7y;823qsA1FWlY9Jro> zerVkg(Cas;KWXOmG`|A-UtxB0@@A8h<@M<})hK2@;_cTN@v2hT)JEQ09)zp~yvSGm z?P>V!XRmC>OkCNCsX<~3)<Ub$<WOH#DEWXg9tcNq&%v(oQ;fJ}Czv+Oz81zc_rkgg zGZ;3USM7|(Tx1Ft9kq{Dqpy|zj9w70a<6#}x^82N_0e534R>YMn5dU+3;#ZcFk^-B ztZ5e}yVdc_PRg#OGIHNlFu!qD(=n*psw4|?*XOv4Wpr|a%F3IJd@QqFv8xD~UZwa( zsD_#pb8<G+xaC=tUDDWvx^IHYZNT0k#2NJv`_K>*VzuA|sy|!ppq-JF41qjp9Pb@y zn41z*PWb#4%SYg0N=H_B*5lA)fYw$EJ}H&?K(VKAqtW6fN)9P@53Z!-Zn#XH_#C`t zm*5IpPDbddQ+iw$wECXuf5c=K+q_ZJ-4az+cmmwV_hQIvXkmUH1EKWR;}X{nC5GEB z@mgT<N_d?%yyYECYR7|gLbq1S0f<?s!AS}}r=U$HaxDF6yOoB8Kd6`q4(gGcQ$Ik% zWLMZK2_m!0wqXj`Lzvu>WE3H+jGNeqL+nYcmPeS_scg)yM%zRPSP|F+Lj)6>&<c>% zB7h*voKS3uu6m0lEZ4(|bzD5C`~XCB$U5%&u#MgrAKKkox->~8ITadOPM}#*^O(-5 zb_S|w%oSs~(x(DwHG2N|7+-QzxKvgjUY^ub#>b@hXksLNd3oI6FkYU->9c-NeIEvx zqXm9>S5ekbUO3+ak9c|1mGbhWKAf(ql-`@B`YV0>VPCdZUnZB+PFc0WpAY-RI8Aq= zKWdqjTDrTeDpJOR;nCtHV-e4{OSYw*%P%LB{=|^?|0nMy3;)DZRVm($7RSah3!T%B z{-lZ;t-EHaS5mDQR7wcv`;-%hOj8NI(xhzlXzZT|O!N6mKb@yOH1F3-_vNbuhi}<S z%hy(8mCBE-`#x2#+3eKT-~Po(E<IF79d`7{$DQPAbrBavXn<Vfab<1kg0m{l^*EFC z<igY(eP)Z3tXtJro%FX)IJr8jeR|`_Z_^5#@>a6$?DJPiC<|S5KUOb2&F9ZZ$OW>7 zbkr+hEW;*EqZw9PRrHh_<FfUhi%G$R?vU~b=}?S6T_=X@lzLaWA`5LFwYII8+>2w? zv_^@9VJfS=t`)LJ=`+vy>gq2;c2Fm#;OF*6sVTZ!irquU9*+;|-x{i*e(LF%EFC!M z@1+Ab#`P*~xjiPRbeA+c7->1RsxE1wDy!;xL=!b7JKL)2xv^BWa;#o3qxY~dy=<je zx%!(Xs%I$QdK_YATecC`)IEz-6+F>SDN?OeUA+aS>;kI;GMP%%j8c7T6wC$SRmR*< ze^aDJsK&ZyQ@AbCQ+R2n@8YF}-qKWM;)dvEF7MW?Rcx3kR!eI=%+Z6H&v$^)gXS0h zV1D}#X1>xh4IH{DR*Ci7AM9h8V%!?dFFh>p3QSH^wc1z(9&@(U!D=aH>V~Y2R%gAk znVM@iEGjM2Tse+@>0oLatLZ&v2}tBzVl_U5Gj9|t9S(Y+I_t`<RP$<GjRf8zmbiH* z<4R5vIc-%peRC_7ktx-vIz(w`SoDRQ)LlQ-3U|gHU>r;ctr;LWN#t!s-UnBPqI%*7 zhY1<_mqQjglc#za6;q|@CuOYONg_A?NTOm*3OnloC8}>URh^)lhFcolk)x?%)YJU> zd~21VKPyq4R6ku8oY@a@9GpZ=L&KmGlUM!qa9DTlPfN*4wr3nn4OJO9IZ5OuW_=;R z!RAgK%E(E5^<H>aO`6~}V$DdBlcG%%tg7l?TdN$Et1GurImLq^!ciV)8tN3|Motnr z5QW8Gcg{VHjTeVW!%%&58<i0r>WUa&#ak7QhB&E8897PhCJj;#nu!i&<Y-PZ(rP$< zaF~*WKa`P^M2?tRiV4S|)7q*~XE9I^jW0^cO3R=`;ycoyS=2x|(@+j)lE`U`2e`>? zRfgZ2VcqoIZB@N!Wz2$BTBhro9IcEdO310%keMW)>hmy3hP)lvWD%HIVsemClp`AJ z)-b2B2ymF>gQ=@a+NnmJ#~8U=onXP}vuY)Y9B;xbHP+Q(R?#EM$Vnp40;{olZ#xv7 zh;k_!haVgd;G{Fk$Vnp42P;-49FO3n4rSydk=F*R@%X{P;S+TzBPWR*XsHSOMVk7x zS0UZHy-JPb&I|RQ=t`^Nl7?6}a*dbElhf>Jm0Y0@7d6@C$|9$XoFwviuo|d8Y>$L` ztH)HxaU|kQqdpFDlE{tM(~Q{sL<@$6mR7};vl)`t<9fF+-IWM4I1{|Ijc^;Wppcv- z7Rg{W13x(Eh@MhLP7=APO*0|DF$O1fC?h9{JPoXbnGWhuMutup7q_-VmFB`srE<8E zqaIZRtLyQD;})FMp^Tg)@+`2Lg&!Qta8f5rI7#GM<jkR5hOea4ULzK{xRRso2Y9)p z^TBCZlvoz4D4ChDRu~tnShyFiKAdVcesFZcNqx%5Nt7deYY0wSjK?(|r;>h%5vH6n za<m^ZMROwrI9A}K4rSydkq5zQI(~4h#z`H@$VnmxTIEyo+!)c4%(5|MmZzWUq;mWa zF++H&JpExO)t91PF!F?`WoOl#qNy<QglI`;)sdq6VB`tWQ(?QT{<gF7Q~o$)JRwi) z;)bykMxGEg6VZMcc|tUyi|gUHF!F?GuV`Vw2D1^J@8ZTJ3r3#M`t7W*tnSuT6*AaP zknx24_O7n#co=y?bWB7`VdM!>`EIV(<1q4sXtan9!^jh&O(OaVMxGFT-_4D0nvKlF z2~mgcu3rsd<O$Joh{A|hKNxu`Fpq&`)Lb4z!KvVUFo$_j9xq%A@@c~Lz_ZElXD+Th zqkhgOXF&nSE!4?!i#dFo$FM?}w<ax&8;bRiFx*&=2{W**WCXSYSDw+pc9OH9fMXAJ zgkxb=HH_H3`_z^8j{$?F>be%`9%kUGwkxL}s*cOm$)exD!_7S0$-^AYMfC@Jc$8`X z;t_8rQ6=`WQNG#3i#^N^CaM$hF#C?EocEw8@AB}gQD*x;5;fp@+QXlE_zMqT@bK>* zPGsea=AwtQJzUqrO~K))gZ3Va-X0$2;Rzm|<>7@MzRSZ8czBzKO~Y{`8n!<0Sp3z) zpLzIi9{$e5KYREe9(Gs(B_|R*T*kxchME63DtIiiJ)Gy^Iv#G|VZMiq23F$Xz8)Ur z;SnAl8}=Bk^Dx_V)YBV0JkP_6Jj`Ys)xXQbt33RGht~<4^s`Mz9Y5*e?H=Cc;Ws?| zj)zZr_#+RW^YD2OD+lc_8gRUGB@&z%i^|hIT*<@v9&YGiF4T>><>K5ZbKz~2x!Bfa zq<`sU1ICOV-ss^i9)8BdyFL7(hhO*b8y@BZb2Jhkki$|-|LU<g>*4P`{ELVAWF7U0 zPt{Qlc{szvT>l!?Y3Jc^Z;yfNS))qVdH5C&b9yzZ^N@$1@bFF#zv|&*9{#J#Zu`6F zv51Yi5&)N&Mg!yPg(!3RXp}p8n9E0_a;^Z4@)i%j<Kb^(8eUQAg4<Kn!BrmSy2Pk_ zx?%lLf0a|MrrULF^jLFYU{v*GSM@AZ3#E`hr%0TAM~-v7_>nBPIm%Q`-E4rWhs%Tk zcp$E+m%Ep31Mp_7u09WwU%cGxs#m@W&)DL_t48Gde2^^9a_^Gs>cLmR%ewkz_p%-r zzeFiN-Y6V{s93!3N|9J|;aHT%dw3FA!oJzaHMYNWL>O}hUhzB`QyLI$f+$lwuSb!1 z&gD@^=vi1tb88?)xo$d!kvS~IG20_wMXsxx4Z7m%PKv}=E<1v+vj&;y?1fe|-<l;F zoAZP4NZrl#cLYUsb;@9rt;BG?(Q>U9lgqiRUDd%J)tw&I=gAzq;CS6tT@Tf0x)V_# z(G06duBks9jFRo9%MVd~5rxS^Q22HALqk+f=bElJEt8=qvFc0~c@K|#kVih8%*P`f zON@?A9IA5qix*FLRJR&yS9P~XzK<+VwWrA4T%9jH@(bj;dLg`y_GIaPh$MF9$?_yy zpDe*QC0B91D+WhLwVgaVeaYg_K#%-tk9@pG9-iT`m`#=dmU(!Uhj)1RZ4ZC%;n=_x zf69Bf7FiNgpPVHl*~TzL$JVVqO5Mnknjsz@>Cw5)BcJ18Y=^uY*zF$qT^{-B0D97B z0Gm8YTRcj;Jn}a^@~_BQmN^1tu5gBji#<G?T-VjVmYfY{Pd*8T=wN@gM`;mRQoqzA zf7Zh<k>|OdzTuI7;o%?2QVoMautcIFIIQNnj;nht>XUDB<xM>DwjS>9;h`SB+QW-H z{D_C2xxyI9UNKnTcsK@+H_@18c({g#TY9*shZlKxyN7pq_>f`dKaNu#i%&i5OSuw> z${w!g;SvuI^Y9c8FYxd~9=7!2+WyUY@hCMC9ogAYxXE-YO&qO$hzUzO<c^nUn_TYU zyFGlrhadDXS5ZXWZujsm5AXG`8Ffgw;R7CvBOZRo!)M7-v$(E7Wg#zd{Nmx?J?wB4 zkp%@Di5?Dk*o;`REZz62luE_*JQmyuqq5)<hZ)Lb8ML@!LJ9Zs@Kt)<RVg|CYdoSG z^wFzQGKv>^MBLgEb-mof+}aYAbInDRAJzVWDH&mIUWtmhc_qqwJj|sTQTZ_sf8gQM z9{$wBTy++8%OxFA{>^3g?hwlnP?lwmL=TtOlMu&h)jT3@Ls3~q(`+}1mRe`sJ<iF{ zwKv$wDcoWboqzyZD!=r%3F>3Kywo2}R2gMCk}$JP?6`33!I_$^AG#E%tVgDnDJY#e zNp*6<8#u^DG<lejK1NVH%m5lg3m$i{QpgDF5*c?79%kr@ew9Z}CKX*54>MdvyX3K% za<m~H+#eJj;h3x`D|eKxObcgZaLgym800~+3^HCLmv?oFIn1lz@?f%z0@jh`cK#k& z?#n-rrKxb;zshpm<|Lp;iDn|7f1>+3w|n?CGCV+UXB`%1T#pGePRE5A_J_h*;7^6C zgTEAJfBvm-A;Pz~u#W+7mgkaiBe0FEro0FoFWd|q5N-iZ6K)0Oi$?0V24@Mk1#^WW z<sHDah1m_%2Zw3V0|qYhAol{d5bh7|Nk%<jb?Pt7oF5|06ps?F4ZcRWK6sKa6EH)# z1bm|~A`~{e4;cVs#D!(#KHz)FsB{c?jW7dVFU)Ff_6tHM5B!wKc?;elTnEhVlm65L z?-OnUe$6oQpILfXESRNyf}?|$;N!x~#t(%%fj<>y&Y2B{&}Yt>4TfMQfL$#8xe6SI znxBGJ1Cf>F;mTneqzP5^a3eCB6CE@cW@~IE%nIL!jAq6h8Ys*h8ZOMD86(Wxnj)M7 zo+TV+&73O+mLGdtdfFVkRJa7p-j;Hv{vP4c;MKxo!E1%5gEt7z1ecOi+{8RD%*4DH zgYu^ZQ^RN06eI=B(>fu{e&&oY`;)W6so<}KIhXpqa2EI{;i}+-Som4iea})xm^qX# zT$%k(1u@WZwlFJEo-lKzj&OZ&17X&iroyZrt%O;T+Y0vq4<Mt%V8Vuacr-Z-3wA8y z#eylDER2X-Glkh9&K72;b_W?k){m9KiQrYj^z(5tdQS%YlrVF2hcI=*yTm|GxxJna zs)LV`(X|zT-xp?`I4#Uh<`dy|;4g$bfWHwQ2<CG?{TUAayYLt==KvrNn^)v<uEClJ z3$qsx4yJ=sMSdqZQ+NfqiZG|7s|nu+t|hz<TqwK|+(>vQxDy$bfH~JA4&_e+v#yU= zFk8lwQ7fr*oiOUDHBA_$X5Ao+xLWgsS?LxD=Ynq&t`5FSI3K)9xF*84?iU05e9m=n zi)1o*n}>G_vrg<4=8f?cVYVPngwQRE@=ak@<d4V@GBM|bnc%;H!?a+Exn!K%C>c8+ zY7CiOW}+}_eo(j}xU6ssa7E#k;HttUU{1EspElsS!kxfon;+z;A7OW&9}L4`Q6fqc zz-FHx<a{e=_W6Mqg3UfZ@a<r;&kuYz*zEHIuLh46f7XMqCuh06Bv)>dnR5#ahuzNS zR<U3?nSFjxss%Rt{J;&sW}hFJ#boyRft!H;B5s?3%|1WKi@|1}AGic;_W6O?Pnd0f z;9lUD!{T@d3}&AnEQW#2K0okyu-WGao&h%d{J_kWkHqcGV6)E;^7-JeMb6y%L3j!H zqVQ7i@523=jWOtqnJvq~Ny2PqA>n($8NzG9W?x_y7ITB^QqH>zj`~rK`1fY%%-%k% zbL;9)*7I&sYy2o09`sjb>E&7R^-BBCRhJx9B~t(8db--7P=OwMTY7HfnU{0TQaC8S z<I^{f3)C&`w?MVA^+O9)f<CiQCF;XV@bm2=RYfo7PrpTR!O|+Xs6n=Vd$CH@`xd)8 zwe;*Is$%KSOH`rKJ-6C5N_#C;zu0>1%GiAU>B7{YK65+v3p}e|yhG)weR{$4K%RO{ zhnC^R<?-Kr#@ZLjI+~_^!~8)#b(t!sFDy+8mcNAiKKrVnIMI8Umc<r((bn6Rsp^$3 z*siPuG9Kf5Vu*n&^(*O>i<47z{GBSRMyB(B>or83xJC4sUu?1Tw@CNCQ{~lY@CWss zP^UG$Wf4TxuhZ+Gt~TfcboKBbT)hHUx#Eh~sH;6Xb2-#Y|DgUk)GvuTn@3drJ$)_I zYaacB`lr3G_@3`kKkw*W%T@InU;IHozK=VmU>a(A^y75GT_}cfABTdOy`U4#zS<t0 z>Ut1$?sH;-{)&AuZiOBFsjIu+r7Gy1ccHxI-=%_?17R6Wa)HN#tMx^AP=oITn5+_< zJmx~ZAFlL^{a!T5x9QF+u<e7d3cTt^pgvx?>J4@A3IzT53IsiM1%fWZAUaq4YV7fA zzy1P#)qMF6ehq~>W5}S3JnDb*>1HdDeSC)ZhP@2>BSoJb5banc0{XU<h-v}`Ltgc- zJh5pJ`R=_6F-u|nWaP!eSOoNbuugCQh8&U<_U2LV%u5HDV{!7p>TByIx@yX2cy9=| zT!m3HG?;)AoKYX9K@T2Z_TiE)tl?yY?i4W^jC*JmQ5m6!{~!(-ak_bqhh9`W7x5{} zXoUDAk1mZn@XXOd_l7^|{0ap_jXG!n2SM)SOFt(zqHlGB&A!OW4^oRihK)BxTnx^D zn4(TNqbcIYDCl?e;OzfyUD%{dYVn0XcrhP0x1AWk(u*!Qqh9d46<#l1M`v<6Qg|XY zz1$ycHlRD05E*qUwKx?v-slxgwXCc}*YEBgzw`g#L!dgAnlS0bIe+kB;2hipkwc6f zI;zXDV`h0{_a1y0sE^)?k7@0HH6d7M=3I2=$Z)zttH127=O5hFML*EQY%Ctd_fOu) z`{rY&K_ZV<blHm`;su)mkFkZ=9Drx3=)q|59QOx3TOVD8VxIyr#xs|XG~ADiv>NJ9 z3yOoNRX3e|ugWOqXEwa?>U2AIj=D)h@n4P?Kege_l276B86EmQCAHFRfAFIA9k7C* z%$>oJm8UBBUugpgqQ(1r=g4>GE5vL-W$165>tI59$hQJ(Qdr13U#lw{P4&&q%4A@p zbkoTEZ}RQj%+e)VJ(^PQB=SQQqS6gQZCeUIqX)M~SoS;2J8ay&3Gu?d-yiglO{#kN z6VSJ7qR^bO9J^q*?+b8^-M$C)1DjN<oMbd2*}hpG{>v`S``|}R3?10r67)Ydscb(B z8T&a|m+TF?))T5$`TpRzh9{r}8E3oVn$|#OC3lU}Q=d@TcFkBFc|tX<&<6!>g}7f) zSt;CHnVdLTeGSdj-}SjCRNe8n!OE97Q>CF&hMF<IL)+NcLfep^wq;+BOiUX78RTic z<UyUNwFgd4SfPgy>T6c$I&^{cL)>zj8=7sZjm-g7^3*EOg`1UJZV(!$=WSLM%Do9U z$&Yg-Lt-*ACYZeI8*tJBy>+w7u=C>dfz7I!+M|6>s;n@_(kg^fx9rdc`0Rv!hr}1U z9wEkrHY3E?&`q$73vEKe;zI-ARYHh!8i`i=23Yt4(?%eaPytk}&>JRMcOY)ImCla} z`2uTZ(|RO)wL(+jPGRTI%@Cz5M&c9O1$^o*K<Wbh<dZ6sdAk2eHLyZG#3j()?CZ=; zeFpvoI;%DCqIT+8-TWz4q9S_kQ!2CKqeyIEtl4|kDzys~0y7n-?n*3shkp7gm20QO z>Gz*f4b*9!v_<8rGrC}lny(h=r?;r?c3#50Tag(Hbn~s4{64QoY{ffSA7WYN>Q~@d z#iZBBW6710sv-?#Cf^0$vywLJ2ezteSeN}G9Qv0ag2B*J(6W<$)!%JZ_58DtAHg&x zJ2~lPUFT`6-sS^SFoU9UW<_+c+*EMIq<wlAtW|S;{nP5YY<}YhTi5QTa=oYVo8}7^ zp2ao9#Vl6n5v{hVL4FQ?<AbgElz_-wvrP?9H|f3GR3&v?>8Wk1m$EA->bg5rb#+4b z-=S`@W0Ul;9jaax4t7-wt~wtM|LSmCvMOfVh|qYS&U!}mOEF4gs8ocavg+20D_!!8 z8mv@l=||71flBq)&33A6wOJ3{sj7qqGtNUC`tlcKPu1`AvYl#4t#m|AUGK0d<ieND zIMtfJViu@jTWG?D{3;!k>f+~AOSNCmeNNq8>r+N?vvJ3Je<$OPuZ3K9n~l4D2(#IK zUARkCRafhNyHs7glU=k6C0-b>H}1mr+0FXHUFvV@kUqFuRj<{Ck*VNgWaw!l<7ved zczQL1tKh2)n-xHKT44`7-KksdQJIL-z&&b{`mWS@9t-i+meOu})h#x5FC5*c2H{fc zMd(h^Jzi9eVOmVn2>tkrs%?n<hl<#@Ac05x2<N!I^r9-x=EptML-t#Uz<JD+HDl+l z9=4~K#j_ytquD*BgI`ikOwL|LxFWkVcOzkqZ-A;&cSKVJ$MpQyRsDwSa#YowSLCMj za#?z!$d8?<YTPF&f(iQU>)4h&N7vb}YO5}K@P2GG8KdXy$M%;h`hHx>9f6y)+|89y zTbCiK<*MPw>e?qkzqKE^a=-p!znZCr>){7fJKIXs8xE+NcKuj=<bX=6^bsn5`rvnP zk2h|u?rR`OJj4j}xTw`ZRZF2w97K~_qI(~NcS}pJJE%rgi05lD8($Ut-?WQtu>NYk zlU>^7oEn|}XZLtLw)v8ZDLtp`mFcRW^u`Q(%e7%XoJHSwEJABls5d;8vAUq%@z_B| zW#eJq)u5vB7{<DXhQ*^c`k3ffEhn<>m2>5MYL33NFbg%xyYeKIDPCHHjp-{ID!LYh zY}}Px=G`j#)?z!EkAXN2lCuCf#-cr{Y?psQBo#Xg9KR!Be1X9mKkF@-_v|ELJ|Bb} zginhWFl2~D37E^yC~ptW5$*!6A>0#OPZ$poRwH3fTr?NH2HaYh^S&L0=YzWo-^uj% z6$9^3gM>GNd1quKc7n$W9|m71%syb6@KNv$!f%6b5<U%HPDYWiM7Zab%#7r>BEvLP zg<-8&F!vr6t`0UIi-b--*nBJ!Tob%gbZUe53iIiZ+mY!fbJTn*65I-WMC7f(=39}F zx8sbL`B)?j9bsWU771onb7vVn;wb*Sa4+x$VLSy}zY4PmI4Y$+2dJ^aERJMhJao9< ziiFP9;BrQe{2vEHWl_2ooGW}C*nBJ!4km-SQ;h-41M{1&<V9ffeh9n-+(zWLfjbE= z2lo(O3GOF+4|p)YHc5{(3?qeCgU1O!2%ads7Cc?}5%6r`N5MA>v)=HDoPKTw-!8lb zyh3;z*t}1IPMDR;yikH+H`u&T0`CQz7fRrLVDmx={4&_QPy)XOHZPRG2f+Iz09I1- zLJ4wKQu96ud<<;fCxPDu<9!m|c))NH2J=D*{2};L@#qt<d7%XPXJGR}3H%k<e6bRI z9(+mkzXRK7G4%5SI9~W?FyGTt{ts}Pu%l4^<;B4JOO|jlxVmr|aBblfaDCx)FrWPC zX?bu<;VR&E!uZsT)kT=2f6fn3pNp~wkU8U72*XgZXbc`L+#Eb!xCA^|xD9xwFc)#p z5$*(@FWeQ(p#uZ!0lt@v?i?9qt@CjBaWTZgf^Vm(gx=WNOGbCf;}s7d6o$Xn5#dzu zd&249Q^K5B=KKNusRsUBI1l{2%VDbq48Mp)9WY;o(*ZjZ8?hpDswkaY27tr7q!KnS zsle#&-Ir8grqaBm0yAOeB^5XUY+h1<kxsm%Liy8E3>@4qR)R5-viJ&~a^9?Z3-kWO zK^f&3*SIgKaQDjxo0nAJdSLUC3d{t|p+2|~c)oBkc!_W;gl{bqLu>He!X3bT&ZJ|^ zLRoy2BM$>_5S|1!Z?Yht0yb~5z|+9yMHZMho_(T!1Nb%J1>nQrFg;~2c1$c5gO3Z} z3jR=-J=dqg?76-az87r1Y6*Yt1OFs)c4C)=d1JHV+yp!X=4XQ#?ppT$0WoZX1^4LE zf<0Gx;ite^!q0;F$s_8p<7z@i?du2TDhTo*u=xrmcqrI>1rt0H+*5R}2KP6N{J$0k z^BGJivCkhRO3cQI!gIkhgl`6$FJD4`KG=M)5_}tYvFO|ZHebGkd^y;B`4Y@rG+(|1 zGZ!C>I=&x<4dR&D^@Q+xFdyTXvcG`Mn=kNVVDsh+%p5XrzQ8-c=FJy)ANYv4WtYq~ zAoS-w@G0T&$1r>>26n5T3x5MXFZ@0Dg7DwLzY6=%v2dP|o^mS+Hz||ZOLFRjTn@}m zh+F|&PMFV2mCe^KVUYzxu2|%NYYJBf7YMUwY%I*L-?b2C56Gu82EZP$lQ6fm^bj5j z?k9XLc(Cv+_WvWrFdr7?lbG=64)6_>mvh_qJP$7tu7$+kCR`VMmv8}im2h+L1H!Gr z>x4PLd5j!J0KH&%QY<)<*)BW^{G9L@@C(A@z^@8V03Q;b3_dD69sIuVOz>&pIp9x( zmw>}xh=H~A8{rk;ABFD*o7ZEA=zU=Gb_~q+oq+z7ImAIqMKU`4TyRxk=0v`51F(5J z2A!thhORtp28yjjiCNS^xE;8gaCdMY;l5xl6lY+=!NY~egU1Ln^%I2IbUAZGeRgiM zgxN&ra>WxZnEHic!8W>7m~C{qFjIVw@FU>W!dt;>h1vWb72XNnEc_yPtMJR<m&xVP zO4$D&5Cd<WZwY6B-xaO|J}I09{z$kQ_?&P)_-kQiJ3r&a02+cX3KxNY7v@dK!F}F* z?YJ`xWntjEe-x)xQJ4W&70v?Z3p22~!ZpDSg=>Sk%%1)*5+%a*!5xGfgS!d0VE@ng zPdaD=i-E#Dz{7<HfX4_A1oP`a)E^9<Dm)a-DKpAPgXapfPAn9j0A40M5zMa?rBp!v z^VWHvSg_(eBz!%1gD`KMn}lxyZxx;oepYxPm=mvz1nbR9!mKy=V-zE2OL<e6-T6CV zF+2ss31L>KGs4@zp9-@={Y<WCdR^-u!Xe0=Bv)P*>=$NHrV3|)`S~NdtpTngY}W8s z6GJmt)DTA5SS`q?1j*nw!fD`6!mOk{gjrYm31@)^3$v1r6s`*%CtL`gn8fivT(VM3 z6^kP9A~MEU4EQ$T6!2ZbOxY@7<hJ#Ia29x-FjM)MFavu+m>tnxautpfQT{JoHlWFo zvv5O#65lA0Yk@x!=J@WMFl+VK!W`fIAlw{$QMefVyD(c>3{pft`+$?kVHo<s5E2Xa z^A&|z0ds^|>1qfs0M`><25uzGO4nR?Ex5Jt25?7V)~7zg`@mstAz_SOf?=5OtKg~R zZ1?6gOSnJebA<<j7YYvpFBKjEUM@Tee2*{_wpy4su(d9S&6<u!#bPQfHVaP&Zxfyk z-YGl>yjOS;_!Z$hzz2odogWdt8~mOyo8l?q2f-h+|79v4hT(IuSO-2Y%zmCbUZ}(N z`m6BcU_L=mz6lsBybqi#ydTV`De4>qmlHk%t}Og9!nbn8Z~<IXm=B<hgahCf!a;Bw zVGgahe})0@0knrOcmMVi=C^|f3)cpZ6y^iyIB=MbIkcK67A?Wkg-gKPS3@0s`1WRD zeopunVGg-&7v@9f3gN!sdxeLC*9eaTuNTJd;;{9&7^cJGDdAhd+^oZZZv*cV=CJG) z;pN~rh54D|<H8#Jp)j{2e=58l{H5>)@VADM|Bu4(lUQs9UlQH|wgYY?c7WrB_kjb# zFN4#BUj=i=5F`CMI7|2dxVrEmaBbnY!1cM)hYpUzP$YZ;+*0@yxSjAv;4Z>^5z$Nd zTkrtk@4-WbFMvl2{{$W{{0n%paG0B@@v&DEiA0;9b9FfxJYP5jULu?dUM8FYzFW95 z_&(w4;D>~3gEt5lfw@zO32qMF8esnq13!WLtXQ-H?-6bdeo443c)xIaFt;<&ZAb7s z!kxh<g!u~djBtPOS>da|-2OzjBW;xbw_+F#3#SY$a@}P|3Bs$;EXxRMaJn!%lM2F* zfwP4-g7bu*2G<eZ0d62%3g-T*lrRE&4u+0mu@~H1nBDLY;n%_AgxQ&J-xVYJ26(3M z+u)mo-v=)c{uX?P@b}<V!oPsS4~yY<7&Zzkh2|&BXS_YaabRxRV!)jJ+AmxQ{HAag z_+4Q>zMT>-0Dmmp2+U1h@F#2)!SJnEaK`IrVRl5n39}=L3AzEZBT5qHvtLNKBRE62 zGq{p4JEa`qp5Pk7d=9J^MENr{Q($N$7K_2nh3^Bm7G4MLD9jF|yYL=xU*Q+PgM<%* zM+hGUj}?9gJW=>e7={^Q_#8Y(_*d|JVIL~y5@CMZV3}|dI3nx^uNDr1*9r5R2agGt z13xLu=DHmmX6kcbcup)DfL{=927XnTP4SR0o7Pd`q2Tw0`AYah;j!S)gy)0*CcG5< zo$#GD%KsNJ+zpH0g*7-9!&*jeJvdpIpDp0Bd&-{ymlG}pR~F`1J9CBif@=!D3N8?S zAKch5%Kr=uEyUtua2w$-z@3B>984Ywhrs=X%Y%ms=Yp>m&I4a7TmYUT%=bjIgqwlq zg~iYc2JZZ0%G!Z%6YdATOLz!)mGEfr1Hv=G>xAcl`K?s?69)4usbqfgfV&CFe*tqh zA-U2f81{*Q?{{7k-UU8b>VMFFxvZM2k8Zbns&94n4qW!@X}IX%Gqz8^vcv9X4_u;C zp0RtVrFzsec27Hgson;oUHcAgKMV0ay7#koPk*oF?(EcHbTs$||GO3R{%7rc+jp1# z9$I#%6}n9+wD;+irPN;OcEZ#y&}xi7_1>L!0lryZxD!$MN-yB$7JYQ5eS=zC+W9#< z&W6+8yCMBtuiFjjJ34a@O!w()ak2ZI)4TTAHPu^s6xW;nvd0eExnJtU=k4k-O-3Rt z-ROBc$KE|LviD?JJ@t7zsNT>Ep11R2VkV&_a;2Ew2dSMFtB=8vTC6X^7NKPC#bvzi z%*!u&8ZI$ALdu$=*PZ77Ebg_hEM1D!J)Pkzs$XROZPFe(t~Bt1{bp?VG}5ScAip`t z_a62jm@Y3};`>7^UHT4}D}Pz=BKisZ1Hp(G+QszsL7(e&obm;5iuFvBX^4-TL^WRw z@BCN<wH0bHKEML_6`RO~R`jGGR<FA~IXzrC79rGO&fCY~AjauN+z+X&da8)fVq*JJ zx{nyQh{%CjO#BQWK5$=_5sLTmdqMVK{KV$dlZ5Mwtk@dHy91a*jIG(84*5Zm*g{4) zu^#-;7hkjeVU8PoaSizH!q4GgT*G&v0B!E?h-=DQNMJ3}5g$<0ag@!4U-l-55{93F zVi{lJptZ0G)`IAS6;$x>HLPcXR{bEGRc_FMS8&63YKc?%cMov0lEboK9^W?1j|u(= zD;4CLsu!(bf~{A-ZrAX?PyH7bz^Tvwtv>R)ol%V+;Yd8fJAAT#08*CtHrXGVK6ady zc!C`8-=vfG+vUR?Kv_XP@v0z~3){g)2+IlHg>ZerjrffTj$^q5+d?NUcpBct2M0kX zA&9?+!^@eJ&tULnPGheZ<iCko!A1C0L4N+pwqkwH;~F;zJ|(w>17C6@ex}9bVshiK zWTOu@$;B_hB6$`ZrzLmhYh^!Y+LOC7!j|8BF|#{a`T3>%<eo2p?a+v8$5_d|$v*!< zdefI2>*uSz<U!Pr_jB7{@(^-@{{VRybrM4}GN)f{C68c)lKtEVmOPRiwCtaC@d3MG z;TlA{qQ7fr_~oAjdw+K(#PWAT1YGv{BaEquSiFCUUVp%@7v_sKe{Y5tGzH-ALk{`h zqO$?y6#p>#Igp&{e~exXWs=kU%_twf0P=EH@<)hGe4sr)dg4D0QJ@1ISpGA}^FT+k z@-Ks@flh8_ATI))U(me{+A*1@5z{~ylNpx11`f&$VTHCI)RPa|S^lbsW3b>c_?%ol zPCsza&JI_BA=oGrO7Z^N$c_0fHrdbDH^C;)Q{v|v_+SyEmxk3~2s$g+{5B?cC!7Ua z5Rr6dV)1II`uuND-qQ8d)R9)?WdBI&l#qk|ztQW~VH(o>Ty+&}LoVkxF=|V$h?=yY zvB5`s5N3x<408$s3wETn<&PjP!A@kKpGgmPCda$sbRj4EP2qMW2mM@V8SF+*^QV!! zr_)f*&mn)XM*v*WN^29R-#TR13A53wMT~#ONGPkt+`yH=aMTiJaR%SZsayF1tX#%x zh?}~PFTgS$r1JgDz>M+KSUm_%GUid?AqJOuKcwXsBJOI#3E+bu_;3gTsYkgy4@a!8 zv%cxD-N>IzABL&2&?!4oKY!S+95_s$MpmO*m9{bZi^FzRyLYVizhRfhpEKmYVb@WI zN(a1Q_qXjvwtn(0yDIKeN8Yk41WhvDU^4iCRR2x=_qXhGYODU_h@I2fq~;5zW*scE zS+?p+mMuTMlw)G|H^$Ccxi*}W#mIieKG0rSQuQ80g)=0zFgcMuPxm}(S3pdzJ8J(n zfEy=O8GOVUmzQAO!~|1DF`OdfOPZoLR#R3QRn2HNg!wg`YR$)Z6vj$DW5c*)A#a-_ zu`e96FEr=oDf|Zp{pJymQ?03hhbh-Zv7(FH;G(#VtI4X3&*wL7?CA4v+vN(4#~qCt zM<K;5YkanawH|6YpD<k0n%re)IWOua@7Nu3K7(%jG{sJ?WGH-gKT^-f!6ZJOwYJ)9 z)ob6e)5~)6ZR$wYm5a0_SZ${3L+{xA?D}y!`&~P&;$NYYSV6H}hw-qH#HYz5K44iT z^K|cb?M%ChqbI&=SMu|(Tr&15cAssZ)Azn>R|(HTO#Bo0iHan)JgW^K3(5|T#V9su z0sUxy9pYDR5UX9AH<9IKCe@}L{YYXD<7$<3hLwLjz2LJ(5+j58R(d{@pQkXMC$X;* z{oml!f89jg@I5=#&WtPV{2u-bI{ruaV&kuH|F^7uE5(01*Z9-lH7{NLnf+F*9{7q~ zyY$Fc_R%<1px0lpb3%=ZtZ@@Z%@{vo#?0xt4T~B#)bCxeTd4Y_sXyAQs)o7hE4nUj z0-5z2M|b3XbX{B)TNet5$9LpZmp7p#qC5NFCa1gdy6}e!y3i2aza0kCNi&gCt;FT9 zl>tKsvEUqcH{l#`AK?P<K;dTK;li!Jd_rJgoxs<VkpQw;83yhF=J=2DUf^4W`+)B> z>*8S14+h?CsWcLNzwp)IhlQ^N^O1r&*MXl9o(6ten4>~&rJ~MK@bkiVf?pPX3e2Gb zbzTd@@Rk^kg5MS9Sox&z=irZozXhKYz6AbSn2T|K5UvBhDBJ-2yYNtO42qQjb9yof zY}Uo`>xUfK(SjpreqN0{6<kSp1~^BUx2zh%OThJnIWle}%&E%e!km(9ExZZbUKq2G zVQU}_=znvOn&HCrz+;3tf}9}Cmo-y`+kwqr5W{Up@IsOI1#^f&KL>)jZl26>{wm=S z;0FvN|Hs3yPApii9JtWIWbl*1EaUCMGr`XZ&jP<7JQw_`FpKq&@IvrW;iX^>tLZ-{ z@=u4w@GuOY2(JTwA-n->R)fL86JWC%49xj6vl<M%4{TP0fnNg0qct#qSHWgA7?^d- ztOf(00+$n=@TV};q5<u@2wW)K7TiR*J-Ar76S%E#7jS1`KJ4@q?g{4JG5XmbZ2s>U z%;Fd&au&fg=1TyuU=eT-Ob5)~8N$rE8-?!yhlSUG7YjcIzC)Nfv{LvLuogZ7eo*)r z_z~fEQ2(rrVt5Z0TZE5;pAr5Lyj%DT_(kE5!LJK57rCp02{;FSTlhQh2f`P@e--A; z<7ebB9K^uzg;*qmIRND<kA`qyR)&F_g5%M}QqC7|0pVhBns6&{d0`e`mT*^ab>ZRQ z+QK8j;re124MUOeHQ<)Q*MZv!PXTi;7bCF%+)H=~*nIB*^5x*6B9DO0_YNRuk#U?# zx9h-@U3UKk+AJl51*eqfh|&)5eBoW-CBm%XW+fT)4};B0GVlqoSxE-|9BfvSfxiZ? z7q{PlpCP9KaO{pnHH;cw6bl;`uM7LYhlFu)SBc48&a4s>Hmk(IbZb_Lf$8=_>BY)U zT8!NYf9sIz9I!Eu@<DZ{r`@ec*UWQz=w2h!e0px4(@o9R2lAYrm|M!s$7R00mX~Gv zxqRmv%<XKf0n-kBv4(SlI<BYHglV6Ck(Ze|RLiNQE}9Kwy=pl@yW$`{x|UNt=BDac z1gh_><>bKgr)xQRF}K%68SA4b;?g*Eikf!$cuA|;P9F4X@babZ&C3pbBQMMJI$UBd zHNxEqe=M1p6VvZ%JUZysjpNdELLDb`<?kmytX4LrsHjO{WB$3PU9oNHxH?X3O1+~Y zgw{0)izDOF^IQ%T*_8{!<%ys8L=5}wxX${4R!;TcqyS9uG2GvQiJeBt`e-YsUDbtb zFYccRR)@Mw)bOinF|n-M_G#Uu#HkwKU$J6dh96(F8wB(<B~E2^P%kNQiZkDa?D8y2 zE)7iwATI*5^(nZ-W{uxVoJw|5P*-m4G;6dM0VYoS5n%=W<Di^4-3R3~e>$R<IAZ~V zEQiOa-H-)+NexslWNheZeP?SYBkn7x`$9wX6Rn->)XnI4txy_7;SfKQcXQ|`{a0v( zx%A@3&;b0-4srJ5hEO?-n`VV7#bG=XQjpIKRYoLcgr*`Jr-%3-6w^XnhBVc(pF^f5 zn`xkA_KiXRt}eLQ`)5PPzlUh~{|<lrGK<51-SY2$0pj>F6UR=r{D)r9*SB$Ms2}vh zZJexdH-xN0yph=<&c-^SNs#zL<5Q5op}!-SV?!^(HZIf@Nr=aPT4LTK#D8~7v{L&a z4}8ICyC4f$P_;teqwG}Z8+gIlntiZ{n*$|#A)-;H5u=gH?-u*Y6!B?1^hBz0#bv@O zG!V(LLj_5?cUz}o+84-xc(WZaA@nuu6D_-&UeMO*s9w?s+B(fmibFqjhBwLn$8@Nj zQ%?=jt=l=dYNH<4&KYdiOwup4bH-HIhA=`6&4W<K^x24DsF8Wr>6EVVuLw?Nn4h%_ zwJ@??>0I{~YGn-l(jTDH5@Q&c{>T->&~!d+hT0gLk?EC?aiO;ARU~&zdTsjF&KSm} zb9z72!5GG;??JYNIw|JDgmk_&4t1j;Y)wo*%ust8y~*jLkoTcJ>RHI9rt>vwsIM{1 zOy5Eu1}YZw?DU$n8KNAh%}wWOy3k0q6h%KjeFSnlG+GUU;g<BpjKUbjX|AQ|Hf_c! zesN@3`n&XCyh?i?rWNT|(=^Sb=$`a%^~4TNb?k$RbU=S_qu$-YnWu*7rX8IubyyGX z=;Wgq7Ilmk!zYXci{Vg5r(SMLX4E+ra7D}B%Zz%HY0j93n8f<{xeU8hSMKCgvwQn> z`%X^Xf&!!~HM1I&lA*B?SNjNJnp*y2D)&ZKrIv4w`XB2vf(iPOPEM_sl@McJV&i47 z2=RM`C`4!mLt_w5mX*2!KKK$_aY0&$|Ep+)79&b3v<L-chpOr1&ZsMcbYW*Fr`k)b z(A~LLGui(ZeiM7NhO?l*2IW1uSTD`LUEkQ*$uBnmhQvPfHF+z14JP(m3J3l{`Z;*i z-*`08cx2i4(Dk6M^p$JAk`sr#Le(Nx=b?-?oFV0j!&(A;e&cpH-Nsw?TWBVUBO)-^ z6Leu0ry6!>Ue(1J6z1x#_|PuoaWGU3K837Q{t3J<asC2CC)A$ahRz`0R45aE*jDnh z5Tzw9{}|SOuEtEfD;Mr8|LqKW1=;qqZYHiI`~3WtZQ|YJSbq;jBhm~U@8?^%#NPMN zknFz!nV-0d9JG=@L2S|z?`r~2Oz)F;|1+?#{M^BmxSH(qvsNcQKwsUSC~*xr(LYAd z@9MO6GvX1+2>oVPr=FdjsDJP3)D67K_-tlSxqf`hqj@){YV8Whg~Y9VMc2;1l4*Ln z7LwNqHKZ6}+Fa$BxUCZ~IVV})1{YmkgMDJD55DyB|CN#7N$%}`gsz|a8=~9CACHEW zxN8BppMM7RcasPD@jA~++*69;9O^Ic*FSc1npJ5FKU9fLPt;eisdSuq-o^;5%FpW_ z-JSBudtjk{s0`JtVm-6FQ{8S@Mz87ajKzm$?H*16wi`F-;dBZay@}L|g@0D|BYK%@ z`#fx+6x-8j5_pgS?D>e{_RZU)yY_TC@}_l9Pp3OnKJMwfO5?^}xbf}L`+GSxaX<f| zm(#M4FO}6S{DCUo4Wg>lynvn-W|qr6G{1nP!p!p62XpNQOGo#{7=pgt+Q+G@9@NkB zazcOB#~Ffp*t)NiNz0*qoysBO_)FvXMiffz2lX9&oomaO+$dvm!)Mi)tet*NI}Btx z^>gy=_GR?+ez*sHr`PmzG9i7opVJ4Ig#J!Ziz0ZUHrkw7LUXn9aANYUETU<WvC(ES zCLqSOK0zU?Copk|br>*PHGb9e`nxf^ufJ0fL#k)`J2e^6k7(SZe-mTP0ZtQ&ug0~D z@wLFAuUuGFd^Izxz+wBxTwM+B7FBH#O9X%e<%#I5#1w`b9o(u|Hy|!<q(2>i#KGUd zRj&UXuW~wO2U!K?I8R^{^eeFDVDwHfv);5o%xmq@Tds1h?LUR#J!!&0F`GFIwI(Su z8qSj@oON`-9XM)>(Y#<hU;tYkW<wg<VPOk6Uy+TU8eidylTK!eN#PsDgDz00nH<pf z4MZh*P?rvL28E3E_r`iI(vAYm9^`bYb%EXneM~qb)Dx##b5r?fgn~XM{B764J%gOl z*=|M}aS75`Gmbe|;G2#qo{2ES-;BY|sRE-m#;A=!mryii>P$<G@i9O64c6MGmXGr> zIrhqtwNB`qA;`_DW%SS?PC4f8tRYV2pwU|9(b_P?=}p_8VH?V08E*A0K%6h)fdD~Q zAL`uXwu93q==pda;97i3oi;(QquDq+ZJfOUGn^fRGdF`0Vwm0$80AAee3;W)t=3zI zIhmm{OlDpTyQkB%ZLLoXb1L91>QBR*8X@x)=)N(WzHPud{I)I_?krO`>*t3%lW;4o zHNq)WL-jCTj_bQdIF*y%Mj0g?Vt%y$L_asesjY6+XGfs9Ow^cY&n(*%0hVok46!+# z6`eS3J6^XMi6UL2hmUlspyuB^(rJ`+E3zS@1vRH-i)IoVeG*%`)%H>S_DH9Jx?9JM za%xsOfXbgy{v#?f@2z$=elvS7qUJ-o$0$VLc<Jm>PDbVU+Q?JfSN_+`$7;;S4lc!R z<gJ;1b|Z4>n$^ytIKBJPGQrXb>z#d7RFl$LFF6lR3-cRL(P`Ij$QT&$$mgI0y)KVy z$*h$)xLr}9Q{cgQB0d-J;I=k}D!_veunOhI!)#MVo8{36enhu5|3WUqX%8INu$Mut z;Bhk<4U>oY_B>i2kIj^$gn4k76P@qnCq<(3z2A{hpLy^hPH|2bM-{R>?=>c)1LJXL zBEpY;)s?HhqhEDx%hprTRhmw&<noi`$}XQGS8<t3i&d7(&B&;)Jgy~Ib-92&SB}dM zkaNLIe_hmQ#Ze}X`^nW^{*BBV4GymGQu!`-V>eR6<pboJE>B<=Ud!bq<eIAOGW#=C z$K_ITJ(qt0hgE@V;Pg9ZuUQH;gqeHMP1npZE~cRlXUCfhGh<o{Gc&kof;!BA=%(u& zaCFZ#(;3}!jkJX?Z@Ok8#)@OciLYPiQGM_<;fCPorfc3$xcG)TUBHWkIlao4V3dyr z-z7W&yh`|b@B@aC|2M&~PAuku`KFqVSu{@y-wNI?ybAoB@L#|$2tNkqvliWM1RoN9 z0?c&>ly3pQFZ>MnG?xs~q7;Ttgr5VOsddPAgMX!5nk5GxQBD-b1<(Ah91XxKD~#%6 zRTRd3!~G~P{9&;+pghh^q}5amkXx;U(L1}-<4}Ug>MC*=t=__{D_04#)$x5lJ!Qig zCCoZ8lPvwm91mmPw7VS{vdbH%nSvFf#C{{XaT=A?S}k&>#>|LQ8Hbq>7dA8EU?$)N z>VxUOnGpvw0cJ)V>}MgHDRCGWfSD2pGc_m0G5d}4<V3f1m=Eg;|0;6RFQK@o!xj-M z%%&d_X6rSx-OynxtxP$$qtt~VSCkrq`9U0d#HWq|;kMw$!VAHzg>M0O622AOLwE(4 z>vQPO0q{uS!{BkkN5SEVVt5+{{(n3j90%Vld=h+%@P}Z&5~t3m;CqG7f!7Fs30^Dw z6?i)tJtb5BoNy!X3oeJvCn8=Ii)OGmB-{pkRJc9(ec_Ja)51N#p9o(CHj~!~Y$*5} zk&g!dC_EPYci~B3Wws;3!7Lc!&@>p+`Cz~BVlcmWM)@7!OyPULRfO*c^Xuu<Sr4uy z{1UiOnAzS$n7Lale1e@!TQQsk^UX9p`U1>vT#>&A_ZPkZ=GVz6{~0_=_*d{X!VZQ} zlY|q%GlV&%f1_{^d<!^CkJ4c<U-SiYV7*e5DucPIhB~#uj|g*(%|_w+;4Q+%U^A-? z{SxqVBIgQX?tM;4b_eapgwedi?%rou;0EW;YJ=InzYryMCT1oZ@+`2~?+mU6<^YAB z@_u3VID;F2%@$`cTa(%13~mKBTb#k|z+8Bh!tE&CU@&`}VbK$8_BbPIjD*?a46Xt; zdz``9V6(>=%t)9$&S2JXv&R|CCT+GjgA2jq7#O%Ac#<$9G{bC1h6QW8+2agmgragr z$n0^3yf@hFaR&DVn?26p{$R7m89W@!1vU(99N27e22TcW68TK<R^c#f{<C734Srsj zcg2^5Zw7PuAU$0Q<{B?DJDGQd*MLt7KMejzcpcb$^%we&fWH>`qhNd&AN@ZpHo|aG zEOvl@7v2SqiFX5g9-JinGB_l>ADkh~9<7ovJE$DtufR2gFM#U^|IGfsgoc3Ix0|p2 zf;rmhCh`j4KEmwV2MV)J@Oxf#TNP}!GK2HM{K`M&wZKz_>wxD7vmVSRa~`!R4E!V+ z9kc**;)vV{e4lVv@I%7Az#D|w>unMq0p2P+3e1^W`g1jSkMLOVOTrVt;r(K`5r(&g zISM)<j102Q2;TxeD|{#TE8%;=-wNLcc5nyfM;jn=w=9Eshb$xVba1-MVUyMT0u~*x zt!E2of%AlOz;%SHgPRC5ON)h>rEP_qfO`nH2KN_cyB{Ll89c&lM@GOyV3<yeAOMHi zvn+fY<snyor-#iJWDXi|Y@l4Yl+5Jf*zMsr$!V_qSd^K)pV7cP!SRKMFOkc-a=d7` z%&FuISDxYFn&fh>-0T(>ZcRCAv=3HhC$Ml|$iuWiPiqYlC3M{u|E7y_X24isM*KQq zSXtK#XMt}LW-%=gW-;;qyy#C2u-Wii-i?IW@auBe-SG<pn!LN?7tGu?JAT2;0JGy4 z%z({~UvOox+3^czmwcFkf!QS=6V3-8|3BQlXM7Y@ANM^onc1D)>~3~LD4`}KkVZ)$ z#Dp4<PH575=)HF=3l@rv&H*Wcq9UMxf<Y81DuTT$R<K`IM5TC%KEL1Df0XO(?fv5U z-1~vd_kVgnXU?1=%&Pd2a0Bp9WNt@hvhcGSw-J;7E6f1#jh5=DMOX?NV+Kg?@`XD5 zi|z6Svkj;vW*CTUVaA?kY|)*1;A?~%f}2G}Xaqs;>}3_ePw(s%);oK_7S#35UN8fy zclLr=%{cSOt;Tp5H<H;>;kWcE)|+{uPIvTXUNHTS?dFAmmN>SX7tAbpKrA!w50aVY z`03re!q1619px!uG{f@54<+S0ir*GSMT>3btp&gjn|aaxi=cP&g6WXn%?oBM|Dt6u zV;P4onhYhQ5;+BcU-hfFwlLkv6lQ=L2;*Ti64vt%?I^GW;n(FV?kP-%`U%q^y=fQb zp=1mfb;fKKxpr*aut1p3E)-^sSS-wfc_%pv3oMPRM585mz3{c*Ey5ka+l70BcM1;# z?-d>oenNO6m>*9VpvhpaMI}!KpA?=Cj=m|vA_(sb-wOUj_;&CY!pp(m3U30R6W#*8 zAiNd)hwy!13x$dvKLXYpb-@R~?DnA^)yK-{ox0F?3L1K+F8DB5Z`1`p3(gdWo(DH0 zqqSj~Xf2F~(LtEm(N&m*x4$qdh%rn!1w1+!jXA{nI!!ck!E=QhgKrcr0N*0q3cO6X zEqJ+b33#<|ckqMc^jJXo;hoHy^_Xx4_-`B(fnC5e!fd+r##>lmBlDuDGX}2<qaqmZ z3L}w>kAzvcJ`-kSz7Z}2|0rAx=2W`gj>dw<j{poEW5DK)+!N>#W}yoR4*+vuK{JEE z)rCvJwS`B5>k6}A@;iMZl9^f7N*LJ`HQI^5Wa%Qz-m|ALQ>C9UQ)P%S+aG=$rlTkd z#(3fSV7<Q<>WuyMqRuhFBH`xXC7O}`Z6Vwx8lAu^g_#n1BP}W}L#;Q`f{{?%NNXg5 zS<v)8S}+5x_tApcM;sS3?6mYgTBtMo^gdcJv+Qk-|L9N#1ig_KoCnq$X~Fqmy^$7N z1lAjA!3^|yvCBYT5N4qDK3X`))YAKC!7M8k5!ysB8>MQ(Q6`<<NDB?t0=<zIjDN9> zw18}|-bf2(k`{?&){a)fO~CDhnY>+u+ko}{TG;IX?kDOjPea)LGDLkLj1&#FXyb*4 zfTs!%1J4#70oEIDVRtlGZ@dLh051_U)4+EL&jzm+z8<_mcq#lh^oCqmz6%-;h{hW5 zF5zw9eZu#H%Y=7;4+|dvKP!9?d`kEbm}`O<Nj7L_$f%z-_$zW0LIA?|qJeBQ&I^aZ zmxMXC)SGi*o;AXTCLLmd@(VLxd1WKjv%r;v>w$TFBh^_8Y74VGMKeVxhR{IxT5!H_ zH*izoUf^Qk!Qi&SL&5#X@RczeBFu>KyCu~bvGKxq7*k`6{D&}GG#In%g&DI&!i*We z8qp!f>@H!(OmE1AB4e{b)SH3t6=sk6fN(K*mvB4qKD`|omODZy6AhNk!@?|d$AsCX zzD-7TU@SinX3WkA<6(Ry%!qw2oCH2E%#pj^g9~>!{xtp+4Yp`Dnn8My0`?0tmSJJG z4b_Ah<J!Wka+$(x8yX0=2j>g-1UD6C4dUm}C_Nhmp}lB~1D6Qj0KQIm5xBqbE#RTT zOTi<A?*Pvx=fn#2^}=io7YVabS|W^&Eo$5)0`q&da4ql#VKz|r3ZvmO9uP)hHg*Z; zgZBwDRh|}Z4SrUbsd7rV1pJz2q(4jeJEAcF{Gsqz@LA#U;ID-zfqxKY3jHF?6uK<T z6#7e;DHMmoz*J!hRU#u#1K{dW5n$G+EzFK2Q<zEDKsXtkFU-_xD$I_gSQzb$(O$R- zxJ0-G_&VWYaDU-wM+k#O=nUpXq>1Q5Q6`Pq!n#@tGyfI|v%oG9P6gj3%s{Lb&INA} zW`A+7Z~^#%M7IC%jP-SwXfULEgj<1+lN-jW+)3ehsJ|-A?)YtCG?vB(!VL5oVFvmu zVFvnp;S}zlI443nG~$r<i3qX{_FcsZ!XBts6!w9u2{S;c!c4ggVK{B%2v<>Nt+=GJ zU{AYpO?-Z>Gu58xVyD{5xpsH8a2_rz`hKq6R=rMYKF@B8<*tk7+1;@|<PAQ)SE=*y z_*G5kW0X3EhZWeW5*OIrutR+K0;qmdwr_!5W@7d1_!}U;te(Wfs<&PFZ-k-sYQT+9 z-L4+y<D|OG$J?sYO?aG98~FHM{fCcBswfJJRUTBgM`7`(It>xw$yx~2%pGdMLZ}{8 zry!btsN_X>V4W}?mc2_IS_IAKl<#J!zN`lDF-twn$0c<c4=eLg)%h0tgjMpWO1u?j z|4_qkwdZ0N`RQ9>XuZn14UgSw{%v-SnY;Sz=?d!LZFboFLY=zJ&Ty_re?M3KcAK4M zou8}sj^{46!;U=<Yc}+z@%|K>Lp-X*g%GVO>1x$tyRP#Gl<nAt^w*&tEW}DRwz#X2 zO)GgxhGpEY{7YamcP-w*)uJ4?!a8M!t>y)4;1WCYe-{`xZj|3BR~?&>lv(!568jEs z^hXOb25hf>!vCZAU;eX(gZ^G#{H2M4W_eR!`k#H}PeRceLY>5ZFpS;d)3q^2ORjU4 zimvxnD%wsP{qT;1qTW|N6>h~vO_%4ccx(k_@9p^GvG2oQ*V>Q2c15;&*eU)YAFjOw zMy;p8PG-zQYa~>Bx5DMHr&2r~{t>gs7@o>RBYqG5c&d=?c%GpVV>kY8`WRaySrz`> z4`UYH@KmkNzxJz82t0_(i0nG%3bk&9-7$fu+Z=^vCuoHuW7Q8U?4H>C-)g1(pQ=UB zGpk}dziuA8!-TnMS{&XApI2>G*^gVV8tURIJJpI<s_JUHsyS9QS#3XO9#X%rwtJhO zsP1d*LUV^&x(3oM>f<#iO6^qrwRYoPTv}~T<`9=Bu;;9y(^E%6G2?FPOrwrDtX@?H zU>4O=;B6g-HPwqmf`C!<6f8)i!A=nCtyYh(Maai0XB}$Y8g+P`ot(0P_HU*c9!Fh| zTk*|XI0hL65zeU#>+A`zGhEsI@i?UHJIwQ{{d&8gleW5nR==Uu#<aSTA>n?RSb#TC zj5)fQj%Grq-Xa>@LVH~x(vRoY>u^=xU^j;!y*Jq7&5i1r4ds43PP6f7%j)T<AE3yu zQ}xEvr9<?C-<x7yKBc{!4kPB%G&mkQ^rOW++K=V;*p1=Gv-jAOvGz7^qg@G?4RqXS zH%z<<Y2*&%`DhIn!Jd(KuUfXzu4#EJ_3%c!hS{a;g^l)&@op<5uZ0td{$JTf$z?mO z$`<diyLwb;k3HyLuiY8H$9^mrzNW|+Hf+r7DI<psOV4jyn5%LQ+ts4^|D)O@_v$T{ zjSK%rv*>>`^K%<r<z9Yn<Ew4v=l;)L&HTK=tIg&W{cW}pc5>!7%KuxY*f{@c!;PE# zk7j;u*~P>5@T_QO7Bv)C{_Y^NJH_vFvOmU`$?RJ3OF(HVUsJ^OBUn46f3wN#a`D?s z=12;^FUjnF@e83kl`kFQ%6u#x;<y{LsT4R+z;7;@!!7(OB4Fifgiexc#MJqb)J%;r zn_8~ipx=Xp>C|xH%HXlW9Jx&v=E!X(kHMnlS`g-oMs09Zn1k3`ggHW6OGXND%(zjQ z5#1(?A%^jgFaz<3Faz<pF#UQ`ID_#&A_Cq33?9})4;p~E_nlk_enXfewD*MDf_cmU z&9G1Tfh<|}^Hm&&Ea0bO{=8Q)mz+iU*_LlbwWtBE2F?~{YUc|x)OxKE%%p?$S|e~1 zuwH8f=8#dZH3GK-_Y}LGz$3|0R>uFsQDd?Q2(Yn`EQM(CReYx~iiWXD7?C#C3o~+C zg!vk{U6|!=hcF}g6dCzNcaCXB`qT0YqCv~A2-Ct_!Yq%cg{y$M&xH<gO7I*RKG9Kq zhc}qHpzrVoGd>nHX$Jq$7sr?>ogAfrQbWt!5<zBw>IgGHIl>H3o-hM+jW7e$LYM(+ zEu0S4cP`K(etKiA@I;zH31#^+riwtmnGDzI=u%<kz1}qob=Eq)6bPIK-YjP7fbSRP zd&k4VS>QdwIp71rc-t_Z((8`kP-6(kM1uwD1>tMJuL!pSza`uTtglUg-QM6YMV+sW z-w96!|17)!d{Ovz@D<?|jDH;JKV!Te8b0C8;Gpom;1n`ik92TdVaBGuFk{nLxFNVm zm=P!zW?Rx;m=P!;N8xBU2-k^55AYD-KHyQp1Hlu7r-P>n^Tn6P*f4O6*$u*Xf^QbS z8@yC_75Hx9HQ?xa5jH^BBFxxt7v2iqDSSUzZ-Rwqd%;hO`eE=<;a9<LlWQQ=z#j^; ztb8V12dtL})j;~QfSeNzCh0|CCg~MnCMnM>qN90WpD>d*L6|LLMd53~`l<w&ZwJ<! zUBR8f`g#O#cW`69?g+wY2t{If8dzWA4fUJB?L>VsxQj6761c~U0b)}36J}EDr9e<$ z3D!%2z-z&JDG-?DOfLljZ$$Zvtp$Rx0~{5Ho&nz?d=$KnjJn5OOD_civnuM1tN<o2 z4_KiYrX0^XAvXf+r9j}O;HO2s1^8L8J_fZlgcn7FN%y)ilkP)d_I{rUcLjeVJOKQo zFjMhY;o0Edh3A6}j4m0V>wz9&M82O95MdECc-#yP-3qQQybPQn%%pB0%mSM)yc^t9 zcptc>x2)zl`##rfqK;j%ldQZVJ}bm=xTY0y8;e4bR)9{ETs3`<^=Vn?ce_y>Ucg&l z!7IyBwepI6uT`Z;HTu(@gBAD>{|VJE)MY#@x2fv<myP4znyP#LvbR`0nyzi?bTdb- zUFP6*eC=uc9aWZPI%7?q?PfW6D{relvz$3r$DV3n9E^@r568jOuj+D~lVe^RJ2<V- zcEVPmRCTtUy3U7nk=<&x?W9?Av-Ml{UTB-k)G^!1aE@hTw-Vp3*Evx9NJShdMo@|N z#x9fW0p(!t@sQEpvFvx`yEP^Smcbx)|LmiAdkTtY%=|gW`RB|wRkP4dj%(bwks7MZ zx>oOHW!*f^-BlZYhd#`_35i|g#!laXyZUG8j;{Q^$$5TMS<Cx~icfXwR{In^zx6FF z{Cz%~#|Odn`huz?)oI&+=L*{OS%9p!fwH4_4;+yly~p9Y?C8a2k7rVy)L=TjaP7r# z$y%?zPjzaUAF4oYrvURE*VcB@@j5iFw$rjI*JHT(-^Bts0;b)fQzjaYf`B?&+o@z$ zSMSw!nk9b;fBn<%i${+g;(~YojH)n|6dI&*(wx)^Cqi%_ave0Hk%NfNO_4{{ur#M~ zv@>kXkNgLo%!_a>;@rq*0q)nm44xgC4)s|P&eG0|EJxDKh}6X2>5+kO2>W&Kg3<V) z7vQwNwgaC7hX%%Bpv<i<fv1T^=r^Qw;0TMp9ZG=lz{z*OZanwv23~qc{g&orA>y^t zos=j)&YBT+99D!Ac5#tXsMwL~F|2SR+-~ZL#35GR$QDGwjoc0&e33U1HEf`L1=_*F zQYa<rt-A@+-vLJon6Hssgx8ED!6diteh3XO_uX2(5u#8NhA7dt(1_WgLLMs?;klhg zglChQ5%#23<VE#ix|3_pR)IQB2lImJUB_vrBO1QIqdfwl#IV|2$7z7mr_?KTP~vet z-uXJt0F>8~y3Xio{MZoAH(!Li9g^-tSqe8XnW-I<HmjHGI?0){nRU&zT8|_y#tOI6 zLhqzGv|6l%{z*5fV1|<%EkyE!uQksgCZm#$AeX{zwJ;`$6T{*5S{Rq~GSV;HQSW=5 zki<`n;Sw!OO5#rOFsAI_z?39@KMY@IR${Iu@g&!9FD=YUIzR{do6O63Nz17-$gJsN z;ouEPeAfz>n)f4v7bfwgDm=oR1>x4DgABqbvjQTqH0coIHOAyN&O4K8F)HKC^AJ`f z9i?;Ab-dOjnGtm<!>MCVRy8wGy(g&lna+*4RPnh?2UA=L>MN>VP@$~yWd9t&h$VZ! zET=)8{&e|kW*+wCu14VvzshX&?`2pbR~WU>7PT|Wxz=hDQa@!ml?K0pSSL26DJygu z`iae$A$BMe;Yw^yc0<$1EodeXKX=L~Be5kp6k3h=CblAnL+w!V5{t=+C|umi?w_rO zXFCmZdG7c>TYvY%g!L4asxF5iYc~9^Q1u(2$JPp0)X{7wrzO8(V(V`aay7!w0!CyQ z^Cxl(qLN}Hj(`i;`a6x<&w`CeGsN1A@CpDcQmnFaoOG7L?m15FI{c#R@A@&!20~oX z<L~w({0oOlsNS7dOeBSdt93a}W-?c$`LCn1{%LR)dw-k2LI^Is2bcP2m-=g$a7rGn z54c3LKhtghpy@Q*4Hd>em;t9faBTB$NZTDsyV(4z_nQtYW@s0yZuOAocdJ?ToF<sS z+F8#@ixxu1jXcQwjPPXP2tL?Bu>Fg<Cnmz#B_py5f6NG1ZCH`D(2a|{0;4uIE5Z}( z2i^#yAzp^!U(U^IMrZ|tvx01eSS$Q1$#!TiW4(&(3Dt(v{?yg&Ah@B^NO}Jnav;Q0 zkNs=OVZ;BWnq1$h9OP;c|2=;}%??G?N+?+g0kyNfQykP$k8Sr2T~HV6I}Nd8E~A0d zFjyU-^Y5lZ>7mYQWCJHHXCsyNPJ-8MLx&jPeeWXyxY?JBVXRLXzQ=fUmH!8|4;GTS zXvbex6>jthF=6}%$vs08)ejAv%2o5I{nVX^bN|phM(F8j$gIJk79mx$p))F&fl}l| z+CtwG!KS>1XsXh~YJWqg2QD;qa-F_rUo|+_X^koVExAtBl#}qneAeP>ZPNi)_rL=v zR6&{;sg(oj{ahy>$KeI@@Yt@}<T*#p$I9XwIdx5|slP0zvD3mdZ&c&+oldFMk*4Ml zXAFYHwmWSH+%Shabc(Nl**}-PmG2z3&2+W0$f?wchZ~#C*t`~T_o}Juq|tO7JT_;g z<1d$-o12bfK;P^not{Ip>~WfpH_W+AmL#NTvn}dek#m2K9*DWA;E<tR*wh2Bn=OwZ zu}#IwI~pk+b7ljbVaH5o?x8bpP)`SEBlWn}ve^gf^QP#Z`y>C%LsW%V#^d;JZhDO_ z->;fAbF!PWFqqFYg(K%-vYCs_Fppe@7=h2ltQqD}76`L<vt_h=j8091p3xLXl{9mf z7IW*o=`)#1HEu^&X!=d&MvaAxa=gjY^lSXZ^a*ILSwkmtg2`mY`*fKa-`vTK>MgIW zt~Sv|o2c1l+Q<<G?uDhlHEZZ}?4^Yo?=r!9$C%%#%|5#Ss#)Vj=G!o>K`)GJ3mKI4 zW+|9aGdDG_g>kQ<{q?xH7~j(z#3=2<vKlR%bCwlJPzl9OA$FN|EOs6=|D%2?b}Hhi zP339r%r{S{g{_^N%;D;<))*U{P+4u9lUAFAvR~Rb36^<JSzJ3O-n5DXD%{>_gt5c5 z?VSl$T%y|3-ucAbrta?Gq~cVEy&arRkbbB1m#W^;NybpAprcbOvY%-cZ*vqi5)%b! zN6W@^L}@jvm)+F~<v#o~WA}sea79$Vm8EI7s82dOhpkHSYI7H7dL6EV@=Z56hUhjK z<p86E?-1>7JPRe#Q>RI{ZK`pJlV|Q!qf5}dy`}Cbapu<i45<-*!0cKN;}oWKkX>T% zMc6fZcK554u1>|A0Z66redhIln_*9B^gMu)6Mo0Mt6bUW*&socc6FNNy#yWqMqM7x zP*>-9kL&>IM!!2@^>-@P0q8$Que;UDU7c!HL%;e@S7(&@gX-4JscGJ)CU?X5^A2@a zHz&LDS(M30&p+zJk`5<75g0vBt5>^WxcR60vYS&6WBA1GPFwRG)vvqr9Gt1%!>MHz zB&ZfWoZ;q!W%u@QE~L5%n3u4Oy8mx&rB&EUTSWz`nw82@W;ye#|J#Xq)#6i+clD)6 zLfM`b&IC8MyLQwDXL*X*Nd5Yx(<prPq<WJkMMbLM5XMA}i^}@rxhC2eC9!-CT+dyz z$lzBWWvqNY{5Tnff<J!VDWCU#1Ouh=sq0CwS3X^xgSM=EN9zePr~B~J+hq9`k6#{& z9;UQ82Y}WN1-E=l>mD-dKYxqacBRIc;~lehjJXWXOp7sBmzgZ1_}xj)h_SARnK9PQ zPgab}*w|#p_|FLZH*;dbOtv>D@ch+eL)jq41IP_yyp^0A<Bgb3H1lHI2DRO66yvkx z{1~@H>T-^qjXO_xCnHV<kEtOiF#bJ6fd58cVU&GiurQ}1%MW%$*I<kjbtcjj;S%sH z;XdF6!h^sIg-gMDW*Huj0dr<K%1}&%pr@9>)4+Oa89W=Tr<TF<z<O#K%y|qwwG6%u ztf!Wd|BR)cS_U(gdS)4nT#3yrgBeLZvkXQgqp_)F2#n>Y3@Mng<i`^-WBHx%VDQhv zqrn%2CxEXAGXilau(Znv_=Fkg1mQ*CikgxBiy>4K4fdg_!gqr8R5Tn~2QH*KnrUW# zOW`7LTj6Hl&cd8x>LJ_;+*i0Yc(8Cg@CZEz4o5pe7$+Ltz*B^Kfc4f@n7IzTK-33< z7Ydhx7Yj2b?i8K{UL|}Jc)c(qxkWgtAZ!<5GkB-)ZZM}#7~_NBCxnlK4+*~p)>G60 zd<6#UDQYk)#c7%WHwJ$y+ytzrtD(;6OH5Z|?F|Gbqn@t@GwJkvHMkh8=c~c(!FswH z%+%7;)!@$H1QbNN!xZ9oGje}$HQ`clsxVV1LwGjZA3cu^3%5W+&trp`M0y?@ydK<2 zEZhgaR(KD%FB!#~o(&cr0v;he3_MPFEO?6Wc<_8O&mW!)VWDWu1TPk5iM><!Ht;Ip z6<|Ge4ZB;wdg>Z{0Ia93!OSK-bq#(QyjSeL3VuTP9dK07W5duH2**X^GcZ3nGG<?b zUlslatmn6(egXV}s9y%35$0ykuY|eT^Lyb0@Ofb_t+*89s8IpJpQ2F-Y@<`5$5p_7 z;cDQpFgJu&5>5eE7fu7$7R~}^3UkwF17Qw)^M$!-w5gs0hiA<p6pO~S;P%3t!zmH& z3BFF4i)8u>j{^@Co(&!)ybwG=_;&C#;Z@){!fUyV<pvQpf^Qan5WG})7x-@BN5E@^ z_kuSHKMmd{d>s6M@N?jU<ce5Yfo$TLV`Nsp=fF`4ta5q|99#_6bKv0i;CIDBC-6tY zCE(A5*;wiMaF}OfrRT%JtcrR*9NZhM=flB$!3J7X`a6j2zn&0>FdXW7J{-)d!uFen zSUai+vv$-Jo(I-jW?^O#I9t^30_O^|>hf48x^q9cx$q-ko==`w5%vE7gpQ(d5Zq0e zpCNh+p8^jQegj-8{4scx@PEK_$#|hm0pBQ`1-?a?Lycv^^});a9$Q#w2w|;gGy!iE zZVKKeTnv6lxE=TrVYYye3p0726lQOEM0hCpd10pXOTy7<5Z(}h$;%V(7z1_~9}C|K z{#<x5_&>r+!9NKz+4=5FyKBKbX_34cY`QUi0PGds2@dM3fMJMP!1+E}I0Q}>X3JGe z_(QPXOA9khc6}`{1`1)Yz7`k^t=P4|;2L0kEikwiSYHbaW_IXnfx%7K{_A^zArwNR zl%9c`g2xCq2Tu}i1)d??8az+<TJTN69l*B=cLLuo%v!TTm^Eb`ISSAEL)au5rC`qQ zG7#gyJA|i#9~EZ5zF&AQnDag~&n$aJcq#Y|a<$lpTYW7sm|gS7qFw}!el9{A2>M!J z7-9_cwZLG8T3-tc?gRd>m}ep4`vE-|0}cp}2Uig0xU#D76mW_#BTzTSQG+q4CmIXD zjf8Ii7YZ|GJiU~jEd;j}z75=2cn!FR@J4W7;Vt07!rQ_82ts!r0*}*sZy`JkVTx$% z0?!hD47@=25O|^R2{5O4=+H}Go>)kJ1-wf5Bk+3RZ^2uHzX$8Rx-kDE%Ac`QG|qwb zeZkQ99sGo-^W3|qg}M0gxNs1BQkcD^-rNhj>EJg-JsYg|_Etw0!Oice4n}b?cv4Z6 zLLCSfMI#H$wNF&92lfiH!{F>F)tiGW2(#QI3$riaF-J7RLS09=6r3eI8r+<W`iY_x zHQM|m7#)S<VW^vM5ZqfBJ+(1VI1yYbTnRizm~8+*JkbM$!{Em_G9z}AFq__Gnvwo& zZdZs#Gw?d$_TX*8tOYxS8Ouk7dxD=79soWnJPdq7cmnthVYasK3(o+5!n0Qxx_J<I z_!D^<Snmu5uLNHZbp_U&fuX($>>`<Ho+UgaybYWz{4h90cn_GzK+^nva3kU96A%hS zcoN)+Tr>7M)?GLi>V1UM!GnY|z{7=^q+^BIlFkrr37#*^vZ6N|!+oaiZF=u51Sant zVu%BWmBItTN_a4Mv+!{6{lXK#<yZbPN%_Ty`*TadM}^0NPY90(zbrh7?f;u1uvOyZ zIW5lze=ZCo#<#*ZgU<;wn=T070sceyZm@;AMt9f~y22a5{Dw(&W>ZCS6aw?9nrJYe zQib<{GlZFE^@Yp8jfI(IMZ!;kTL~Wl>rKUQ|7Eb=R1AI<tTz>dUk69^u3`x9LeRU4 z!S91dibG$4d4d>2{Udm)@UP(6!WY5U3)?1!W5OKgFBRsnU0)FlcQ_<p8&i)O9EbCJ z3q9aG_cq~T@I%5}YW|2YXS*L4<~_7e3U>w{5$*+kUbqzelJE%d8^V*o@9C?6;qg=m zABzU>1p8cg0r)?{H-LW<UIhM4n3p^JS9mR$Ut1WNd%#}dP2iyLqu>g{`#Jtk7J*~< zTEZv5b%alXbA(?7=Lx?KzDD>Xa0}rtz}E`%ddW`0-+{XeUjp|5M;TJbLY)?kAb7ZN zB6zHD4e(^)Jn&560`LOiwqSi-Fx=$Y+LcsKjSbP1a5BouX5kdJ|M!cK35|z^bHMwB z8-Sk@W+!w^xGDGr;bQPB!kxfx33I@5T9_Tur@}+PUuuqGGd6_pL}LW_XW=p6i^Ai; zSA=f>$Aw}syB+Kkz6+cnyaLQa(HZ*<VBU~KX0x3t%omajz4sOx92(ab4Ymi3g?EGX zwq=-k6x>SG**551%TQ+<pm!~Up8@M#%iyD6y=xi#ELiVa2EPc_yOzPx*C6O^%Md;S z^Q3u(^b_zxa_!i>-eO@SLhLGFsIv=RCF)6FeHAd&na5j1o!NSya3k;ma$0OK@|3;` z7(xUZ$3&w7_yysLVEvsPW~zYS5_Jr6jMKvGkUkY=hxDazKKMJ~0`Skm?3^wNw_y8! zMT9och{Fhjp<^NP3YUPZk}*sQgHwbVxVplX!S#e0xJJV0ZH+?V6fn>KF5fKPmK=qn z^`ODiXQ|N;+(WoIxUX<a@L=I$@CadcqvM3TfTsxe1?ww<;U-J_0#PpoFBBdPj@~K) zOSmE<4bhkxn}wMj{Lo5u#(0k~V|+lEF@8#zF+L`YX25ts7{%i6UC1mGJjxYr;woSW zr^QfPFqccwvku@dg}Z|J6`krmz<-e83LWCoD{>y#6>ba;2{!>J3A6pED$Ep3(R*)U znI6{_jm}`+*hNP<7-=Nj8(b(n0Nhe|Jh*%p@+@#?QNIz~LwE_eukhVq-ta~DSD^eE zBSc{1Fix2Deu^-MXtRV5ffooL1uqmn4(75WI{F;=PT^DFRl=`=HwnKD<|2tGEu4X{ zS2TVEKP7wtd|dc4m>=_L{txi0!j_2<lyC^Fum8=8WzBa~2QzE*^}k?d%|%g1)<lgf zA~0{_&=Al9^TsF4tVs}N)>IT`*63ZxFwd+>6?JA!hVXcBec{>Q#=<v&i!>ws7ei<z z8Valz<iOE~z+FUrAGoLR0dPNI4!MR19|r5IfMNFtSYHJUejYqk%&_U5FZ??A7JU^k z46*6eyO6=(g4c_o^I*O680x=)_0D7PC9vLk4E__mN6h<?1;@$RT+f0kC+q`raUs<) zPBlId=KQm9Mg%;JuY{Ap-wU&@pBILI#sy(ET)sp&ivF6OB?!~Aio*1)nlSxJ6~@D; zr}y5%GCgZ78uYA4I0f8FI33(hn1SdbTp!$1I2SxfnB#-t!fZ*$3bzAK6fR-=e-i~n zg{|JL!ferQ7e;4jtPo}()(O`IZxTkOFzypZ3L86w8MsG<QQD3D!ff;ok)!aq8HA&v z!IFPMxD)tg;qKr!g|7p@FWd+GiEw}L7s7+U-wF>0pA#Mlz96jI|35?+3k?g6JyT*l zI3PR;%#9gTp9-!dJPVvfZV=1+hQiGICc@17X2Kjdv=&B<H#)>Ps{8e>qQPYEDa>Ra zMQ#}LV1h6mohD32=LoZK-5`uO88-`81TPilz~pY>THrN2`-UE{cUmtR%*$P5l%}@e zeZtI+GT{>NVc~AzXN7x!PYE+SUK1__zaz{n_)vH|{5Q^uup9if@E-6F!faT65k3Xx zx$O+x+u*;1&ww3NBdUJ}ju-wK91&)_Qd#(Wa1C&j7Jh<|CK^A3vxI*EHxy>$(?s|p zxS8-3aBE@q1s#O>9@tgb3+^S%??VHGaR4aJUKSw{8l#2zy=S5@UmT|kr-J7S^Bd2N z!ujA^gn0nyGGV?eE*CBVuNLkOevq7p^hW|1yR{IT3wlhLb@ZSx8<S^**_b>h%<}P~ zFw4a2!rj5|3iktlBs>`WneYVgH&GGhLika5KKNJRTfx5zF9UN7mY9dW0_YK52@VLa z1@mhM&8!Dk5#9){DZCAwE*xc{%NF4=aIWyv-~!?2z)gi;0Cy!f!te>)OBjP@V}NiS zFs}ok8MN-kXkj!J#zbL+&zN2j`A<Xn5ax;olln&CHsD)?JA#)9cLgsO?g3sa+y}f- zcnEl#a4Gm9;VIxpgy*vTe_VuHpz);eo!}$F%fY9F*MMIWR^WGpH-k?LZv}r(Myvwh z^H=dD;Y6taNzQ~JJPo^2%mP~|zc5?FkZ@}3;D#Tjdsf%B@(-$;*Lb>F9iLQh;)#O~ zQrCLA<H&{ScvzXwsN-urb8vh?(K?8Q&#K$k!LaeX`hd@r6DnK5(mXXEcc)l|r__rS zcdO*}aO0>NkB8O#4RvTeRPR*24N$$L2Jo>)J<La`x{QbAzN0$dLx<l}_uvUb|G5Xs zC8t%>jS#=VPHPyxRh{NzhsxT7$IEIy9#)l))r*^8=8Q_-46*kaHDNPCyhELZh|L*! zTRd~E9!YBF7Pw#BM*YsG-A;AB*OP5lP^pc*6;$C(IFMnt+HkKY!@1#ROg5<J@Aafv z!FAj!vTmy<?9^I^0lPkcA(LW1h~H?j2Sh78NsZX*sq3^tKK>dzk6|m+ah1frt)2`k z|6%n3weufGBdfQF@DK*46caYTs%^{s6;$yy&p$gxR`a&E#)XY?bM<X+#dno$+2+Z1 z<Ex;%GI_q~P+PtAuqQjc3pz;4@^aQ&4qmWqFL$U}uEV<wEZ2LhO5N$nP3P7&%f&$w z7#H(viIaH^3PjwG_~T@=ipBZj)$E;~E|vShF;AS<<#&FM(~i1l)O$NUsUhx)bMtwm zGK%9l<=N$_ZPjvA_AXC#^K;c<m#10P`LOSwo{vz5<GD1#KVvHlC&dSRYSS)HN`;4^ zV<d2aMl^w+YHmtcuU^~bsT}2AwD}2KPcScmrxVOg80$rkoWRY|vlA9UeO7`4$7d#d zg}*Zr9>L$~376r}G{gx;<A?HNMaT{exX0q`3G_cO5}tv@6Gp-gq+O$g7vN!f0w>TB zC!U8Jm^K||VP~c16fK=p6L)*6Rk<Ev3G8?PD*i3_gWV*p5sLU9)t23!%82O`yFJZ{ z`Q0|~F?WF^7_R*`&DBL{?BJ$S7*2>l+eo+wPfTc!fl_20{<IC+CbwoM{;2XE@!)o7 zN0mI{>0fOn0u^j$Hb-#N6S*ZQ*vY&E7wRQ8QAZx}6kDl2g<H3)n4hYuk9w+FRXnQT zQBRursv7vHCm#n!EPvFKjuR>NKk8X%)$^)?J)RQt8FkAZPc!pJb!3kxtqb=@ga+}& zDk=VT1SM3;H4IhadB$#NBqLHizBN)PG@4u^{u87^XbKNePl>l^X4*^yDBbY4aaH}j zo(8q}!8sv$HWUMh;y66xx=^X=6xfVAp%(1*<h0~!RO}(}Qe!hyK7pqdhZ8;krx;;= z%f}vqmelTrKSn|kQqoNL2Hsi;`_$)q5v}``yU&wWmmehkU3bA$Aig*3`MYr&UO2ug z)w}a*$)xxUkLtP4lToEI?E9~yvwohWjXeZ$Fcp8lS^<}mwM+fAOGeyMS|4x%rs9UG zm-l&aiMcwz&oiJMw@|tX`w@X~!gK^JV)%PQ35)tIsKvjBZ1gXG0vbj<zlZx*kgfPP z$t%fryy>VFk9jIpn~d1{*BpadAfBi9`qz@NhQEWOj=?}3o>}d`=N2Tq9p8@u+DHf7 zAa^JEH<A7EpQ}F}^Rx~!AN}`ph+xM*qdGtCX^8c*3-AbXNsxaxT~3exPCfCsCoSgz zD(yW7ciYBuYp{Rc1i0Q2`85Q=h-*RZ$Hp;4GnBm_NmEGI%eKOe9`R$SevsTV{uNcc z-&48jcTD%ESP=T_`)&MBzlW#|j*oZM^!=WuK`w=`&APmmDB*%SxZhLEb8_~3u8pwq zFtg1`c-#u>HFvA72RscU&%gp!4YOEs`aT7BJRb1uH3zDePk0JYf@eSB8D;KKA3Wiy zf!h=>@v&W1D)VFqmcV247gn~cA!Q|Ho>?YN<~erIv(;RwMm(u4Z+Ozv2ey8CQrik1 z@??j#t!1=DpJB7ZA#@j&KV>jVagqYw67k>M#62!GH<rEq6lzz!+YoE>9&;CTkcLKz zHnF7wOoZ7e-(!-WMZ(t1_o@8Do(_pxeYaM3kcw2l>#%1CHV%Dv*i)@OPXLa@7s0#2 zT&7DJceoVZ2a{&{R=8gD7BKN8V$-iw<7Ye*DzAmPKy8zC^8)O7*(4dwYpDItc)C=W z3FE=X&EDw$y^NdDY@|v&f<CO7M_q%b`Is7X#4|a-kBXtW55cMCwaeZ<;yD|1xuU|t z0SNzB&MTRoZ04z{WkFxjq^To^Pii=O=I9wS8;%`5d*ry`Ge$MU|JmcGOf7#78$EMc zVWWbAhVraGY3}%GJZ~iL->hZc_Jy}y*-x)}&ien2E3NN~OD=o;w5O3%hIP@aTSmWO zyM%<}k9VY)C^7sEXZ|7i`Fos<B<3&75`|pluP2!UIQ&@C`CW%UUFt$H{sr!H1#NYR zJSl{n1^z3>Q9b-+&q$31(1;i2@HZliA)rxNn4NeH;UaLFFkd>#uf$<lFTWC}HMohG zX$x*9+yUG=4x?Lo+!=yCrvl8Ovp%N+%%O8HvCs?5Zky)$mNHCu40yEg3~>3CI5&W& zi~3@4`IR^;z~xus+ynprz7uCVxcp9>hrs1`;v5986^BlOHwwQ9-X{DG_#xrb;75c% z1wStQ1-MN3d+>|kC>N2j(Ph_3?hSrdxG(r4;Su1^gvWt@5S{@3Rd_P^cj1*_wkmXU zD^Q<n0e%P^7WIcYyIEC)N1>4-d>qVC2Q9w@t|$BoxRLPNV7=fNX5Izs1;^lTz<R+k z_*<}Ea11^N)(eio=fOPbDbb7c=d1JxaWn%wSvVIwPq+wtvv4c0KKlX=bpqcl>U@1( zBitW+kMJPyR$;D$d{B4-c(-2N42Srw^)b<y2R<mwD`vm1R*_%`s1!gqsT7hVB= zS9l%xBjGLJ&x9WWe<K`y7=pex2Z7)+%3noeKlpdyGO&SC&+Iq?_6R=*4hX*tX3e0P z*TGeU-vZYZeg~W`{2mxr=-}-Z7EVK8he7@nTp-Nvu^c;6{YP*c;a|a>g#Q3{7dFwT z^bz)e2MD|1iDWcr=ogIX!un<*4h5-^0F4`kBj8(vD}k2@vlUw|oC;>|MZ0yt8-?qG zw+ZKh*)7ow8>n5vZNVJF>zjpG{hp)Xk5#`Hg<1Vx7aj_JS9layFD8b0Ha>bWF?bSK zFD3@B0-qQ2_ks0dVyHh1w$Sa<uU+71K!m*zcx4qeoAW|gZc{2Dl2m{l%Yn2k)X zaBXBqfp9%=YvF6a9fhw2_lj}U7!N@&4u;3m!Q;fxd@x7c4A8CMS;9-e3xrpJ7YeTd zFBaYg)|bA+?so7hQD@25m%c-NFL;Yy-3;L%gzaMJIC!V<i{QP&Z-So?W+CM$oq_uT zd|dc@@JZow;8%rz0lzK$8~6j^i%|$?M7Rw8O877E_rmcgz2}8P;7h_u;6H_Vzod;? z!T@obt-famoDQx=b#&PnUg=Zv$Th$`H$&enR0~3VF;pAeSU4SAB+OFXO1KHQop3Q& z-?IZpJAwyOJphlvBZOHC#tAnDPZ4g$_McnYX@T?l3xvCX7YcU;FBTpMzEhZ8@G4=} zj`hM5z*~gb1?#(Y;QlhOzFP;p0{o~pgZ6(lgkuzfv0?BF!bm-XTL`IM8T^(oC!q8i zV5qY__?GGz?bzUR!nAuqn0EgVrd_r`G*7#Ra%#ne%erQGGkjLt&T3Asx0`u`dOp|N z-7>nXN_h}BsnK~53wx<2D1NV;Mi86#QGFXhEL9Ic#3a&he0-zYHTKTMZsEg?VJ7o> z70QR1U)7L&Zw_ACj*SXdP@D3-Vay;slJCuMT4H4NtU8_VO|#5m^=H1fu2Z2H{i@nG zIGm(fH1Q@_U5Zt=Cf>SM%3?JKPrQ_EZsN@dE?kV>5q&-Lwt+sB6X%!w2m?-A6oV@& z?+$+&-jP}qc(eXKk5f%4@K!OeSsnc;%c_!F_E-U&kDfva=5Cg&e^y&af1kv82xS<D zg=E0De@^0j92Eq|Z}x-DILqP2ojBKdfQqj7B5dRM&Hqrcy$4}WAHTT|?IEnZhKI+# z6K2@^tHBo|zUT||BCdqK@=V1zhoemEC#rhq5i4ky#{qFR=R-8&+N@VTR#e+={2g@s zeA~10Igo*kHZWuty$OuxPB15=x3R{VR!@XAV0)Udn-B6FIwKh6o{?y95Uku3d==_9 z1{;BI2<E};^}%BNT@d76!ui1?(480L`FnGN%b+qR*b%z3gH53_E4UEu%nWY9-x<Ly z=uQughAvJLc??1D41E%w`3mqS>^;Qh$zOs$-lxy8aW?$iALczW2Wb1d!m{_|{a`o5 zmv!$;WWRqIyz#!ydGmmOn@6o&S)r0z)6`ondY(=MOQ3BAy>Q41&IZQ?v!QMW4LIin zUxtb&SO*5ZK~5yO!JiRQU+`X-_ZtZ#VaWDPFNLY#P-qyzIS9NNOojrEs2BuOwr|sX zYERR?u~#;cmpG3viv7FLZ|k$o6?jG%F`w6@VI#tgY`%bb0c=MGK*<->f}1#YE*2+g z4n+DhEGgQ0IPwuq)in>mt)$2g2$(O&{1!r$$k%kNz~n}`>X8rV&9&wnBL#!kNDZ26 zXZC?sdgKhXI+=^%X}!pAmO8VlLY2%HsMyD3rsPLj(~o{86SHZATT^@kw9pLab_Sb! z>n3oF?VDxtgtubDs;$~I_om~OcWiTSzI7~4ZElWgd)!vXn|o(P*`wJ0eD3oKK8QaH z!@*JTY;idFETrS%AV-V`7FxlXaCG6#R&Wh0e0-M`{1EczE36>Pz!!Kng?tWAj+s`i zw1UY{-;O7HmzVKe2>n;^WH0nNo*yD~7gy$4!Evy#@IK4%aRBX!Z=MN%b(M&3!T2I7 z9bq*TU&2wDzlQp%1!D7&if`$yqw~(}$=s?3gVoxp;+EbTLB0T)eeZ`#sD`5^wDjJO zoz$UL-el{YIF;4P+dOX@Y?xt_Mz}IEou9MJh}jom<FGruHUe!XYW*pY>#S1iT6qtr zC(+?noQdU|CwjuBuwWMdqmY^4QFDvEHL7z<led=6mOo)UiM1xF4(((rwYS)tTv<=n zl{P@59@ErCE^DVcQ|zs1_D~m!y$!8Op0bSA-qyBP*9_w~RXW3)R6J$$tnp)vhX3bN z3OyUfPf<s=`{V!3i~#2)%I3EBK5MC?{lk@2kFTuwvIjbOKZ*M{uAa?I%uqvL2xXS- z>gsKh6t$R9$antskdfg0aWN%d8`v3E5KaRp3)cnL5^eylBg{rDM;OBhg9|R{PFwIb z!tKE=VjR`$l&%$x{?Ncz8Es(@xcrdNQgHbpp=|2eIMdPT;POL4Zvsyibq*<J3a<q- z>uG)?7;Tc~hrqX$A0)aD0*_Ipq5a^M!iT_0_yl;f@ay3Fh55d#4-bXikHG8|IbaWi zj|y|BaYC3W$_AHa>Y}4Fc$GJWOz``{?7cq`<^b#q;bQQ&!fn9kggG#~AlwK1hwyN) zg{nmNr-41foDboz?4yz1-En4rwQMZLB`LMk2V=ckaJu>YaTv6$QK!aX(6U{%9uLiW zIcn8-3|hviv*R&niC>-fK?RjE0b`c+DsKYDET7}$tbrOb0gYcIS)Y2g9=bTVh2xf$ zc?rCxF7_Lw-hc&sKDf-sM3p)bj~%KLAA{9&Je*BPrl(d%eoBMu$0lAqR=KHZLS?(C zaX|_{SD8o4noRP>n|=;0OcvA|Rp-gx8qv*Y4=^_2p!1)xNloZupz$9lVr;S+MyyZB zRhirvro2T<u6HLNw!;wwhAGGJ(8Cm#PS`#R`Km+0tqYLt`Wyjc1kzDEWG~62UDL{j zhZcr%hSR7H{<^L3$J~lP=r=)|d_Snr6mK1~o64VpAzU{#Xo`1aCBEF4U$AM$G%rkX zXc4$uy*&kop1U{#dx|#`Mr%#=4$a7gJD$;tU~CAeGCeV>aze~Aa0(TuV^sU9Z2MI2 z0n5v;PnL0ptz6ZAF=L7u&sP7Y4f?+|Yg@K-rnixqIC=EsVKc`s7(Hy3K^#A2ys9|c zd(FQIAzR6^lG)xJ@lhU^R^CAVNk&cLuOia2d``9{866FOY^TcSXIV7Zr10m1I%^?+ zx^Wdwp*ngnW_Mj-zNOTQ@j%^<G!hM#2QFKu1-2ud$ncn!@nWKxmU{`a4H`p6)uWk7 z!Zb6j?3G1cW#gS>^kP)@GwJ{ymYtwHOT68z%mmdJPkd8;U<ulQNvg(D=(bH#Q<g&Y zq&mD5ZNO}`XbHY&|FP5?wu&pN&@#Mba7*7cs`c?e1y!;Pjl<7s$THODIJ}0&zG!cP zs?{uBJqpuSdL{KPZS{io`}zxa((T@Guwx~N2qVjLntq9?7f{`9hrvmBL2Ju)!AhyD zw%qQ$>QaFzUsZ|AZCs$6g*9an+$dm2hatkafB??m$68+gv!;Rmev=u9j6!R%5|4jc zixeuFF88gWwHO2QXd+JO2Z|je+j)<Y?VXE<ZX(z=zzU}}^qY+8cQKM2Z2<q}&BafQ zy}7KUUEe(Ig3Wgmyt(`Wi@qoEr~J+3Td4p2=JGo=Vs9>Ip#IOB3+D=b_0Y73J%{Fi z{d^_!JWVwGwW1W{^`Rg9_rzWw0(^b&$m_#TFzJ!k2hI+8-dYcpU|_~*++pwmIppVn z)AKPo0kQKz3bL;>58sc!{B6a5a}z5@h=tKS%qXG*t-I2@)^g+2;g#OxpaXlRtp{#N zd(`JEy{VxqwC6S1&l#1+s>D^^jEFW?pp6}XjpRM5^D2z@hN}sDe5-C><-HxNM=Gu^ zH+#J{%hQ`-w(DwbcJgWz?BnY2YH!tK?cj3pmtk10N1sV)>fCB?YE>PE)jAB7I7~3t zXl<i%zRFqS%^0q&pVZcOqb4Qqp%W*ynfEE<+(W}WrDYp6zRJuQBPrjC@YI2vJe+RE z<o1xO4j&2qmrUmSSjg4BRgbSh`TI$=TkFk8)xL!+rZvaDG2cQK6M8A-G<DZn9m7Y~ zB8IoAD{H;UW_MM2owvE!N%damZD(Fl_pI|4R=E#Wyg5T*DK?_^*gT1~?t-#!*LhFH zdwITvWu*Pv9svX1!D`dN#9-Ob`@JdlzioQeO%Hi@mQCN`ElZE)GNF+|{G~FHrQQ6B zjHvLJfK)DTfBz!ONFx)mEB`(=gp5{(zh-c=yj^ZB3~NRQVK(JmV;t3Mj(dp)nk8d^ zFsF=$30DJ;7ES?A6ix%P7Sgji;2VWA!Tf4K^&IdrVUDDi3+I8?niwF`5Qo(pMT5)C zwh6ZYbMlmCiorZ&f!r4SxNryXVc|~TXN9|gPYL$~za~5Y%r63TX9x$VABs>4{!(}( zm|p>CXdL)w;fdgj!c)LkglB={kYzMKAFR7W@FH-6s4oMv^`IF}1Myu$pYp?cp!-AQ zeE_VxLvRwfkQTtq8ur8Fs$lNuB6C8OJG#iV!99f2!F`46f(HvTJ4Ohj!-yJueWv9? zXmCtLW>YmwxD9xLa69lqVJ7=xVJ7vR!o$F;gvWx{3v)=mMVP6wT{F^uF@&9>u@t;l zcn$ao;Vs~&g&zbT7v2FrDZCT>s_<iAt|4M%_>%L1@YCQ=gpYxL)~`#bW~e>JMQVWY z&$uFtxmHZj#nkzshA+}IQxRO1?8dSzMVMJuSD0DGUW;Z}n;HqTHWdnUm#Lx8qJp8? z;I^WX0oG?xL7j6G`Y0+etBpR23S0!%M^S;Bf%Q>T;MQP$6cw0RHdWm02%at68GL;l zzk|V034}$W!K$)Ecrf@b;hEso!gIhIgy(@dkw$lJ1V13W5WGv6S-ekpIaq%UhWRb< z-#9E9%-3gycYsd`?+3po{0x}$ZS?E}n3G84li;($FM_`o<}@g0vuNf6@Grt2fiIGy z&^Qahj{;CWiqxNp(ZsSGR1)<txVms6I7PS$xG~uuD?>%XwA)G;T1GozR_`vtEGtpY z%F;3m3n%c%EG*;5XwUJ89XSPNv#*bw0^?uo$SDAa%?rgm3+7^Bx}%Srf*B5{^^sHH z9583D;eJ#XD1GJ>H1eUbT`XS%)<;f3olWuqQD+nTv~U;jabdOrCxv@}UlnE<dRurX z_ygfm@F#Xz)wjLbUVcCL5Iy}owH6O6DMNkrA%@|Fs>w%C{a)RMhZW9L?|uZ;d{yUT zs4i8r`FLAB|1k#e%~gv}AnjIn@lmQi{siOq&tnIOSN{~_^l_^Grx>R{h;+zP13vYp zneV9^p@Ksy&C;aG>S-8qQd2OB*2DDoOTuAi6yn-ZnZG1fP=PaWqo=BI2A?2yLwOY1 zhx&*?jy}8mpqdN~r?3uMFJ<1Clx~)&XU_aHcrQ>tp7B<RE67bz+wSmZnhC1WS?{Cq zL*RfuP_Lt@zB}u!9_4;wjMF*Z{b!uc&BqvY{{_Psr}L{H#_167@UnlzIK2iHZLf(y z;lb>M1s+1-*tbLQuwLTr{S$51<~l{Zytl!_%K^LD)l7kb7KU2<nfHb+1yGOAX^FqF zA(dnE`$Dicj949mAw1&l3ME3x-eLyXkvb0qf5gMnBFLW6J1|%m4|ja<2SauJ-201{ zBLT}O;2<nnm44w(`9FU*FT=Zeky)1ZmA8iZuSa2z%}uIRHtcKflb$HQ4403>x`Ek6 zGfjF6*9G$>it22QONASO#|X0nog~Z-bcS$SFu%FbZfEdK!mK1W$GA-W=<Q@-!szTd zl-|86?`OWM#;cou_Rhf#c$X>S6xGh>z1ijx^#)%`m!3y~EL0oLquiCDN>z=$lfDmS z>kW@yY5faKpbGo~6Z~Z4##UHU^=UPns%cP-75A-FJ*oCV)$FZKQ<E!A=kra}xr9#8 ziTPUmtM~7f)dl>lR@rWn8(UdzE-l;qt2f??-hp=2yn@J~CHtSB^)AG}-$`#|VMSTT z<Dat5kqnA%W3A`BO!IsZ`+Ek9Z?Gu#_wr#oPw0pDR~XZ;rvdoPd+s>2xOxifSNfr+ zu&m}V;>ZU#qW<89s&R*Q*se(zOzSmRaBWXM>y<AXYKAWZX>9s#0$aYJH0=8r%C_%T zdhWZOKKl4(>5U@YVB5#fMm}F_Xy6cguEFvYvNy86r6E0C=I4mU@=xM7qxfrJ!aw&h z+BE{J@yCvz&SAC>RR@1Llrw!TpkNvLTbzjt9N0311~6b_H78(x$jE@O2v)*%;9`V- z%<(3_|3vPg8xzb;&`gXxsY)(+YxbE9!Q5kV*qfwX+CxW;id+t9{ziA;yxtmWZsM#< zC2i<8Z3r6LlgiqY->IDnwJP_hBbV^L_M|#}$y?a$4Y+5Xfx3=}xoHiI)x`PBpT*)@ zt2RS*jSe!sVy9?sdL4=>160XnZ>m{MO}Xq%PMk+`Jxyi_XMhniwc#@67O$uym+{48 zfO_Y$cS+@mw7%V>OX=Drz89s;Q!{_}K4?Z&)&F|yMpGH0p8KH@Yv8=AfjO+MzHBbS zh^gizQK7+A3KNhfzD8Fmuv7OnzDnT;y!7Q?rNCDU-_WZR-m#1}hHu1GD*1F|%vB2C z(vjP)Quq=v_bvWMp}}v;{KK2%o`AZyBzuucx#H_pHti4Z65G86VYG}Qz5F!!|Gb@5 z|38@ny+);cAIL8&wcIoRy1g$ew%sx_j5;!H*yQ1p@cC=lw5d}km9_G?j#<{n>poj4 z+Mb0>cdi)Jk~xmUkMAVqZ{Wwsx{}AfRg}Mh2U%q>SmLiYnPWZtdcr*0e&n;k`KfZ| zj5e88M#eZAy9iq}BG8yB%pu-vVGirA7v`{Tk#J4$65(|4UBa2*)xr(HN*J$y#tyPX z@=5)<2m@mNUZw_O$x!PrIKui14wwm`-=qMH!DnKgf&Pt*)}K!OSC}tPCQ_w*tjkJ9 zW<aZu;fRg50fS9&`M@__m=3WSraC>#73N^1K$s(Rw(c~;7vwg=HNgA;O!YKyi7>nI zVPs?zBRLveM1e8WYiYssK(D0*(*w5SG{fv*UqEJd++5Z*#qHol7rHjXz1OmFB6+6U z&C0K?7UPMPHSc7)-Ek>yoh&?lEt{R?erjUUxlfMU-72o79?Ws)SXJt(n)P6KtD0O7 z%DuDHGxc2b_xeNBANAZYMgqb5Zid5i6^5#!`feHqx<jZk1FdFk_BnT3Vi@O>9~+7x zZGW)Uyq<cuzFXIPQ(b|{;JkWR--Skrqx&X$?0QsnZ2%|sBF!qrR?m!5n;W=)ubwGb z-QeRYao048eUEx>_4JQx#kYcOGarAdnd;t!p=x7qfRq39;+*0^Fa8w_V8qI~oPS2F zuTjx<F6)PP7xip!ZAzva>&S10;9<XnZkcmJm^ZexgH}bAx+s)p`qbHm?ke{nj9A8F zhF)p^Zw7;C>$<36H-}oPoAcbu|HdW#^%=v;Rb|1(ZudAdUHyD((p<BiYW*SBaXhWI z4GE_?txzNOub%#68n#lLy)7xjaZvnXxpyuYAI5s9yv0xrqiLw1zYrFxyf>1nDsQ2i zP`;$8Aa)N@qk{a{JxG}g%SIHsKPJcDi4tpaOV%Mv4Z6;)9&LxZgJITAjN$&tplT?( zNbmW4SWY7pVvFnT{vKxar{H?OKvh6q{Wq3L4Uyh@n8hWUu+2{P>QPp2dJ!9Cz0VP& z9%WUrMj!yOVU`u3vZojGZJY}Aaw|u(89LYg2L8EKkS?~Tu>;?Hxls4ypM*)6Jqle< z(f2_ARD{SIGHC|GG_I0~x7~a$u?X<86eI9o7%&54X)Q1TX%QDlLSoo~>S%wQ052l) z1WrNM8?X`UYHnZ`eDwwDqjA76?G5O=g=uikny-%Zaw|oDg(<9>f{GdV6y8~ZYndp4 z<_v7$DX2Js6Zq>1WFf!2feUmYz!z;_U<hpa5kP;FHZUEiz?Lh(Wr5K^2+rOV2*Ifv z>49-WAQeWg4~)j&1p#g$n;+n*mC<<tE_$9D;5{~T0)K#K2U<d7R$vHxni=4!Lo)&% z{GA>+2&b{+iiZ~ZhrR_@-6Vt~9Dj(P?0p?zCjM!n;oFBCj6bpnX#2*(c>GBY#$qe3 z;$I^BeQjwb`ual<0>1HZDE=*SFvM>r@gI;wzBg(4V=}*)bcN%=2x4squ)2eh)v0&0 zm#KFP@&RL4-rQyfHeI4N@3S%jyxWSass4mg0+;r-MS63YQ@BHDAoRT^4deO*C<Ovo zbpr>&Jlr%8)PftqYN|j;b0ExZWPy~J{ji5ZU6Vtsq%ga~K#s|%R0$7r)b2iRm1^H2 z6$9<ex1pFGK8YX(I+-isTfOjR^=ThBIkN=<6zHQrSLcVf(usa1<J&Y$hXMn%&@BA3 zO6lt+n@Tn9>sB>iP<{Hk>DF~Vb$wsF%w+l0-o9w9e^+n!br)hwPoI8n!@Bcee|zwJ zC*-DY6pB#rS4Pe7bwzr_*!E?_sh$1Y20><C@In!?Kj53DzU=3wCHIE);05MYRiBH1 z2QQPW`^Kx({%)158gMpPNrx^q%q8N%%37!$nKgNa5v*dKgz5Bf$2c{jzgwq(A8mp) zwPJ3#1@a}BVIGEw{K({)GmT)DNyiJq8|i61ZLBanz)^?$ySdR{kVL^e?Rxt#&sz)T zYoSA!CkO|dXyYBjc?@KsIUkWM3G+=RSfqt+;cpq%=Gs_~aENwVX`y%c3%XXUh5q61 z{}Bd<FEJ!-s1r3x!#v$9c&&DBRCorRYpaDZ;XjeV!S-4h7rvH3=&0i|A^a_c5-m&$ z&!Ml~wXrGT~r$rCxJg?Zdwu$LBQg$t<D-()SC7v>Rz!9iy97x;HWnA<Ibr6$jv zT^Jt06dYkPZ*L8kGH|2JZy+oU^VHSg81p^|cZTn!+vCg^Agl;iqA*>@bxpVigFRCV z>%+e=b7pB_Q<y`>;5?ncTf?acPo3ZbEo}=wg**!0poROwTu&E_YT<sv!i_)!-Ts(h z`(~h<j_cHegWQyB`Y{5FtHME#eHmeJIq#bi{B#|{7%P%zuPTz7b&(u3sJuvi&bYHk z-aE)m%hN^j^H`BQ!PtDwWr4W2YbwM1DmC2xNQ`jk3e(otLH#nwtsP}W3i)+N{ox>m zh&dDy3m{nAV9wnRAt|AdY9W4jOemsLhA$K0PiRWEe0~HZq1j2W?VCdN=499R4!H%* z1VX&%E1@Mh<l}L!39ZO>*w;O%)(>`TR^{6LP>IP%Rk?`#40SbG=Zxex)a!#$y_cwO z2fMAXt~q;%d#zRCQ&Wey58`^IN<-bIR@-=W-B7m>m(tuZ)U6Tu7&&OJw>T5@F$#P3 z%j(IYZf*0h`e>+|W@USnIm{hp)%B{e!{Bo*1jk$xcLApBKY%}+#+?8cvL~y1hq)ba zTm9F=+=1pa)uz<VGPkHnrEY(#AYPp)ML@3esQBS-6D!xF+6;GRm>txC;ci!K-;5jK zHZmVn1tZ+F2#ch7#>*mU_A+vsxN5=(x3(^}=C58BTPhz>n_$PP>8RJCo6TG_ap4OR z!R*DeyY)~xn;XQ<Ixf?RJ6G`be2c0+(oIWX={8%sEZt_WyfW2oq&om}p*u#pb@FaP z&YOE|Cg={NbM{1Jr@7Z=d(ay0Wpll|xzBzG&P}DfMEyC^t(BQizYp03oM~^72=(3c z{1a{NW%$#8uQA!fY}Ia*+d1+zO$Qu0(hgzCeo}26<tC?2WIV<@^m`$dUt%~XI;?oB zDL<k<809X)Qmw(G-Du?=4B28AntGp$xhVnT>#SPp{AjlxF0!jN#vPW+?=j|o&9TsF zo=(^POUIk*l=&|criH$K>548t%_@1-qhs7kmg7+;#<-bgnfhsrTODo%#=14k$z|DN z-KM7bu^K(jJ&iB=t;V};61jHYtmt7>Hn1cV_|@w1?xMtns3GQ?P9vx{Sb;y;9aP;3 zZYM0opEkkGu)?m|Fu~1CEM#)V>GIbbDW6q2q~4m~c4&PR6~b(+)p^ccHY<+V#5xI= z7E@;B5&0#`Y@^I;EG88XZp;2g4VvgyPh7x+?xdZ$p31##wQQoBgD4%C=$^uKdvub! z9y6L%CcAYaaSY2}9;U@pctOn0QQan^Z+)I_=xadq+7)xto%l4CwU_~dDl~a)RaRb{ zT0Ys$sKGwa4EyNF0;s2?Bg92~(=*x?2i04X-TYqKpHH<vJf0~#2N5vOco;Wc5Sr2k zu!jYy=y7Io6|b3u7wD!sr>c7Ca{Gqbn;Kexx$|n^6gR!Dc6gt5xS@9RG3{u>8|lpB zI**LZF=gAQxc8b?^MGnM&AqkxQD)S$?ql$ezq<I3C2_S7rR9ubOs55EdKNdiLFPE8 z2j$Fo<xF?4Nm|Cd_)NQShAo1T+0a%!rn`l;|DsN=O}B5yr=u+PF=n34KISvX*=S#O zPInvNmaWs%-RjjizA$^>1pu$CjDNxV`12)#f@TT*Wd^dXaE80TwodyLo%Xy!D~qF3 zGbS&GjEb*9Gu_7KyQ<Ah6ywEe;!L+FfunV^h3|$`JbLH-r5>N@W?NO`)u%JjD0Q?| zrCDy%3cRMoe43>>How*>$E!xpavS9GBU3nMNbPbBk6j<!Wf+pyJKgjn$X)nO9%`@K z;?6IrW3$}U{I;weyO?D$=Q?j?ARZY7TcR+ACiY%sVx_7y+f9jbBbIr<N-H<$Jqzzj zcEe&~Jm*Hc-hi|Xy=rpMo(WSG=!DVrL0AiZqE%b|t=erSthsA@Q-N<G6&As$(Vc7c zLzm4S-^4+8HPxn<n=q<$y$&IbudVyLB~;d9@~(T-E3@5PbDjEgw%atL1PLGN%^<kx z<w59{OlSKf|E<vVk{UM0t>_z!poKm%ulq>dILEDC`5i<&P|sp%nn1HmbE8Lw+B?Th zvQh$NC+4`hwcQrTPs`Zw|ISR|xpv;VYS(su?XsEoxCP1o_C3Dr;m6&>{<1yKxVd%A z+_E#DyR+_$K8Q3epC9~%jI8AEI%IVDJmB?Y6e0e$laZDDtwHXU?^Nd(8xvKQzgJMa zOf;eVT_AG`4Zo=@r)ahK<1P!c0>75y$1QXEXa(>HvTho%fQF39&mT`?Fe}ISLo#xk zze{A!Sm9TZHAXj}SeroR!UX&VkvXx5AFoTmWnlXEu?zppF9Tb^mZ5e`gJ&t5D9QY_ zVMA0W#&gMaWBeRBBgXUDEN8~J0b*`u#ke0iC&v1E%6c(=1Sw+H2Q&WfQfLs<_>0^y z#?z2gW^Ro4kQ>FgF6Qd=TouI6(Oa8MV(L7X%Pfd-6Edg7@Vky&6k}c$Xf};;Kcr^V z<T4BVPC_u7$M{P!hk5wzLz&<JovB?Wj4Egx7H$uIR=6wplyHBrUatbXL%|=4dMWs< z@My;WYZ1ml<2&IAV7@#jBClB1Y!o^&Cn^2Hh=>suMtF@%!YSbD!pxD{!r9<VVJ2z= z%}D=32>GJHl;LXzJ!=gv7VZIVFFXX?S-2EDgv>@0JW?1%!x%5j@~GFVzzoYEw++#J zZSdkK1yn869(_j|8C^r{iZn3(#jZ#L(9um|9@%c}AtQOnoH#0<y5$@WnVuaJP659l zOpjj?j<R6CB?6P{v~UiX(?fKK$@Qf$Q|mk7HsGIy+k*A_6PRb2;1)RAEdlE*(!jmJ zKE#yjgTWQb@8lW*p@wLT0;dU&1!w(#wB2`n6jk3g@SV*j*_oXU3mYLM0g}+Gp#(zj z2ucwU1x1=v73oFVhF+xzc#tLth$vV<j3Nq%s8|rOfug{T1r-nw0sDJhXMY3d{k;D@ z_w(kX?Dv$ZJ3Hl+IpX`_o5jQ6Jn<;FnRqOGi+DWTK|B#=|3)sj0A>{$J(It``y?<2 z34Cy4!hCqRcqPp4bBtdHPZDo}r-`41=ZIf`bsH7r-wr>)c$`o8x5@CcbPNf8Bs?z( zJcxAr6MWfeux@_>mxXov6PV{57Vog@YZX|xKY@ALI4SXY@XzAL@FlVSYQ#LKWBLXP z6L&#?cP5-^H<*RBbZ@x0m|s(-cp#i3eh_9KHRc}<*AVmT;KL5%C&3NGynSdEcg!~% z0hZM;(<5+u@e=qh@ndjb@miP-aG8G-tlvNYKLd}Kczy*_#Babe#Bam%#P7pP67l_W zMqeVJB;h2yM*JUmgZK=*MSKo^Ui=HZQ+yeIO?(C3C%y*r*?`OX13pSe@UzGAecwnR z8U9v`W5@TC7}NO9i}_n;gW6)aPT*_wB^wTlac+sfbO3pZz-1+#XUyti9$U5H7-z(* zWPM5Cf!0)90d6g>2Hz&;f!0~fYtmg}9(4DL8^P>`%K0~i2Z?!Boj@1Ur}kL<tpf<~ z+&)VZxOV!j1BmD8^HGV<f_byciMgU1#1&xuq5;J7%Bx>A0CT1Fiw0n>oPN;&oDb_4 z4HU!vZ-#(=(*P3M!1_%CaA)|4ET9Mc9gVf*Pn2)D@_bPoLi|-Rzox&%#o+{ex6IG` z6kE*GbCKI6kb^+Fn7`?4F}I++n7cin#@x9QO~m|;`S8H_qH5Da(Xz49h|*(-A*vEQ zl*#!1dB}_sbA2Bc^AL-PaahL34MTpe`yz?wm$FpMBjzcZ8Suvv4A0w>aaLsjR{;Go zBN~UV?;tbrQjNcl4C~hcAl{Go?-|b};qR<r{W<`|GY?<X#?ia@XB);4Upk(Bn0;9c z@Yum$1;ebLVLWHlnC7P7udU%uV&>^8#=68u>EhRhKRrs9cqH?{++aOQR}2As`@Tt% zz$-eRkU1g_f7#2$Jmy!4xhL0)xdS$fv*2yw3h)jwkBnEvwctJCdT{K31ezi6zPKH% zhv~vf@Yw!L;_ra@l+BTN`oQPK1K`Wz!SEmA`(fUrF#m&Kl6WMnN9HPx{XZ4~R<<(} zPxoo!8E|RwESLpN%rghBB3=OJidVpO#Vg@P;x%v^@jCc+@fP?_J<=9tx)lLE92dMD zW`Q9W_7coj+R-n=dNeM0H#}P6--PvOT!`nTqCnz5gJ+4qg7s)z$a4~YRN{Z+SzQmu zg@m)P9*ztC1>Pu`F2Q;<F2tjBC_Wk&%+_IgG%h#|)}wL3S@4@OExTCg(YO$w2kV!? z!Oh_>ktfD2V}FQ~G6B0ld@p8Oud`yd?z<#rvE?=K4EP`MY}m#%h4Xv_j*6GU>Eg%X zEb(f-X}N*~o<u@5@k?+maUq;9-UT-izYez&?}cv_bBr1mVsa(e1>#QeA^2V~+hwt| zq*!U}|1S}^UlNYP!^NlIvEm=#Nn&>7Vuc<Ta1EX({u^E{X8+RFVn0p}Pl|)E9<dA4 zy6|&)q%8#4PvRxXlnU<>SA+M8^I$!E7xFiNKalw5@DVY)M(ClukmnZo8;NJ*!tca) zz-PrVHm<uQf$s1%F<a>TBWBHP02cvn@%^wP9trd9gp3~t7Z*>5GsO$x95EZ>u-=0C z*TXfuk+#@qv5q9LzjXsK8%Q=2v$DF4cn92Gyc6ysW@%D)@gBIBcpuzf{3U$9_&8hr z43_{~^o$jsgjp2EH9Z4Q6Q6_Uh<|~XiZ8({#aG~U;=kdi#6g_&w~9mXcAD4U6a-$8 z1U{R-A!gH{x5R9<@Sd2hgbs_d;m^h8;8Ws?@ELJc_`H~pub0Jqe2uX%m0QW?LrHGj zY%=7EZ-e<f!#o|~G;wFRw74r=PR#xpRm20}I$|~;Y$ARTZX0(@j}_iY5(<#eO*{+k zDV`7a6DxSIn9sNmiJyT-ieG?d(mC<_pZQ|m|11&XZqv6~kF<qMyu3ao3B0^+72^Wv zds&QZzJ20~upYh(k@>J5z6)*!e<69=!g};B#NP&=miUga9=!|kck=wNhwnn57p#Zx zg8RUF_%66V{I5(r2<9VVv9kEe;52b-xU9GxTt(a-&J*)8-AMcZ+yahqMxzmED+!Ol zUB$~`Hnm_LUPkW|Z-n)zTZrERkC*u8;A!H$@B;CE_%ZPTc%ArNEZ_H(1l~u&R`DTt zyZ9*liufe_hWI=9E%62TBk>hjkFJH4`v=yeYr$+c^P}W(;0xN=|E%WKBWfWNo5%hw znb?wFkEn(CDzF|=3$6+45w+lYupUthZUATE_LzIC1zc9#8m=O~9nKZ^h3o2(wlD!3 z$v2RM0=NTRK7JeCRg9~wuZI}FT3>H5Z^H+OaXaaIKwJqPCawZcqj6)1L&-Ns9OIF{ zPy)Q;UMA*U^GY#qeAkJ~!B2^+!CS>O;qBtu@GIgb@NRK4_#+xWpCJ619%%~!uEbZ8 zfM*HcDKYPEe-Lve&WZW6{8gL<|1QRk^ab!E=K^>KoFc9a-z4T;Z-%%v@BgzUa0?PD zif@Ihi@U;lv@FcDJKR#@?}gim2g9AjL*Z^>-s#>W9tZaoPk;x}G0e08fuWMXJKYiD zIj|lG3tuGn#5~5s-1^1hEch`ol6<ShRpBSa)nPqY7BbX=pObif|NoK%8Y5wsxDC8l z%#+F6;!f}fV(y6};=b@vF}MC3@hJFP@kID1@eKGv-0@PKE0Qo53En7L^I^93<Q6Z5 zy-~DQ!z>VC{L^rz_!&4yycMn>ejct*;~?OX-&9--Zmmb!LIQX1ZIZyBN+)qH+>gfo z48nRKESMLMha{c{tR4sp@tlty2n*)dR3LfEz_Y}hza9t+d2Z(UUyp=^0DnR&BvV~@ zt(fQejp7#YGvZFL9v}<T_Jm)Sczzwb#RK8J;=%AIG=8`I=^le)4Ae*9ge34d(4%D` zz8S1X%Ys|OdbBL~c36*=1#`iAuq?PYtOv`2`@wp!EVw_c2g`yVfc0Qm@GzeL^=MfL zj6gyK>{qT3FG#uKNpM{;51eLV9xJzq7s4IH>)@{9O>htKX1KR_7d${4`+qkA4@klr z@CfmKc%1kkJXw4Qo-Y0ro-6(wUL-yTuN40VuNPm1H;H+1dPR@4g&$}Dfj5`{C&O=v zZTLNL2tFjnhwl_!BR=g9VorNb%xQlWbK0w7eE1w3{v2W`<{}W009{;M1kM!W!<QpY zg)50mz%|6YUepouRNX+#UqLf5e+6yCxUb;=St$R(TGT?IyCm?)?<MAe*<aic9xQGS zPo#6>TR&ACM*M6sH{cO5K732XT)8#kay<WUkN__jo5hu3JrY)}_(?+#gazX|6CVf* z=5EvjVZq!hM~Y#E;Nq|z2n*(3(F0+@T=2J&hkHd2gcU;qcZ(hg3(ki1NLX+=SPz5+ zbA^&|ndAcU;1n^>;i=*VaJsk=Tw2U?Moqd-yppA!_zuL!8cX0#1X_xF!R^F6fpiiN zfxC$xgzphQ1ossWhX;wrz(d93;Zb5<{T_}xru$9vE`)109SJkV3*q_V#qbjGQdo%} zhu4TVz#GI*!CS=7!Ox3dfp>~ugJ07lZDGN0A@HUo9D?5!e+(ZIe*u3gJ_Ua%{uVwd z{sI18{3Co;{4;z>%yYvv@dX@zzJDZe2@a&j_rx{W5nC31qGFc$6c<O~Oz}-{jyMz6 zgJsphu?62O@#SGXSQg^h50-;v#kkw~#+&AnsTr(C%R)SRhU(F>;5Kkq$-_>2dbBLW zcZT&~S@2!39xMy)3G2bKV7^L250(Y@hxK4t@DP^&=+UweU;)$g)cDp9gY{@xh-crl zMG`*-UM?O7uM$sy*NZ2^o5eABn|K<$Lp&3HRU7+%4gz~5fn6aFh!?`|ix<Nmi&>iW zh4?Y}D=|y9^k7-|ee!g!2g`zaO4fsA!8XkHjm2P|k^?ab@MKbg#_5j}mlAX0vSLnL zS<H#6i#csG8YctZq_i=7tC%OHdug6h@pqq?$DePA1QOt3;zW3im@_R9JMesQG59et z?|jyXOT+8M<=~fSoSo{xyTr}my?UfAB(z1~ZArKdJ}mACe<|(?e=F_=pBHzBFN^Pn z{}A_vc`oLHd9q3pPk<xh$vpoTm%vmcWQu3PIpR5RCGmW?hIkoVN37rm;wRu{;wRxY z;>~b-F>hA8&@rstHUzp$!V7RO@pibsm}jp0#XNHj7xRW?tavXxN&F@}O?&{JBj!nL zq4+o)TPA^T5LhWb39l2MhMy9jg|~_?!`sC?LA@>x!f%OF;P=GrQF>UM0e=;D%$I`z zo9*#?DhHntSBB4vd4jquW*7Z`#rd#ZB0eooTt&of;gVt&ZfA+Rz!k(iK~*n-@1F}E zjX-Tlm<rby&w`tZ7r?E>OW@nYJO^|VuYmi}4deF&gT=hwj}m9Y6U1e)d|!bCD#EkG z{HZJvH-}e<Tf%F_x4;|4o#AK1{6*{(_k?$gd0F2p?hAhc$BN-jfhU|}Ob~x9=5PH1 z-2}kj6~ljt{fPJD$Im>RPf(l$r-(V9R55SM(#7}|oBFaOfDc~<aVA_%TpF$==E)>q zTnTQJR=Ddi`(hciQQP{m-N;7k^dI-w9MG-)UVOZu=JMmLI))E_WV@=e&+dq}!Vm95 z>|%8gAO7|`Rr;HV9j=DFiP){`ReY%K`)yaH?zdavP2fHDBmOV71t0$WLiNXfyQ9BV zp}O@geBNHDR`RoFq527*X!=|K0CJC3bNR7A9plFeRrzg9i}CR$yp24Q)IkPw_o(!D z^y&<G2bs`Bo*$!?{VwyqrS5(g^S$GMdIp~u0PlB1V@~Z3;$yFRoFCt+AMxQ29#jq9 zL!K3C?t6$msgChuxT^fV{&<)lc-<#IUQs1Kz{eRi1RwsiLu%ItSV->2%J~qVsYle^ z{H%6FJ@cXcHdcScA^R7;FySNQZuW`V{t;3mCzSuNJ=WhnK}|S}a9R!Z9zT25Qt2Pt zRs7A<RGW|O9Bj#ukL`+ySI6V=O)dY}F6*y8N547r@W*x}u_?}~@qT~T7#xRSTKqK& zSx4*$Hm&9nyP~y7_29=GHI*Mn)fRjt=0A&z_w}*wk`Cjhpu3~)p6`^q-a`=GHcKSr z)y`X5@Jl5e8wck*?*~HXaY$Ov<9LlGswWmZnX$WJbPr_PGe6sS`IolCF?FM-U`PCz z(bw-09M<S5SOPiFm6N9#bPrU>iSB`{<w76M6-d+F11Di#NdexjCS%IqaS=@ltVJle z1poL4ae)bUk%yCT>5&%)w&enndNFz}b0kkE-^M=)!BPA-5NN<G!N3tL&i)lq&Q$z^ zd7r_*p$&+|O9hMJ!`+97K%KXk>hp7~sX+bT!7%&A<E4VkgU*AqF*|>6zTGIP*GJ5G z7))+44-EZ-l@2Di;rkcdUvT@8e2bo&%eOWqw{3{%fX}}ib56d8YZ5w*e<I2EzR3JM z;V1VZeJ+~6Kk8J9{mj|r@g}^;2VfwWUliLIDa4$85mupCkt$r9$U;OUME->X5e~za z7%7i`lOhjsQ4zNN3r0AcnH^zgbM!6D;~eZ=Q;?z;Z0{z0?oUXz;~o6mk!sJQPKomQ zNU#rYV5)lxOSV6u<K6k}FX<HbPxa@cPI`=Ib6*4}H>?<|ko=JdRv;n5ik3j6CQ=h4 z4<bG(QVw~NBOS0x!ALFSu_L{Z2R$j-B;3iLflNiFU}1Qf#qV%L_ZEp9#0FXs?jpa> z|1u_U+px`IQozB##d6iMrB3OZeK3cO?j<(6akpUt_i`z{PwOE*?tsgRHTUuctVGbg zPn}-sl#OxsyI0C`rY>)z+$&S@Z^UK2tb656{F~~ga&}iZS(<ydj^}ri?&=Zjey20_ zE^_}Yz`B=?W^ggZEl!XXJ;n**f$Zoj_&VJZIwdES9qR_TY1UiFS1$TCCUrA(pi=Y) z1~M(y<5r9Q%Egz`ff~_6Oew9i<wkGff+||CVg_|m+40V;tY4v6H~KH4+-f>oesqQU zX_-?q_C436re1iPXozc4M+a_+j^h&Ybndp%9ZbpBi)$a{OW9q#K?jp|j3#jgjdZr# zqcKj?R0r;e=5j@v=|J~rmm7he(TQA<7EFox`b61i&TXk@*FVbEC2lJn7#RJ46SdKS z!BIY&xNY^O+#gM3N_!o6Fxs5cbkf<-5{Gl^VzK@D@F-g_yIpl)bd-;IZg-0Z_xR{~ ze!1v(_cacUNl`y1>SOgopdh-H`TAKrXl6v&T;A<(u~pKX=u%EJ&|*8O1yQzqb_ZMR z2D>=goLe+PZ|kyXcSO0PbYMl4V<5VtbzpUL5N9x6@8EUOLZp;;C+N`nXgTJaqytYz zw=fXX0rb0jSiSz3Q^WsOf;#sYUi`FK6<1E{7Fk@)Spm#3DR3J3Lu0T)S?&oQZt;Wt zlyR_Y%fWtX1J;%Y`x=FDE>hG!<&<crkL}aOv3;7k<k&tPKejh=)<5t^i2iu2YjzJY zA@l?eh)DQv-De<0Wv_5@Qh0U<J9-P8Xl>Pbg%fSu4Er)QC7<nnbQipo`kdP5vY&2B z1KRKM={2R{TX4WVgRM$wL<ilM)%q1q3BNyxk!zh&<ws$&twPL5k7jPI<{Nd3kH%_P zh0M>t;`!<?WVMo2`r}Sz>mSwXai^B<d}{s7Jg4w~sR3%%<4(1TpJPc@j&6uw8PV2i zwkyf1f-OWWGxIJzD_<RZ+$m$N!T`BW4&E-Exzefazm%XluXJwp<3&|#RytkqI;9IM zoihHPEmd@tQ_X+LQcYJmjS)S06-KQ1T)nr-DUa^?7gjkHt>!9iwNty?V640~fv2)~ zuamUa+`36zu0&k%t6{61ZUecGtPbqg5l;wK1uK8R*fFfvl~`VWs|^a^8|ZBDELM$m zy5T#ttMm0F&eEyKvJ6u=A0g<gQ5OG3-q4$RbML|`Yn)G$lE20b{Ju5+3-3LBpb%Xu zb_CSOUBMECZ)|Y}{MT<kP3YTilq$VGp;BST=bU1dW6xmcd3`F{@oVFufxpM-P}~P- zY%>3faS!tr8h;(=NZjLTmIL7LG|fkI{IORm`cCM-HFRp+JF#4})sN}&g4f~!-2!x< znDcr^%!}cN;tco`aW>2=0vr98g-?hpz~70hz(0$t!576f;H%ynP;(Jr>lx0d7My@B zrt@K2+zgJ2Tfph!ws5xicDSOr8(dw?JFa@-9&lrEPd<II^$Zu*A7;xKHt6SG<=r8T z;sjqGG55qkaXQQ!0p`hq*%*fA){htSDURoD#@B;+Pe9{|)5q6l#Ta0X3oqt$8<;I) z*tj3T_}~LDzw&Jo&##6JV3>zr?W<xwH0iz;h_3|mJyLAB!LR&t!^g$gm{|PPHOR!R zVM7;Az#082=F`_7;w;#QgNu3i{UwR{mFc?|#5aRWF&=A-2etS}kuc|@`%%E<;5?lN z`@bpz4P^rEuIA#_FwZBP(XDV#8s7`Qnt|dRm~BZIUlSfK=6ra=%NE7li+X@Z@gj-G zPVz0+eJYT^nXZxq{&IMg<-~YE^=%b%5A6__fnOE#``#nwZa*OA9(rG#3x6!;LH&g| zh6nEWdpxnQw(xl-U=6rJm&N)k5Ode@F`IcRf_%vX&9lEN<{m93Ms1QWP0ah{(qbNr z<#eA4Ow1xd-h*>SD7WzCikrZ7#m(SG;+Aj=aeJ80FPyd$++N%r?oHze<ySC3%o>^p z#1R~Sz7Z0@^giCYaRTo4sbU_C^Tk>45;3=UxtP29X&Q$*7xtW(3wue-J-SQGW$mT& zF#-Pby)6k`@CRZZy+_3S3XY1)!^aE5Upom7Ucg!O2ZyiY?28Y-TT^ZS!Rd&X2wG<l z`<Lp>k9XC2el$}T`Egt|{}CTE)DnIiRi}P*e(`7JsUtsO!oe#0XT%n$5kEWQP;Bud zLnzBQi;s8J+_O$q>s0);p5q_ED?iStV`rU;iS<ypG(!~~fMLec&N&hPYvuK0b~6|+ zJLr54SrT!O-mYJPxR|l))OyBtL+p6{hNY8;4X1TM5XTvh$p-rMNQYI)^T?Nl{ri%B zJyPOgoL1NBNg|)vH{OP*Uz3!dpQYc=|EYdW(ruWF^%edpE3ZjnL(v=0)(Rm!A)iME zJX>#J==zI2`SZoIHA@xoY`r7?!QVP2_zNG2fob^HdrcCbe(`9`COvqvEfs%FQqli! zuSwcIHuY7dKDXQcw|y)X-<72BuB08R;Jc(iVWp$?IzL|Us^6N_=>K_Z(r*3Mq(9?t zO$y^!G~SxjHvZP6G+f0p^jnkKs;RT^60G6J&F|=&@+AUw@^ka`mvpl5!{hdGCyB!g z?nqM4|6u0_%O_zM`V${kzx-g=v{tI@Gj=v!3()cmN^|C`foJS;c<0vqGj`=z5`JYU zO}MDP6MqRzmx967*5E5}d9m=hJ2BgsTLY^(#pPYyWVb0MndE+lRh;M+!2}cB3O3*L z!>@0=%aiFi_c`Pl>o!E{7<U8aGumB(`HXVen|Y*L7pWs$KHjL>Kib9f-bd`0c(O#s zw|(wcm~$<>k_P8Bw=Pm}56F&5$-|#UR7xOu3GNAf?n7$IkM=`;$5!WmwEI@zSl2=K zOJuiQ7ps6$g*jLX21Mhv&`srh+zx8YPj-iNwneYxbY|&-!}kL@U0IBcNo;leC%a8e z2kB0awTOy1tRiym*#Z}H#$hILr#gJCfz#(G;?tY~s_V~oE`EzMezwcw9T(61Y}Y8s zrupszoG{>A#Z24>=_Kb_b@69A%^Ihiv-UI;T|RQwE)o6#nXPZQ76Io|_2OB3k~Kor zIA>SJ>nFRP!%MeXs~P9)YyOC>rkuC)t-Qj*^Y#!6XRYiD_RUtW!p;{kC>vjz(B~pv zuh~tly=ad>YUGkV%sN(BaLInqvPu=6`_&%m$7$%EEA|7{WcAJ!yJvU=7u`FNJL9IV zD)*}0+Fv55#$C0m`Y$J{jaTjbY@H>P#4N|K*_mBAiJLT*+XiM%FZ}zeU0_+~)s)}u z`bBm2D|(J!qP#e>t9ti$dokWG(&G;d_I8U}^M~Cv`Xgp!<yz<Q<-{Ku8ctOSf8t=h zRptF@m$9Bu-Tt&c!wI<RUv_<~f*SCb-7)KROq4R07qj}fmn*sei2qX_@--||_{m>( z=}2-5e1Cr5*Z&KT4gX8ygZ&$J{t7Q$o0g$^XF41I>(foG*Mm9gWaX$`SfiA)y?yK_ z95>#hM@{Td3){~>w!8JZYS+UL*n7nI2*<qlSdqi;K^`mgfaJW0;*ZbpUXSc;G;f&k zmxXzIJ+FVma&f;MfAsh>9?*567FL2c;whLQS<I_;Sj>5OPXMe>;Sd7M&zrF_V%}(# z7uSL-i+R)4h{lTWmZgP$-6H~>5ojw3cf%dU{b2nxfIR(S{WJiNfcr=u9?JS@0P#~` z{WJg<!1`$bo(?}O`Deie;wN$I6CXkVnKr@;Bw;iBsCXy5Li`H6R=f*lF$TA0Km3gN zU6^m{Wc(rcW$~BrZt-#W9XQ5JClUBq6260vihqE=5nqG96(`{9`bm5fd_i0tX0vzB zlPwGW64!$D5M_vG^H?^4XP(Ba_)n2QJ0zrvZ-e#F0?5ST_biELyV(lju5dN+ov<ES z0Qm>NETrZF?uVO*hr+GIY*=usHugU%4)n`PIRV?>viO#s2oDy|gC7z<3Xc}EqHltD z9Xv(+B)o*iy=NNs99yf?JYd&|E5IA{qX!ZyA+SXfc;~LWY9k&uWAU!qFrQg<S8e!y zc%S4S3hS=gh#v{-uG;W8_!G%90oFaW5kDC|A@Q*p2z)1jN8z8v>)?yx7vQU69*nxH zHfF?wF(DA&vNvGeRU7dKVU~(<i$8#G5`PAl5g&ug>qie{I)y-0NjMAZZrh0e4c3ns zH~|cY^&<v63hv1KFn@k5-=Js0cZ+AkeZ+I&f#Uh_gW@H8^cX3Dr;spNTnNt)?}g`y zxn+yRpTducPr$3iXW%Erys_1fBv`p$VclyRX7#upO(2E<?^$1y30!!eI1PSB%tkvO ziYvjNh^xTI#Qgc45a+_*iSuEWQgaXCC+E8;?f}QGN`OD1zr`%8PQWRZ6HJF~@f?`% z!D2jr5jTk+fiuL5;B4_~xT1JHTwS~o*4@1M=(i04-On2{-3~XCOs~MYn>XT*z`C0^ z{1x0q@_Y+-7oUTBi7&wY#lOP$i?6`C`#0wEJ3L-@=SJW!1a$vzm>sor|8LlVb^mWT z6<#7UDhIC+SAy4y>%beub>U~kt>72Lx56)ryT%aMErDL}o8rFkyJB8Y4vB}spNe^L z;r%YZ4!#Wel$aM6z66Z%v*2@LUN`t2J;rZ_SuYu5fESK`C4ogs4zBTx=Y^xFm=_M- z;WPeCxRm&FSoar4{C6<lUdcS{B9$xV%aH4e`C!mUjBZgeUkeHRi-fjfUMxC_1MnSU zUMubvN8!HWlCbVCjs<7KLnXd8JWAXQept*GBTv`H@1Mm>3nigF{Ft~iyhhv))_upZ z0A3Sx-*K2lO}g(mJQmh{$Ki>v?mG?_!24xBb6{4fa1XIJ)0Z&@ip4JyC&j!-d@s&| z^<ebKlLKFp_;T<yaRpcpMvpwajs%k9^UQ@EaUL8I*Mp0TV~r8e{m3yf3)uK(9j~;e zwqd>;m+>Lw(Sy;$yxr4-(Zeh=(Sy;$+yFfoJu(DgzM;n}l+lCHBcAhlNO$~3fcJWO zFnSn8V7~D(0q^znpz}B383<m=co>C&zLjF;UoXb8eVfFU;a6zPqz=r=G`cDLmbeYi z|L;kFH-v}9x5J-{d&0-X{owzIc?srQdpXn5@Od#Wub0KV*!(Ge1ZKfL^RI%F=@<g* z5zt-H;q7o#GV$`tDsWD~`?zfJ=Ws>wQMkJJ8@RUkBwSy78s>91=kp!R_aW1~(#CF+ zz%K}N7GH!}$IeW@!uN`=!1sy&g@=e)i8@To`$1OaaoP&-L^0cOO%+##XU84$)j;48 zNvH`g71xFz7uSWK5c6ubN!$>AR?I8gi{fT5tJk;^E#TM1x5E3yZ1{DMuXAFi`w;j@ z5_kitySgKO5d4+I-w&S>kAnH!&1oNobr*P;1DohB@G!5Ox(hr!7iOzZ=6?cC7H{s3 zKv)8-x#f@}%=8?ryTHTj23?i$CGp$Fd}@kuT>0vW@!{h;Yng{Xt>%Sm#yLe?v<BKX z9mR&9s=xWMTXmR$kMU{^KR#9G__0hio{5h$>JfbS%k@&<%yh=0aG~2QW-Z(_%fUDs zt5tXof{WF?bDVMhI^)&nb5K$_N0pz8*cocfTog*SQS0ZTMs|`qFc-yz^XsF|SzSbo zKiX0kMOK^VL=wxl^vbO6VDMf9<3*B_5cIcNr54U}DkN@0^l>${YA~ukKs;9b>v>Ma z@Pc-@sNh1y-*CO97td!Pq56C*Y{h!qEa(EsPp>*R3MAF}s}9B-ikC>nf;hYQ65?kA zo+%?ZkKBQ|ai8K}i#K!D3S{v9{D&dy(@OXkC6G;#f_6e<@NuI6GsH-|=N%U>l$pKF zoWVr4N<ibF%lrr=@_`eRe~m*8WtPxy@oARgBPlQgv3hh-KW}{e39S(J_eYXH@n*6P zR?43|oV?6`f_?BWngX5F%LpVRIrtT_2NG)Yna<`DYC@eSKxEE9YC`?}pwrsl0+~`Q zW<mk!XIuhX{v`H#1~I|DSU83j9f`TxyhtVOCVh4f#3$`}2n^UEzZ(9#Q@lcNEF$Uf zT*SFHn?ogiLWe`~kwobfJCLBZ{_d2FrC<$w;o6vs6`spY39sUchugt{Fi)F_;X62w zFn`O*;cww!xB*h_Fvm@Bd@1vgDUdwkKS&R6MU*ehnk6gD74+jRg@_6yul|$Cto8GS z|G+<dn>I=ks`!djz`R-|2Q1c^M!0Fo$#`igvP72R-(=VN0S-i}sfYe>(qdmAken6I z9GQkmF=lf;Oq3ewgn45?tp^cEixlCcbuB*PWkz1$G%YReq^t;U$T2qO7f2}=Y0p4A zi=_h9A{DR`lG|I$5Xdb$bo3Y>#yMi3R^&2g-Oc(T!PnJSCsKwJ-DPn<Hi&TlCil>R zh7sPhCEsIRMO>qz4~-d$MpindiGC4x@&FxZ8tKLvjJCERTQi^kR@MDar=0b&n*66z z#~<~p9e+AyOYP=-KWE43q`;H-H<h`gdcXK*sbBwedc^o#6bR;J@w?zr6|5^q6;F`C z#`?%(MOA9B-3!cf9xEKYjjQdmTVq>;9catu$vfDITj~$>9@5_z>`Vvj@9}T2E1hIN z&pbVtKWI<qzxT|=%?$<*dP05tms8@-sa$>^u1drgydMiqvmZ#rGHgB>*bnLTM)4#( zoDSH1IrS)J3EJE~djc2a+IyLQ62J0@eWz;jw^KKbr&p&ce|_=7#H0XAj7zjHT=2Kk z$V%oJ+VAVa0>RY(rt}R1sK!eK)s%moh5yZ*^biYE-%W|`EEBrhU-+g!^pB0kp!?j= zIREhI($eQEs6OFP0OPFdVX_LoLd(ijT&xDFzLzkL+d7W0FhRW-4pmHK*KDH(;VosQ zAa-L4Zaj1i!X(u>C1i|)@lE;SiM4Cy=jXEaz~5)2I&|DlFFctNdOb0=9=m@$zBQJ2 zcz^yb(Dm`ISgDIM=)3s1aR&Vq`xj@>x3SN02Ca-4;0*dUBZJAjUgHd!g*oHAxdmUp zK7sbel@F85z=s}#*_VuSYs}~G$oVJmKF-f3a?-AHCg&U<a)C9#GBz{s))In)kryY^ z4a^-3B-%J!SPY0}l)N9Z`(pWlI=m;tEN?=lKz-hPIgfKqQY_}dxpXfU5DLVS>hMr; z8)AB&%d$1geF@9+yKLT=fJRi9++`_rqT3bmNp2NnOm_doY=iD|h__vyaL{t_Y0NMw zKa2@Nf#f_M;_h)h*A>VWbNLpcDQ*u;J=y&mF_T<A>&7O!e8JcR_YEXJ?DG0B-kppE zjdMpLW~}=gQpdO}F{9D$otSKt+Y$ecba}5j!sSCHMo!p(HAwFDI_8a0C3++wv&#}5 zRIsoN6%{OZBVR4|L(H+9n~N#2fkTlYI6UWTy}rREd_ReM4BulxqU#{H<=%yueQ2kr zUMn6d-I(`6!QE`e;IseWr162P?JUeQ`0i>%2g4k=I`}^A*sPHW9$o^w_8L{ZM5s!v zJ+h*9<_MR>W>y#>0smSqi&$|<XpXrC?A3fZq|0_mXzqtK<t5=FqKdGLq?L`!13n{M z8#~!zUSGtI)wNxV7mz^YQ$(R+gaJLif}Nu6MmqDM-Oh?nAK?YTu3%Nf%u*x&!HS{A zr6&Su5k8&b>^BvG%t(aOw6w-zZds8n_}6Z2v2dqc<QS)EXU#%fwa7}&t-T(gEPjzd zJ8kZUS`ijY*xjrzFiojC5nc%GyYx5>4I*nehaNhBi-fu-EmWb%PsnGFw%FRIna_Wl zTAUUtXVq3a(?WHu?dm6nTB;%?Lj^IE!lC9Uj|DjTfOqQ30nghCr!n_QkVTEDPP=EB zXBw8~+{W+2XHTX((3V{szaFO(SJofqdEV(v2W+mf)0IxLStRB3VE&*z0=vh#X9;hM zY<nx0buTkHVZPtq>CN?VZI%EzeQ2EccVKC0p$B~2uLF6sJ*2-jyAO6oXgD3PKfpH~ z8pSL@n-96637n~GpTPn`llWyu>;d>UG=)y}C8<Z!Lm|JDtX8InYS)~K*=D-8{m4bI z3AEdR*?cyiO5zUKqcAI1Z*<UJr2a_{m5uQzayvD^RIXjf$vSfzBR0Pow+mg=K1bh4 z7qfX|=60u}_GqlP+cSh|Q*AcbaC`9}N%N&l!$$x$!`KRUF8=YkiI|1u_CO}I8s>`? z!}(m(5~!D5pAkwA7ssru)|{;`eY|=%Bh<zEkIKjlm9mPf`kA4|*3)WSW~i!FLv6?m zRV>OzRo2%m0X&WM_m!`tzRC<``%eVaKbfJDR-Q^L6{=iJ=PGV7+x?ipSEZinS_+3x zf*M~cRJJr%-|A>_{jILmxB&=p3#>bQ6-TL8ONHuXpTOE<NIK4f#W|Jv3$!-rA010d zDz8^XONXlaPx}j-l@5)utaSBq8BC^^+)q!IhmEbFC+n{#<2x2>tXC;np)USEFn~u^ zsJnl+U+vBcmCNQ^XYqP>ejCH_e{LhJ%)7Xx<yc*;Ts%6jQ&u)M4|^s%)WKS>hGd5- zBeXO-RLg(HQtxDka<cBjYFUf?Tw|+i4ZdC4TB7I3vJzjdsIqfHZNhx{T&RG*ioD~A zs%K6p4d29=oKS~+HYLGuRXode!=j@+lSX+YMtOSl)nol~u)Osk)0j#B<Ey(+{gD$& zA6gSj$3O}EBG-61e04`)X?8U~kMkXj)!%a--=J2cIU~7^(au<~FMkVWpS1iNM)0B( z<@e#sE05VGEv5O^44vYu-@0&W+0ep}zkkwW8=W%$^YQWuaf8!6S?%o}DWPuv-k(^Q zQZH02@xQ&#Da>jVdbf7$QEY@)OF0jlYVljZ-#!}K%0Jdld9|0^QtxHde7x`)QI4Ql zl7zp}{BCjo!#~d3dl_{Vx=1{puk}RDC(ltRBxay!Jb{fQylT)jSUJ`}Mv$~Yj6y2k z7BO##c!SG4>F`c*Cj6SXG`vro1$&JyE5ILm4J2zI@QGxq345(BYr|fvOBVEfCwcN= zuhnG(*lTsk9|TLhxkAlgURvlja8P_3oFeYR?N61!-Eg|NC!8hj4_6QmgR6;oxYZI* zfY}Ly3tIp;5%b=hMdXZs48B#o622YQL&WpfbEhP%g?oxO!UM%m!7MK4jQCv3B66Bn zG~F5#eg&Q)@vp(t#QWgov>aPc+;GgdMFRZ#pBM8x-YG`0OS}apCeDCAV7wfdyiM_} zt5y+@C?D_X7|(3HM`WcV|9&@|fCIJ|Ur)#dhjk#{7Bwp7fy3f&PMibt*_bW|=h6;< zzq*DSiLspc7=g%x9TOiT5ateOFL^k5?-&CtR>I!^!}^WYi06zZF&;lH9@W#t*)Siu z8DAD&C@v2#6IX$G*TX!u;C13U@KfSgJp^8m086adV}=v(h~=X!-35MA%mb5;8H^tU z9}-W5KNT0iUy2vNC&f$P@5SrkvwDbl%!tqVmn2~ad`-*)>L2lYu&xG0{$p?iCmF89 zDY&?pj}6)4Yp|~QM4lu|8d}1v2W%#JitzV;s|3m;L05MoQ$<);cfyt7zLKXJJXo9$ z>*`MAVcmO-@i^=8WHnRF16DV#L_Cin-MA9w$wx5{UpieG0p3k=;%YFT6lk7s_+&=& zB%`Z1;g+zj;)FZHx`q?(1Midk55T+$=Cs4%BjS<p*J7SOVy7iA1A!mKv*2IEE8yS6 zYvA9-Prxn?ZN5esQTkj!^OweUax{<Y(qaU!zoa@9=4}U>9>-g$G>ixI@3py@6W=1{ zF6|&L26q*6Ml45T8)g*e#%m^F{&XLZc<y#xGl}@}@I;B{UZ1IJDUnbEf%%e<3+viQ z#Pj^WT;dzSe12pN6TWiab7HQ<OXA}2E^#`{2UzCkO7J<HE(f!x9$kay|05FM!j6jT z!rzEd+<X0H)Le<5B)$oJLEH?!EN%hwsf`V+`PFzYqvpvcD)Bt|l!S*c6Sqd!I>Ow& zx^@xZ#B40cYBX9`D8h(}S17{Rh<Jq}%u}_lP=vGK-ZCw>_`bsC<3poDR)4i~dWb!2 z6KCM#sOrX#Z`Gz5p(oIwxAjbfF01AE@Mkqs-_Hznv|6dWS%`gC&E!WN^%+09tMao$ z<E*#Tn%T%&uC+QpJ2Vyzdk4(XS$E>Y@Agqib3;|o>bK_HP+9bs?KT%hFrQSwbwo`? zjQ{-2y7YYa+z_52bJd}_p$dulxi~%Omb~sfl;#{&rRHIx@rXSeZyDT^(fMj9qQm|1 z6D`1=X^IW3uKLc7W(M$OO^!F^EjJ8%Pjzlkq{L(MLn$}9&a$MZZk@b3`D)+&sg(+Q z%nuDK-h=Nnv<mR!8Rm~yHDZqX&(CYv^>Q9Im_#|xZ}@TCDCaqhNl<9RTU(U#yo|3F z<ve`5ILdi;sq801#T#Vd&_EWR=x>zk`1~cYR4LYJ$vNu*%l+dpcPZ8>>ZlQzKK7ZO zTYwd{K~|u6#W;GvMXwl#1&dOQ!-}vQ#W*9eSU=z7oRqg3TNBFU9Fp<};lmxw-?{rD z{;}N6%%>m45?tO<1za|lPIRZ&=X$#nv8R*W+F0kH%O_~tErv{vFN~s`&pEGCJo&h+ zijKLnup6eh@2RF6LM398v2hQ(EZiFJ-iNu2bDziBjCBLpEo0m;;zzq{up*<}F_`;E zw<Z1^;ZDVjP;gU#tnq@IAiEnxg1gv;&7Q~g*iHIu{>;6?7M3ANVM~e>wp2kL2gRyL zkkXdRm{IVPC5Vsrkqv%Hr`S)ce>a5EV_{@Pi(Aaea{1%&yL@+Mg3Ai9fIA51^hB3$ zNlkL6AvM_@fQ=2heYjfgIqU>9vps->fHUF^#JT!J?B0dVvD}VG_WMF-v4nuL`U@sM zfVukIn=ua-<b2Jh14UXOy_FNNSPUKEraH+MGvifO*nf^!lEd11$0*5hypo(&%#{_N zJn}kb;#9CO#sms-cn69qEjBnxi)?4Mx)#g1G9$d&J1oe-ZzwBLkqd2Y?Lbnw$T)74 zSCYfmuA<8v52biX4l2qRs1@n2Zr>CtS&4hs@k(v(!ge|LSZvl4FWPr{>Bqk&k<n_& zrcgS1;cwj(D(5d1R7W<2YFj_6q^Ix<zE@R!DpXLu7WY#qFBu;;5B88(gmV(}3pGBE ze}kW?!%u}8mS_Kkkd(%-vLz&?F^w6255HgAepuyh4wWc!2AdP=!<nM&<+cQM=jKpO zc@}-Tqxi)H?O(AdSISp-yYEW*%5k*@(_4eo&ds5l%d`9tgM6~q($2&Z!<YZSQhfFm zM8qAie^K_+p_{|}3d2{jIa~XC)%xjB*^)nUiYwf4>Gl~M0^#53O#8B$`gAC*^6SWp zF+RE8*%3C7!Wf?nTp#0eI|Ah*sR`=Mr$goQW-&);J>X?-<X`-vFvjO*<hVY@Cud$a z5@NP$I$M5ZtIFIGsu>G#Nj3G%+eC)p%f%3%T+%HOn<;rZciRX{!7#)p3vb&;{zf{6 z_++4Cgkuw7h)=H2?U4*l(^LoUi11y-7~+#D-6MT&1bRm9;fl0iN(@7Mvgag*_~h*R z#|PVNr2_*a4VltL2L?wfaTVI?gYEtZ2YJL0pWLnoBOH$bLws@u4@DL-rHl0mj=bR! zz91Syd@?XPlEIYj7S9^vBR!dduEt*>a#Exc=g`OMgFr!q4G%EHC%@Slk=0y<{?=gx z=0w<b0z-VxLtsJVSI%Lu^*jQLBP$sgp|^EeWHPsPln$(j{K;({tplqg!x$K^cksFh zpXw`Mh)?eB^^wu|7ejn9@MMI~N*Lmk0dzHPA5s^d3EgF_QEi{akEMA?J@jm-OkJF5 zFvzDLtDY3#**D129Srh01@ZAi@|1B%YV(lX|EzaNp615$ko@=AP}!RLkUSkfB>9T! z@DEq<b3mWsH@VV>m=I*=RE+V-{b|orUAKmEV*I^hj8Cqr6M2h)q88s|%`rabB43ar zJ7bJb#>p6;oR!b!@32S%+HbShb&-ZVQUZ1fOjM*19klrh^dgO!#~b65PO&+fU6H1A zLd0I7u5JyL$>5kI7~+%Ll(rr7!w{eR$@xkqC#ag+@WWlC+HDI}@aKfoh;6tG?okWz zQH!s6wps?bNoDvlYj_r>DsvLkTCH?^27ka-o4D5|spH#1E&NTA3$vaJO|`6r>dEIr zwQotmDp?Z)T<`NZ5VQ3Fdy@jZPb`gZGiL}Q+u{GWaWkGV3`?^<4)BQ0VNrfX<l@V6 zv-cKezJSuZJT@J%PWvssoHSjJVtCpg-<lxTWvt&SikrW9%2+?QIiskp*1j0Z^*2pW zhhGe3gb#8V#S^$;8Hd%i7ekp*U4Hakf}T<BX_!IAAXRaDs8l@Rnj~zGC)|aE%6f`~ zfS#gM#vmO3R+8Sv%+W)K(>ldh=VP^Id#GvFF0R~o#<8xuURmzLhq-p|GFUW8{k1)m z>92|2-#hRPTvPRS;A}rj_1qDvY3(drxFa++fW8@tuY?}6@}}bZv@WndR^R7ZtDB}X z=2jk5i8#)1=f}g%x{XJcM4VHHUk%mDTg`Y~W-swPzO38%-ADuvvi~chR#4U370N2d z!`bS}qgisYxuVt0h-ihepLd07)JeyhMXLUt=H*NZd<Zvx8e8iYa1fnlyScl%b8p1w z)nb|YdRM4K1rFPma=XQMytm*jeoAM3q_#NDpU55BE%R)Z{#qylBTLtPEmYIrHc<_E zE!3d;9oWIaGWyrX0p6lKnMKQUXS6zmO-i|oV|qmOm(pgrI{aEFwfdddqF@QD$@T2~ z+4$P<J?tsnxl6j<m}HD9x;s><#7?X|MnvR&-J{nNTdq^L?+!JvUQ+XShpIH;lRHL2 zY{ND~(dN88xd{*4QC@I;t=T#u<%B*x=P{Oxj51G@kG#It8`ZD7L%GdMVU<%Wr?l#Z z<)z#iW6t=hzsJ4OmCIjtJ+dW>SyEoLp1K~>W`pYgdZ=8}PdIrG=015nt#vkbvJ^I7 zVXVGcY{|BK;m@pKrnjiJ_XZ2!c|BAuB{`=kZ_d8?U+5w;zi{sdp%;q%*M-DmPJ|96 z1n$F)Y+;Mjp@E5o7te&o4UVzwlO?<S<Nb+O3cQZyqdxx5(bypVvCPZsw=#=|BsQLZ zeERf80K9^EvP2O-{p)3@bTa0{c<e#1+%%@kyu5PLYDn<PP4nR_nV=!e=ER)1C0vij zA;)Fw9_ny5+*0Dp!R^GHXD2ZW2fB&*jDC+FPwku$AI$qo0v`bfiQB?M#dpJ_!~@|8 z;*oHHcm_O6JP&?E{0O{EyaHY!-pEpeXBoh*<}P|s%rcNdF@7}h-s;H1E#5EjW#EHi zZv97MZvAKCD)3igZsaL(E0|4@V_a}Y1g<dw-yzOA@lgWd@-XY77+)E7#5LfEI2SH1 z<}T&kEAw+<IpP*@C2?oCh8TM^79S-L6ZAwv14-x&Hxs`Mw-WD$@1jwx%v+p$#S>xP zuP}ZJtjk>CS@1B4Uk<Zf8uP4#S*cd+ChUKfg-w-&b?^f5Q!v|~ae^)ITJctRllUe0 zS@Emzi{cOALh&~+pPM+JQ}BNAx9~w-YK(**5co(EeuCNdj1!!L`Gibgf=`Kg*NnDM zIz9nEw{v0}{#6`;e-}sLf5j!?#6W!77+X^DR-OxByR4$(>TssGHe6QR3a%_>)2*Au zUEn<Ny>LS@?^K$Lhrzdq$HN_T-xe&GO+vd$0y{sm_LeKecZv2EvwCZQcp3bFnBAjC zh#!Z?iC4pu#cWPGUCeGrbH$rjYP?7S&mv*Dm?a~t#Jr_?O3dn~7sVgJh2oE4-q~`c zkHUP)qQ8gvyh`&-drZtSk#A|f)Retf`S{69tY*@Mv@olgc*D<lHjUtEnl1(NiIdKO zS;j!KH(yj-9WE)(h0BO*!{x<!aIC5XcuK7)W^2rP;udgYacj7xm`#A%iCN>+Nz582 zU66|v>IL_f`2O$!G0&*FP?s+?<%LF<>SBWJ@FdB!3!X0C1J4!njJHV48YEq)i)nfG zTP5-AsJC9s8->l{FX3(C)9?;mYK)10MBr6PI1BF){{kNnUxMEk{|0|7=9%*gv4x-5 z*J7SIPm7b`AH}Sd`bC_<-~VqC$bwlS%kQ!rtV@33YH%@$uLHBRmwB4NWyI}Z*0(aA zm*}eEPH;_eXSkmD4!AKK;{-gVwv>ds;dWx4UOS2V!QI3I;CsY_;J)Gq;Xz`ac6ApM z%%7!(x{C?SQ}ATTGmf=J(<Lwg2`qQy3KhVM#Is<&Lyz(6;Z@>|@Otqx@K*6oc!zio z{Hpk4c#rrC_<%Nk|2!4GF9|{TV=>Q)Ux;~D{90TIJ}n*s|0re+(l25@n*Syq3I8dc z4YOXJ8^b<w$uSA=WW&-+CLDmH;zMvr@fUCzF$=Bq5QfPA16)<&&%!mu7vOqgo-bO6 zZ-U#4W2F$dLjslHyTv>g3=lVh9~8HOM~S<@6U1!u##i`p1Ny;y9RY{$<26Ew+30qS zm`yG==)Nt;bT<N9B!PVno)`Cn`F;e>s6V_%JQ6-Ao(X>>=Jn!BF|P%u#H(PwTaWWu z51$ji!SnyG5;%wiHWg&1<8T6=nrU{R(<36n=inj|e+g!LN9JLJ+6?jEaJJZobA#@N zf;<T@OM{r7O<i<16b@?WBB1-Bz`Xm_{ZL?@&vic(xGJo>p};j@-3<lixm|Zdfq8Df zR~Aqg*4<DL&(pc?h5|Q%he@91aBPeOSeQFed^<c<+#S~aP%ts?kXe?%Etmr9ZYc07 zSa(B#kHNYd3d|c%-3<jsVRXD33e38A-3=uZzyAybbUzd%l!jlI1=NOhKNQ60!3QP2 zA^efJ2mG11H_UQ&t{hKRr^Gy2>24^9=gI1v#IuF;uexsw5{4r1yCe*U{}uDh#TKue z>1a449t#&0vu2}&m?yDP;z@8>@f5hSm?yWJ#nX8H&y&DRxS@D4+*<rN+)2!v&~9SZ z{Pz}bg@=gWfLTt)m3{{vBR&jI6!ZRaDjZ{`;|R=_1m0jiBK{6uDrVcj$HhOvdc;Lc zdjWn{;#u6WQ~VdaM{MClbU@5A>_=jpRb#$m65tKy2{CUfzZ3JOQje^Ng|QsylEm|- zQje^NcorY%kriRwRH8m4zV-LPj(9vA5l@7RYvcFNKFpbtumCPAX03h=@j5t9{3P5+ zya{e8ej2`2{0!V#ycK5E1^4uGa9{CG_yIkrArf{WFhUac!{fvU;mP8!;5p(m@FFqK z`Fb=(%;y()mBe3z*NgvvH;ey)w~1rCsnnw>V&Vi?kERGG!h0oC2-c%1B0dGyqbb7d z1E5D!gn8qsM^l73w6z{h5oQa5Z)HB&@K54$@C66oKX*$-1g=Oz9r!OXZ$kZeJZGNH za8P^~oFeAMCRNNf-s$4;aF&=Y1uBTAz}3Xlc>h;R0<(~iFJ1sQ5wm?;D=}{>Zx!>V z@^&$ci|-V_2=^4TH9<ddA<Q~bZVX!%JVf*S|2hJrC4u#i6U6Vp1>%G7EHRrLED*EL z^P}Qp@Z;hW@H+7|n1#_?FzaFT$cnHF$F@sC5d`$eibyC8>yZ^<7NO~p6=C*C)*~yz zZD2jJBFrwyU&ws;X4J36_rj;egJC_gBJ%UTkQLupp_p$X0)I-T0+>w?xu$bq7Ejac zdR#>OI9y!38ZIS%0@fodBL9<c6^Y*n=ZZJOb;Z12Y@`P@#00M+&_WVeT&Ra!L_Evw zJ4!se6|=;YE5vTacZ+#%*GKHf{lg$}GOR~jM1FQL9xd_Z;0fZMy#FhZzz}$r_+fZ~ zcoO`mnE6+Tr^0K+)8UQc+3+*sx$q0(MX(;B5i7I|-i>&D{^$MKo092q_+9a8_>g!l z{Hb_7{H1s!d{X=r{Jr>f_^fy@d`Y|?z9vR5;h66q3H*eF0P4fJdwGB6h<|}2;!ALG z@gH!e_+L0j%=X`v#133T%vOYT#3kSc+W7sm`*1T!$b#F5tHJHXd2kmon+0?iw}g9% zd8^i6+!nrH%-go%;*RiGF>l)@vDFy2_-+LBc#tsf;pRv@@7orNIXd<-F`F{16wihA zIFXok5v+%agjd0Om`Hd%yj}9|g7q+wh>x)+j2<Tvfwy2iP9%H;eorR&6h16I34bnT zUGs7A1^7SW-{3Q1-VL1>mw_*fSpoY;SkC|Kxyugj+!NK|BynBX73ae&tYjYEC8dd* zz@^2_;d0{cupUbi`5%DwSduUsAk>vS1#C6iNCI<_&_cWnZY$<pPe<{3_zv+__-^q* zxR3Z_c%Ya!H*CMomHrnVDfZ(6H=gGCKN*23k`RJth|}PC;s)?yaSQk{aXWamcp&_w z_(Aw-@o4xtG4CZ_67yanwo3ww5!fp(gjuu5wdVc62jV^O5%GTbsQ56<cJ$1D8U9wx z%lJ>?k~qa*5NE?z;*R-lLEtY*;HA}%N=nYC6C4zGh4lcHh-ck@s>IKL)5W|Z>hUR& z=UKR##23P~#k=A9VqVmm7Qy$=h4D((S`xm3Zxi$Cr3a`)9yV6#E%Cg14G{kYKOhd^ zWTwZYM1Eed#z}k$c(OPfo-VG;LFML3peDRbTnAn&t`Bb#w}zh;cZOdS-w79ryTh-G zd12Zw9t<B84~0L1_4)r{1U{35Y4Az$9QbGPBk)BrFF;qtYv8}dyZ|Mj7K3~AdDs@e z0v8d#2Hzxp!^Q7ELjrq|kS*R1R}>$BtBc=(Yl{!Udaz0?>?2qYRtbLwx0XD-Na?XE z5q})+Eb%AcyR`BBe}}-mlJEn3pZFX+M0^1rCjJ#3Bj&|xqL}?8SPjmt55jZBsqi8( zFIdaPW#CnOw-G1c)oZ=DJiJ+45#A=|K*c-6)!|pgHQ_zt+VBA}2Qz+OoDUxnH-wLg zW33Q4A%UK-9?%ji#4DK|&=O`dwM&wRSG8;6G4Q|Q32+jsakw!Bup?&g*-~^VT;6e( z&o+!;;qyb??~3A;iOXYnzke(B9Y5BoyaIeQQZw=4ulBI|yuj_~&n!?Crn()irwhkS zMR!TG>-umyavfHsX1L?53u^fcgf^=0_|aYE&2+0;6;$7uZdtsFbLLF9V&bXJxcI6U z5#ztBw{9<bcBUIi9MaqC-<vuM!S&aJjS$2PJIumZ3&+$Leq2*)@DVQeAkIU$?PI-U z6a9{b8R{Go5}W;kYeM`zvBSbQ-m$P$w-l{kw~p=;Y_%<HJUqNKCB&P0s|bpVHV4#K zQ^J`sRuQ66D2qh=ivKKahb7!-AIc7WX#6<|I}+_fM=%HLY!lLRkqu2nS*XUQq6`J% z9fSkPEDq3Jg4ve>Q?s=*I<zBC@^bu>6xfD;gZ_V$@Pg?;^#KU@XJbBz@zGZ<Vlxxt ztx4Nsv5E1)S3dTs^|5gA*b2-Goq}0Yflj_-k-^5>P1%jt$wZvbc>t5goU8bEit`ep zCp#a&lN{FUPjm+2-wDo8+`T>QEI{gbhlT0moD9T_bsk0P7{@})XlD}^G|K6Ye@8km zBXxu`52-OU>U;&8m(=S^EX)oh_uwl`oqG`VCEj}vzwL8+BB_?M9<wRu)W!_3ecO;B zd3X%zm}bcroQ6G`3KE^ONU@x2h}q|JPT^x(g3mt?(<DE=1EEj@Fp|8B70MX31K)r0 zZrbM_<t+Cs00Zt;<V=3|EjZpwH~D?qaam82e3<owuG>XjC<s^S$0w3tt@4Pn19lzO z1UsxJ(u0m-MOcU6cUX3w;CzedfWx}DL}wc^COKsglk9wq-4S$_Adijrh+tBmpLJ$- zejfx<Myg3u!xg&l_T4(BhYTso)v&&@xK2g6+SYN4>s@pn^L(x2eZ>lxu*2f6jG}GM z4sK<t&b@<~Q@5(iQ^Q%|E}UiuH_3NXmdc(MPA?h6p0wKdxlQrexAn(oukM%@u3cBJ z$zXqclG#{mYh{2lx7ZD&$dHG;aD+uyNaJco`l;8ag}ao|Q3X0G8`0_gxb%Vmr?l?K zct+Kj9)7B7A1?nEi}OUhuO<GsR_{e*Nxk~F=#32_wd7j$@AU9-tA#o~BmBDmWP(~X zGrYyBs#?zqKZ6&xT$qKIWt{h`lC#6jt!#DA>~N-kucaQI9WHB)L38zRT7<P@)=3_8 z6|pMS*Qx`v!&T6C_`>XPnHam`-rRy)ah5A{iNS}ss^_>(8Mqy+!r$%9tGR}k7}pAM zHB&IfMg-b2`k!|YRhqRpEYU073Rpzc2bjAw>(X}swaNme)A7&S2>EJ1=u->lgsTnO z%RO97f2rRhA%h3I6}8w3q9$(7>Tqce;>L4nSyms!>BX`1N-vHrlJ(*y5?q`H7q^fx zT;zF2WzP*)wNh1wx#7}HUEC3sWVML(s9rEjRWe8TtY!L3>5ou`-Ve)lDjTV1uy)3J zOox}NXXb`;&~^4heB8W)^I`)7>j^)1(Wjgj4#@R>?o-}}Ww7(F^`uU%qe{;Ur=x>F z{ds7c`l%W?FPxJ$+r=boz-?7c;4Jt&?92Pmuhz{ASFVvAz|_qXo<kh3{#lr-4~z3< z?B$-ik-%w+C9A9R!lgR?fsA!W`>bvW`pE6d6}n411D88rUIngEj1>sFS&Fs#Lrjo1 zm~otd*W5Hr9uEyr{pN>r(SmU4{BTZe3DUT)9@RPDM<|0WysV`O{Kb5OaCsgyRWR=g zRu}&yIA;fs_<afb?Fk5ffd8%4E0DG1MDDnKdR8{>u}gl(S?x<;FRO|OXRzkZ+MmGR z>OBmvufhr95lave-)-?Q@9?V*K+Znw8<W#U^;!@vH|!!}OZMPw5&{blUlsR)X?kZT z=-(;tl1s7$CDOU`A4izGD>1;8ID}9JyQ8D=A5%{;%=#-US%*vD?jnP=_f}ActEh_$ z!Z%^Ww&X{`Id}9yYRPq+cP+i_l?)fb4n~-p^ftorb*ZJNW(UFey2QgR5azzFqt|5; zLiPHo$&Z9@k8(ij(m!KgyhdCFj;oW8gm1<@Nn~NTT<mW|$G3WGU^AA~p_sR%t$Ilu zS(#h;oIbVfLnyvg&+GL%!LW~8^@0xn&9L6e7j-xi#kbrHv*n(yVBO(oo0c5@^sJ)+ ze#>gd!f<-shR7CQiKBWYdLkU(+@pFW<}h9F`gr&ygzMd+5*CGP<$MO~4P<2LlbAK< zR%J03l%0St=C`Q2Yf(72+HYLw2|c?gx<_T)%J1f6penY%DZ>{rf%PAqK3VNpgeKMX z)L)CjCG+)}F+Gu|#>L23QZZwCB2ParBAkYulb*;Q!`BG$OUTqATXk5B=G&9hlEvYi zGPO{dSW?gFp8)673t{H<>AV}%k;UO$|LcAgSQ5^zv5%Sc<_=BdvGgB=>viM$57S}) zl0KYvcp?wH1l4s3+O?Nf6PJW@va_+D<CET_v$jAubL0U0MDI;(hgsdH-oO&9*VV}- z;nEeRUe7&U=YEpmqFm7QME*$kBV4bWD)(r(M)ohT-p|aW_cN!i@-(vP{ai$idNf=a z0}icu6hHnPH2aFL$4WitjtHlXs)fs7B9Af-g_*_+q)vPZp$rzkS*vyUGlaQ;YxD+k z5XsCTK5MN`Ym89VZJ0$a{?F`-15>Z*C}!&Cv!2(XS*poWT-v&*eoMnS{dXfRZRmiZ zKI<*L@G}UPT#v~S=I*Ut65%gygoh!_1-`9Qw;+_kHX_zLI{YcZRo+GJj1r7|Pe-Px zGgy+<M1_{&OQ@EP8M0Q+I+4grVt0fymf>5sP9^f!{HW@<Ec{?`HYBl^@>JtsPd4N& zldnm4b$D6$riv`W54Nw#cxLc5{st$9;H@-=mTkzZp0DvD<t`7GtjvZ1OquLuZ^(Vz za3=ooHEW3VaI(4BhO1T9-*)%Hr<R9zhYE+SNAvr_-=7RW84Xs$sn3u0*sAZy<dXmM zmjbBu-zGQxZ<=?GC~4JH!wSRpf3XfDPWbB;9xe<I4abLYT5}-$dBT6QQhWhZ;i!Y* z<3$Q@KNb$Oi7mku3$F>#f6EQCve=8?V3>DLUOelEJ+r{l^P7fQKkUVSXqbhUh{uCI z{*D?6Ck&r9%=<KNMpq2~ZP>!Cl$R%Hm@k^};(3GTxs0v8xe|549LT|otD?TX5-l6! zU7Q!y)^I1oT@Bx3xVK^6AA0lQU=5xp8jcy}Z6xx<_X}%zy$RMBW_hO<&$~>|g@$>* z>BYZinB|~e{AY%F8|uZMVF9cc_`^tGZLSy3T3gSlhI#+$#j|qOGb?93H#5vzS}(qv zXKp`lalM2ghIymw#j~Q;Gw*vnKWdm2tX}-HhW8mhVE8LI=1p+INH}l!lHuPC|81Bz z++G9ih~W~3GYse4a7<T>dK2?b-E$+uEe*54*2~k;a2Lb8$M^EE&eJpR^*vA2jvs%% zX+{F;IlWBF4YO|3i)Y=Y=Z%K>xM1OSihnHm^~~x_&u<$3G-d>j8a`o|rNG|AeB$u@ zyJ4SuBc7$eUY?L)mI!<Ctiq)A_NN;OEFShUl{d^1VJ|-4a8twV?ds*Z)iA3tz4&g1 zd$0i3OXzDP3^2@kOE1rO!+fmrMz)x5m{pZt{9}e$QtZXAzwV6q^O%?L()9$?PpT#5 zQ%c0%F{0i#{HfuihWQld4c_;&VLr5ZJr`JR>p2k*N}g@Qe3V1{-TGK!VXc>`f?<}) zdhslW^~|zY&wSjoaFfBmwuU>Y^%IMghz&5Jh8Sj@p*PuR!xIg&`q0b6Cr57-k>!S0 z8)h}3m*<(d<J<R~k+9S7tA_b7>P`HSVLp_4@vH*${F53{5#QexBMLQs*OU1`YT>4m ze__L^hFQty<>3RX=c<Nl8D_<vm#1;u1N8!$8wsq~^D?zJ%qL(kzPI5)h95A@$~-Us zSk<>uN?B`(T2d*cM0viD%1c>qc#Gj}Y9FSkxyOjwZ}@$~9~u5eWmm>d<zx5tVPXuk zCe4fY;bGddW0*B*Ui?jlOB&{5yqD)@!*%11A2bb&gjR;z8t!Dct6`Q4cncU}c(}UQ z&R-%n(TIu}o@IERVHPWRvs+_$qv59wKW})4;n(7hUzPS42`s7b7I4HcODw$j?+l+a z%z85~&o#q;8D_nimnT_Y!|}w#zY?lu)szw?s~G7u4A)hCksNDoM6veEn^k+mw;N{B z3H$u<ufO33470+^%k!||$%bdd9p7Jbj0Bd&coVNRyvgtu!!H<q$uP@sy!pIm_+!JL zMX-D?(+MNtwBer&pEt}xA#d7%;gI1XhKn0c_ss3j_5yHu!_^Gu8fNK}x8OF0I~eY4 z_#VT(4G)B4-i+=y5?G++#TOW!ZFs(67J6B@9`kRl;Z26O7-rd+<d6CG+z9yIHvFF9 z<AzTf{=x9ihFQwy^)KWdi07bTS37?E`JzTb3B%cj%Nwp{IM;AJ!wn6yn9o~@&W5|k zj6hGr0}bDAc!c3GhFNatEnvRkM-4w_c%4{p|3)L>S;Nm8-e>rL;SUTSHq4?*Z-q`9 z{>kw9V!VsYj2}2G%k<2fI?pWA^qguq({PsIiiWEiW-+DL&$Q`vWBc1&51@&rVU~(| z6ZA1W$nXP(M;ab$n5C)Sd=?m9O2<&U%|B%%tTp_kVV1ahGkV4F9>e<$v#8d~f6VYn z!?ACTz;A|sH_Wj}ycq=yvtZYYFJZW};T*%&4ClrjzaL<Uus5TYhHo|8(eT}ddl?>J zc!=s;E2V6VWyn_P_)cDCc$MKN46}^c%fHj`Zo_*Gzhn4)!z`V~eCp~YpE4587(Q$G zSHoA;*FP625euUr+FO@Y!)b=g7%pp=CE!+>_;%Md+}Ln)!)*<>k2`*DWYM`dqke{m z7#?bPwBhlFrx~7Q_z}ZP3~yi;TW`UejfCe6Z#TS;&WdmG0mB~{K5Ur9{9gX=4WIMO z?Z4;+-~>F1c@rcXPBC1}a5kNd3Gr9na5clZhFN*w<!7mL%nNid5;_~c&+s6_4;db5 zcq*L}U!j?X7Z_fA!!aN09=r*jGQ7?3i-uW&;pKnF@FBxT3?DQ6wP99%SUK_I&-bg5 z@Q2}l3>QHahPU9TVb+USW#e01!EklMH4Wz*Zp7h(yop(%;<=0A9)|BV+~4qE!>oz% z<}=0cOv7`<di$3e3Ci$V!%rG!<&L+2R}Aklyx%Y@f4uz144*8)YqRXSZ;gbX4gX^J zis3&D^KsUjPoiPgGkNi8hRa;{edtniJ%Cyu!!-=EiprZ&bHi;7w>R9?@Lg(ZJ}wfh z&hln4&hRY5^9(D)s|;^2yxB0T#H@1h!*H+RcjAs8=<gc|M+|>%n00C1jLsVV)$mor z{}}e;xzL-|H5@64<$DPwjD!rsthDp;)HIxLxRK$OhHo+4(Qp^f-2NV30KV5SYX`jr zk1{;L@D#&y3@<Re)UYzl`o_-Q0=5|mFByKt@IJ!_46~xro6k{YH^gCe*@(JkI0eto zURJ&-$8$-;r3|xz(_)n({&Ef1Gu+T{i@4*5RU0FLHKX2)dK$jZ@F2q@439B9$#8*T zzNW{U|6}Pq3CLQnF%s4nj%bwfd~%FEQ`w1(f0Jm`Nb`@QKCzmNf9(F~y=r_jje>Lj zu}7kXqFDYlM6JB{s`2~(4|DGsURAZXd(XMDlB|`?)j|spAV3Hpfj|fldhfmW-jQCU zvp^|QR1jr=fYL1Jwz1s=6{RTlf`}DygT2ePZM*M%k9Eh*InR5(9G~a9&blD;_aA+Z zHb)<1jAZf0!}Lmy8t105lKGNVT=x-6jGsH%oCZhFgFkM0DH%?FiHsH*f1i`l4&bkl zb9wmi@W<^IB}10HR=s54&Tt9}$<1E@CtL9H{Mnfxb(8N(W1&;mC&uXjbp*DO)n4V2 zrIHp<MGib?!xj9-k=3xUgX8+9bFpzrH8zg}rmAvYAS)%fzn7=s*!SlKUn@Z7Y6&u8 zEpb~j7%%ShlR8smq?j?!>2#WBY)=z2!e)yZN%O^wjCEu<NcVZVO}s?dDh(uyvqMY^ zB}aral5UrJ6)-36X}22Ko_YhW3AU%+fNO&vlbJm56XHf-d+H6$G~@ffERA;1cum{^ zY>&Nxp-$k7Qttu&Slk=@rMNHnTk#;UJzgAkhl2l*`Y3P`GAsi<25e8g;ru0|!XA5r zxMjw!MnhmESK`<kFuGxhV{gEy%<Yb5nqd~<S_5)6xUIMvxU)D1+*6zj?k}zd9?A{G zv|I-Qw?LEYfw}FO+yH!~xDd=8%~Wp!<}PM3qS0ATMlR>e+#tq_IyZ}9%-JdCOWr1K zi7^`I5Cy2x@)0pDbLlbFY57SpE!$(q0WouNN~v-@ZaZ<94KgJ2n?1}1%!smw*??L2 zexeg#ma#v?+2CY2K=m46dzKBjCYYx-Q2h#UIWgm=l9+K*-JU@MLyR1Iunm|I!ac~e z+y>lG+z#A{jHE?P;c!JXnQ_oh%)&E7jH=TaC9V!0C(Z*eAfwa;ScJJDnF1YJC8k5` z#B}I7aSnKkm<}BvV<edY;=W@t-FZOFtan(<SUf6bfjmj(_&Q7EGtyvmy(F#=J}WK& zzb$4dydY*)`bf-}<9=iYq9ynnaYr!sBU8N#n0t`P1Hf^v7^c9I$GV8j(v~S659UoS zRG$ORCu0Z~{}QK<16U#3!^goaRBdI(79?>F)O(7VKl&#)ZmS4;Xbmj)fyQVV8VH^! zW>sJht$`T^ZjRJvf)|Rf0xuUY1Kaa!VE$V0da2(6w&&MCeHVCJ$^FW=LD(fj2f+Kp zcY?XUm~VVH_yO_Xz$JGi-w!@2^+Vv3;)lS`h!2CgU6}410iP8=iu~uiE#YzSMezyn z$Kof!Uy7dwe=B|o{FC@B_z&?L;ADIX=-IpAbnzG9vf^*RmB99X<?kWzghyKV5nNmB zbJ185Cxh()HZa3A%dMpDfjfvxgS&|<fcuEEz=On<!Mv`9epPi*{>Dkjfd)4!Q-c== z%o6iptOa7;8opTE0=$Wg^2XwKqZs+r*)C?Q<W?~&H||HKd43yt=yFC3@z1jOfHat6 z?H$Q5R0Die>b1Zp#dW~Xi0gsRhzr4QiW`INIW=&n1^6?mcK}}!cLx6umoNmvui{}~ zZf0gkM}oP=nmh&^7LNn-7;~ym0cVP*gY9`Vcy-2#J&y)l25irx0ka}%N%P=%HUyqp zP9YcERm?Z;E#?~!6xRh07w3b=iVMJ##YJFlETNmNzzfA)!OO+n!K>^UG%(Z$0(V98 z0%!hixs3OSeNg8nXPWVY|0d>J9ungl>hP>in(@FV#mo~=iQ%2|7P&Nl_5VNr6p&_O zdiDdE@x~u~DPeAGCewZyG4oKCxH7n!m@!&QTpP@N&9uuHZB33NTjH5GYX;1a+OuZB z45>Y92Al~VNDJU>@Dwt>OpJ+{Vt(o8i_^hN#Q3&3E5#^W4$s`BUA|j<lZ2`eZWJ@; zZx`1B?-SPt-yv=Uewd7qF%ZYZY<Qg#GlrfQGt<2yW*g$21jp^y?>%WSbA2jq4E|co z48@Jj^sE{97cswb?B`Iu7ua4~44w$Kw-$pZgG<TGG;nz_OG*_sA!&Iggc{OV0OqD> zsxJgL5HAKd5wqHEDP9e3FJ24oD!vgsKztLJiwEhZ0gn~$p+nOp+z#gIK^nRfyjc7I zn5ze={t$SL_!00%@i8!071GQJ@IErCIVKGcvL&OcaPAZHll>4lP7UVRW74Pv=Bh%f zvoZ35m}!4T+!Xw#xGVTw@hC7?7}D+-@MmIHR+q#Rz&u%<W{@;-=T`|+p~0=$)L_~K z#IwL*@mz3u@qBQ$_$qL&n8|U4n90$SjNFGTlQ=F0%$VTr?TiYDf5=X68Dc5m@<dw5 z0S_0~1dkOnCMJs;f@g?X)6Eli0^4I`;Lbqs2C5^@nH=2hO-==GV~3Uk9?mW?Ypy+F z)&YMfqlTg7hsAt@V`3z^!=;Th!<Ttp%u4AMF_ZNTaRK<eINk=r`w}{UzZ7={e=F_^ z=JH2+&;$I3xGy*vH4W7VfrH{9;4Cr<I$wrM9?1-7EiptVKON~$4YtpDQaQN}xUHD= zK@V{ec(AxVc&wOFeWiE+c!78rn9CgL<_PdA@o4Zm@pRVz8zry~xRs3Jz|6v>jbzqn zcZ;Lo2gIephsCIs9d2-^c_smuIg+b^pAj=Zy&%p5bCqL8yh_5e4=I3|uAhtfG5nVp z)wT0)F$#$Dn;3pLNr+?Gtpg5<>w&rCk?O2TONkkax#a9bev0QwU~ViB<Kb|bBMpVY zT-r$H8*^zRnQz=j3_l!hf~R_I@Gvn0#Ley*C|1n8^ThOv``)1*w>h6X@o5MTXN{OS zpGzC5PLH>U>G92CzWqTm;+Y<BcNrN~ic>7c!@*{EtIn_MDKTUE1$zb!EYO2Dq`~xi zSIi>xftX*#PsDlPU&zS0c-X-+GLtD48HP-ELSm+UDKTTHytsZG0@pXv0?TD>G1H0r z$*JB9+*I5K+*;fn+)+FZ+($eOJX|~*JXX9E%<bfKa|QTHaGb(Q2rH<8U^3^g7Bi!5 z5Hlt=ixFYYHgQcbS2@ydUGP3JYstIB%z#|vNHZ+1T-ZqN#`^!bgx=72Qal*^1{rbA zB6nWQK)f$z+S|iTU?v;<lhhfwB;;D!W#G8fk$eR>BCZQAV;Kp_=&dM?mf))5)?luC zq~#9aI^p80hK6q}kK2rb^TNG-fq7=wyl^jEjC2s9yWRZ6$5GRDJ{}j$4m^Cd=9|yv z!_2j&=>n*JV%GC<+`PrdY*YIxm~j@FC0D`BYV#~acb6%@5RbdeR6brX598r0z1XBJ zf|(I!=pv{NF$eMRIZMsYRK3e|U2M(n;G>WEl#d@x(<ONHFzfj^V&1~T=d3VSEDiVa z<*YDE@Wk%?XP46XxT&xV;wCe78AR;%e}v)%6I>qd?>=BgE)Q2v{@Y&1Id0Yvr?*GC zByR6MzC0Xtr<+%nhifJ;Lo{7TC`VU7d5o#LB3v_N1k${I*z{TvuI5I~94IAk8i1h+ zvwH=WZ7wn=sImcdw7uzjTO2k|npiws6EW13k6X-GJ{~gb`50p!#3T7QvUXY1cM^6@ zEi&%Pa5;17>C(w%>dnf})~`XMqJ{;H8Z<3xj57erB{gW=bnD8mYq`sc%RlL52I7a3 z6JI1Gt^N6W;_>GlQI(RAjeMybcKgp608hJ6bOXQnsh8Xz4q)T|!&D5U@(^Zh{IBWb zBQ*#kcH=*{NT&GLz-d_Ixu+@q8zH2wVafM#%cri6x)Zgcu8!hZqOJj7VjZ7C>wbSd z6i)2;ZwprfE#VLDkNONc!38knFT58BC)tnkH+=<|#xXnGA4M}bA>dO4DIF&SEQD$A zc_01vmcqrjcQ350@P38*a&HrOnfG^?UFyAqze_xh*Dv;7h3+DIG5A97-!OBPR|>Dc zz*~-R%=Zj}G|$@%C+B+CKzEMEbL((IKoXot8Fd620hT9h-~Sp81+n3>9JcS1aqBe9 zr0SCG+fvPa2Q$iset@&7r`c5Yg0;*iFM0)W9=GXu`|;QHaC)ud^WFm|c|0(|?=^?7 z$sVt=Oz~>KV5&C<;SPB07zaI`l$hp(xm_Rka*u{7uM2|gcpTbty%A8rz1-ZRj(fQm zQTqUc=K0`;>-c!GpV{$}S1q0k;@#Z$!)OM#jpA<Z?J)0T41x~s=Kdb+&v*bzxSN|o zpw#4rsDvzg8TH^RuI8roXhviF#ns$r@hF`!30~o9Zf2a!430nHYVLXvvNAI1SmJ8# zQP~;nOyh2D-VU3S!3#-nH}@v^lb69^XWY%b4?_J?Gv+UFa5p!Ff{gDO(19*bTP)02 zO*?~K#%;3<c203MH-+XIbItabz1&Dc7{k@v-SBAR_%@ptU-oivS<*KzdxdU>sd*aG z)uzX3Z)Ke4!@3b)E7*2Fgz-#94-^<9nT!MQ?+8_9UP7H_PyiS$<#=ud_M}_8*?8TA z-QL!2c|;lXtW};X4YpP*+(vh1CAqwIJ2RI7g=Br>S?6HBh<3_0OLE8j>25P?%E@YJ zR=nbsuVlkHIK`$MEL7$m@)YJqw||wY=Al=-CGK34f5yvnN0}~Xyxf?z@S;s>dQqvW ziJ$RmLHDjR-W?engLEIH*LW$%-BqWP8S|<)tR{Qx?vF11+EFHV7Y|NLc>bexi&yQ! zt&6XEjT^P6;X)sysFZbuef%oc<3bxNZof)4P77_sd<U!fd8Wr%uW7kL<SKX0WmaFa zR?V)nUKaMZJ`6KWS}}~<d~B^ux6ZTWl?cl=>%51As#KMM*k(N_qWplV{hC+#3Y&g= z6N!*-Q)FL4$mO@)J>X-K`nL2bSZU_G<~>!_hPt$U#U*&5gtKK`Cg^jNA235+_bT^d z&UQ21t6+I5f>&uH6ExFZ1m*pdSy~{ow48@rZ4V4K#D5-=Rge!=cb)a)H)s~DHc!6p z&F)-^cD`oHGA66wzq@NcTFZ@Xn5+iJE*o3FzoyrtDO#_;rq3HG)-y}r@WzyzM#uWF z5_1|^m(mb_m2%BDZ+MN$*%L5!T1^`ZyLc!RG+Vvt)py@Dv)=T|;1rxSZ+drOUvIs) zyhh!Y)43A}H%ftZZZR4yi6lN@GpO6I3X49>u;{z}oq9Y2#=Ve)WKjs7g%x;m?^|Be z+#48wDGZ$*EOK|TL6mSW#m^{k`#FV&jQ6%zJHx*IjW)}N=~`h;(;4b9PD;7UQusL- z0`-Div+8ZHwcFjCc-t$V&^?&43A!es`}x~=yXQ>Sxf0!}RyPf8ZrJT~&a3K<G*ixb zokBOj<>Wao=S7-LHjhFl;|Ri(KJql$;ZX+9Y3Vm#!6DpCWrFW`bu!N(Q-@pf$f+o& zR_q_AWm2l?@s5{Su@oGPb>{bLEKRVyCY)*goQc2V;S3+Bqz|Wotu$c0XmKBGMTQ>u zQ=w%JqBMO3P4N^bnX)%S%;hR~De#=aQfqi56IZx9(Hi{2+RAD30fJV#7dgs^LHxzs z8sSpuChxakXLJ7c=;-3(=e@T=foI@`4`)XI)m_TCx_pG$btEI*^zsEV%zX#a0&Qka zoIiDvlRtgd__5RT7tEVDcV7PFu?xme89R4EKK?J5I&)UZbM(Y{vx^EEH_q3y?(~II zXB%ugZczM>FT67WdntPH$KQKh{eOAeas8jYUpvH`Gw&fI^T*k57xf;0oRH>#9e;() zcqo|sbtI$o@VAnTe9Yf|GTPw$y+CFU4nKP|0+NQmO-PNB?TC-D@RVY&9=~rWuxE!K z&t5HAfWYa8k_89{$>kDeTJdX^nP3iamn=ZoMrLmgzlX^fui@`2GP@-B^+!sVtUtJe zCtH^+K<I=w=DZqzCD(?N?K%KB0DI1OngR3Wri$4;wR8VaryonDUIn~LTpe7pCLkBg zH34+T_9{!(1h8r{(qNXon~Wr2?D2C#W=HR^m@ju!jG+_fq?jH*Bc{hMiEDt*ife*- z&qJJ!UIF2PH1fb7iR*)T&jZb{%gehR$n5g|C~gP-UEBlAvzTb67dTDa2OJgm16LFe zW3RGg9l&U4*z0d#c>*|3h9-eql9d7bkdXnI9D^?75n>t}CuV+}B4#Yk6qg0_pz;ik zDr7@gBn_s`Mly0WJ=h{<Cg)LORA<`TIesvsowXKcrIERvhc4qs#K^bKaWM;yo#Kai zHXYuGQv)v2^7+g7eK9TbmOz@JWjpB)re#{<930j8X(3bH6Z0)I#4IeCViu6fVxFw& z<Vaw~xk6kOTwk06ZY*XDwGh_=w-YlDbrI)*dyDhI1I26*3>UL6Kh~})K&aW7pCXM8 zV4i!#x9J3C^O@WQ%oYlH2zaG<0+`KZs!s*;KyuEt@x^wFYlHWT8K8sWBGy0mOK1)a zo;FU)t-+6q+k#Js+k>ALGjK18yMkX8cL&=WY~W5G@IR&AAI!Ef-5&)0oE(QR6vDrx zF#`N=@n|qRu(U82oP^4WJRcksF9b)#OTfIff@YS1D~j=sPF3+LFwYUEnbqKUT?uO; zG!$P8ZYtgYZY|yh?kL^^?k?UB=E381^bYV~@jc*?;s?Rw#SekmiiG*N^Du;2(l`cQ zB7O$EO8g>to%mJob>g?cTgC5!cZe^5Zxg={zFqtw_#W{m;0Nuh0)+Zo2>+1AuVA|x zpj4t*+SLGH)Juug0ASV!b};}LrO~-SyI}ltJ`%I|*{jQ;$jr#5FQ+n*qG$?=nKq>< zlu2k*5VID`7Spp_F+Ix@!-`WNW|=M$)3f&CD&THn7HK=t4~w~AUR`c)wy6)n-bjNW zGj#Sw8ZZN4Z=?Y;5OzWz%s|-ba4-Y0h8}=f8?sGaGWEGlTnp;E#jG3liW{*0e~1FU z>kRcH;u_%NVt%Qf60?$dQCtuFs+ceEmbeA@g18g-BQcBO7ve$SZ!9DJM?v68<qX6G z@bBX3U_ZXmRA-Un>Ez@^;HY>dxU86^CQE!BxSE)QNO|II-~#auaATfSPDgh^uoL>M zsPVHC`r`gH1IAa@nM5w1_&7}$Gdbppk(ZrCVrIq_Vzw1li<u92iXq*JGfJ<QPzc^j zW^Tfd16?J|ktZ?(@t`;Wev%B=nQxxEj8BX4a9$U)1id4Ug5R^N3SgO``$!tqz(0|Z zA?N{5Ehp0gPc0{BfYZgucTP;q2xD)6W-5a#iL=4g#nr*J#Wh&}=S!#sjYi@+;O64G z;I?9Bw9eupuw4KE&zgZpQ5{794`+gyNi$8%q?s*d(p*L6mN<rbnKT$Wdyx#(`PI5! z>iOWC#Ps+UF+WbXio1g!B;(bY96S$*oCbbO%vgLv%vf}vE-uqOv@V8$;oT!}q4Op4 z<%rNi43SS93F$}k4?KKrx|@_yp<Wo|9XJZAd(7>8bTQxa@r>y>8jml`&3O3yz060W zVYG*7G{zcTgNHBB$Gko!)XP`8kI5Yi-T7w0Sm<str}#K)%8Y}dT7Au=anO9y{9_z~ z@SUkU9-2>@<>MipHQz(>WiK?HCcvQ<i_NwPI79LUb7BI9m6w?hCxmJy&p`5AV`39S z)qR(W?9sJ7CWfNPzNV-fx4v?^l$lSl8N|(2+yxOYb?-#jeGaPAw~l?Ml=*_HUCeJ# z4HdOPnxQ@zhNx<XBW$xw&q*-+(DkU3%&IzpQfAYn%TKVacRn+zN#pFTtG=%3KC^Ys z`6}r{7|G1jm0WY%%5cTWyv6T7<J4OqVYvAd7{EC7eo9>D$44sD7UR^v*hlKU)bpn@ zBf!EBcqIF;#^00$R^Pwd+V%VSaDC-W)m0d>Pd69y12+baz=+Q|<gj;J>aTPhaR^s; zGy3XqD>H0r=$F6Z5>LJ|hZdH;(e!?x^vU9bSB7rzxwXu{R+nDr);Dd>VSx3h**h{? zJ-IcioWon^d{y23-dtQ$x@K}JGIt_9FNM;hZX45JEmV2UN|~*(udCzq!BuNZmoqEB zO1tcA;s2U4gApk%@50Jb$}9)}CuNvsi0F^`_}^2e4Hf;#Kifx1%J72(3*Y1M|C=(r zfD$QFHjy%E|6?iB^cJtOIelO0cm8VfY^^q-RPpd{(q2jW?@gGzb>4px#>{M-TF&37 zQG>>|&>SsZzs|eC7w2L{cLt*J9{g{E|0O@)x6t`>?x#JJG550_4<FAH{@;&+?uxvF zG+AVgC6}S}XYqQB>ETai)s1rX86-Omv=(wo(7&0=Zs2Def9jRZ+eNd<O`zthPe)R( zv9|n^`3U%jTEjjboEI!>-rL~iy5mf6BOY~4{f%B`v^I3ysRqW{;eUF2Gh`#ir2Cjv z8!>>_*qoplUb*S6q?srv{Z8}gMlZkraN4|<p|QgR{64T*78-*;?k1{pTL6B+KWKkH zdm{X`!GCwxQ_xGd4)3SK?^3+eT)D|>HOe}C4;|pja!xMW7H-1f`>D>}6Mm(tz?RGN zg&ex!?wXtgSI*M6r`bE;Fmd{OR%E;F2a4x#^r*L~URB7+b=YxE#((xwX*csQ4Ew9n zFqg!arK?V6$Y)Mm=T&mU#s9p{D+;9YJ};j$_`l(9=-z*&An?dPbE#vhzc|@=abMo_ zSu-bR+dorh&UbL~<BVBXO>{U+H+staSu^K3v!^T`J$~%$`3vSwG@tMA;(x_+TS?Bn zkh0mhJH5fl^QJDDIJ$VkP7k}-CNRS7mjVq2GQLv$aW<@E49{*l!pEM!%}hi#!0`Kp z%vJ$@vtYht)Qhu|CA?J3bc>6b1$e=1Mhe<Zba#6~u*@O?4coK0pNw`J&2Zv`%%;$z zVm5_Nh}nVQY%R@{1HUL{n~+nPRA*c6EpaaRpS+Qf8nqyNC=Iq`c`7*7Sr^;;wZUxF z^0q;$v#@hIi`)gAA?^k)FYXIwmZzBk;OgQLV7sA+Zw3GDje!{y@Ut6=z%ZNGPy}Z2 z;T7mK!!kQS90m^)GbYA}OM@qgD}bkqtApo?`Sy#zaXQMk<PC#lz9r`i$wlC6#eCzP zWTpMy%lJ+)9uCh+rx^zN?_vh}VKD=JOpHLsol_DR>gUA_HE)%rLku-<l_fLO=f&&* zzAvs1{#49Be=TkS{#M)yoPu1)Z8yw-oczk*hO+VyGNi$tXQntCTv=QToFlFS<}5xP zDgf6PHwJTlm+A~e3vqKW&n2fi1JOm?7Tn8@+d-obgaOj%2OcFJ2%aFG0OpCUbZ8oQ zws<<&ZZ3lQ9Pl!!&j(*EUJSlgyaIf^IJOGHO%m3Cw-+xz;`L5JQ~1TlakaxurqVIo z3Q@nJnRyJiK}<J~LBzU@&~bbH!$>@QXeQiu+`9^^MrxdZ>UOgL4_{%PdFq6Bg}dAQ z>jZ9v7+}hr#FY&_&{>#a+MdL%5D%BOP3vVRaqq+P<~r&op%7=<CiM$conp>YwIWn| zm{sdiOPQ=EpuEY{eFE1)aECZ+qbm^VO1u^#ncGEIv+0)nW<#vv(z=vagDIx+%CHys zb8QIQa7BfQ*7a%Iy6z4)+^_Jbs@iZ@qoDt%4R<pne8kVe0NQYOQu_1r&jN$b{~z{| z%ImAq3aCcO4Sb5n|JsJzYwh|2)<IvzL>n&hKh}mjbXDmW%%N+-4gd1j!#1%a4FeAr z*IE-k;6vNmHnEHTOB4GM+r<7U(ZuHdu*;g*9TH9K()iw#w@vI0i6-{^_2EBTa!t(j z>%*D8h7Ik~oxc^ovOZiC^nI3M(zk|-0$WfmAqh5{?pwq86WFImG}nh>il3kV)D8IK z`wYtdy2FV1$RNo{J&0UduDdn9Kmd|c`cw52<o#sZ4D<19+~mMKsAA>KW>hz5k(Ej_ z?`{oe#W}B+()0`HrLkd>8g{uohRtw%s?z;|M*N<6oIrOxcK+ku_xQWQy9Nr&z5Bq+ zyz}sNsTYQYB_5A=UF;Pibc?)qU~8e*3@TT7+*q@~`xn&b+eJF_JnmeW8}M$26LY-k zX4OsMx>ZlYY>vm%sPP7GB0Ry_?6#%*gIm65IJ%pcZwhyF&zlN2qw}`Gw7NOmr+p8& zknC}0J;h`Fl<EahVFbLEP!D=v!WG<QkqZCQisr%paA|nrPoMJ%*c(Q#yqV^eo5PjS zmA-UyxM2k@Tu%?VY-9#vSiX@Sw(La*n3mhZ<s%<czm7W>4rfMRO)(R<g=_epOEH_a zg<B&`FKi1>a`&2sCOp)A&|GK22WoJ~P-(C03B*%y9Bg~t@8lZ>JCb{n-C&*>v^|{f zdq2gj!xIbPinoWWhZf=;Li3mwf#3%7@%Hd&_a)PLN4Q=2J+NCV(wCcAf<2)h>CXT= z!B@?`9pTOmHb6Tvluk#3Ie62^@I&B?Ag?J-aOvQ1I35|pw9gFwVk+DcZkK%++OEgL zetq6DaFWLlu-`j|*iClIT{O#X39oXq%<s2^^V|<jot@$4zCf^e%Fggq*Y{1bd39HK zq<h#j*d1<ysF=DtoF8)#IQOV8gqNR=|9M&F;O=l;-@lWK-`pJ@@4{G%+wj7UnSNWi zFQmtB3vY6}neKbSJKP-e;hu0)I-I>X+|})GrtJ++bbl*8y*HfUW<(H7HzoOcco6mw z%%X41cl*MlV5|TBa4v4(Sh63MMw%!0hugcanZN-g%oH>0K)9?s(X2fXF397!SbCn% z#oN7w7cIs3a#~hE_9@+#ieFK2G7{Qpz0G`ZAbf>;OL64(a4Z(+1T#Ko?_Zt||9|Dw zZZ_cyi`N&2*M!aBr^3Jg<$CpaEgUCa|M60_itl?myrk!h`;ZAs+T(2Yl(fOQH`OjH zLL?tY{wQgKUu3pHB=a|bxsr`7{OsKmOl|xsAo)t>*IC+2=GQ+kZ43S7;_a9}n1As* zNX9psKW^qI+1k%r^GascZBq_GfJ=#{9GJ~I+mZvb^=4agV2o)dwv2<Tfw_Q>4Pv&~ zShIlRc6anw(qKFDJ8?Vk&*BbX2U(4ldjM@y4%{1Tn{wd3VB3-dj|SV89GF$QZOMVx zfNe_-d@Z<65}JT?bOVF}d9Vr0J71`NJ-D@aGq{uZMsN@DP2hfF4$Th{ZwHST?*>m5 z?+4Ek-v$4j1rqKDFBKPqSBW16uM?jHUnhPVY+G*#=!@W6r2abicJZ6wzlq-l9}=Gj z9|7Al1wMfAxHK+-pAr8GJ|pIk;G5zU@VjC*W<C&yz@Le^IrNe^6a0g?BKTKvC2k1i zKpdmG8Z^S<TySY|ZLpnahM7FDoo5CYg6%vrxEa{aGlRQ=?L0G>mvq^AX7F6Foo5Em z2itk(RK)*c2>s>RCh#!v_24mLF8!P&J_Md2J_@#T%W(7=u-#k^eiLj*M8NNYZ=`t? znM}m!b}{>=w^~EcVCVFJG_t{5MMVqM!FG2!I2U|a>b1dkcRAGA2z^@WO~5aSn}W}Z z*%`7M%3;1O_=42q?IC<5p);6G0eajA{H=Hp_$TpD@E_t4;AE6-nx6pXB4F}VFoyuh z?1z*Wv+t2DUJcGoM*7nbi(H;GwtyRpS+v@SZvk^1D9y7t^%3s@4-?-3=Ec-Bb2oUJ z_+IdA@!!Eq#fRa)bG3vc(70CoDENBuW8j;_$HBLVSrqq(p9J3_ej0qQ_*pP7re=U% z0v{2d20u^cM!!4=uTTIpo!$_40khdib@ox-7xw~xDrT+swRiydd+}iKFJdN>i!TM; znFeMvkIbZrha@b4z_parSP3pKX3|s<?*!Kn-wLiH-Vbgdeh6$gj>Db9;FeNn1!d=x zp?(qEE1@2DK7}w)hQ0<57ykwxD-NOv*|}v{E(@L^byh5PZW-!T!FFyLToY{Pmcezw zc5WHm25je+!R^6YxDJwU+z|p7wUfJm_lf(0|0W&{E*4J&pAb(0KP~1U*GppdB3~1; zgJ9>D;r>lvJBN&~s-N}0okWHJy~G?c*aO=+WH3Lkb`BXF1=~4fFu&AxQ#iOZxH2jm z4iB)B$q}<&xk8)+t}m_)ZVZmoLOlpAq){K-PRt6Vi?|iIhqw)RG#SkedNxs91AL`8 zA3R4~0JfXLVZIUAZVCq%!GDMQ2j~zz;CVu1=KLGPtbA@3PXzB2PXpgBW=_6eyco=d z>U3ur_)+mH@Ch+9_0yIS|2IK+Q5xI8uZr&i+nwWZh!x0rsq-^^iHtPzgMSb+`F<6{ zio?wWG!p^`#7sUe$EA8UI3q5h8iX2Tn#QlrW!ylF#!zBz8D^m5bfG#j2f3HH6nKER z0(h9X5_pU_8_ewov>RudO_xv;JXd@Lc#*g+c!ikhx>{Ta-XLxa-YjOm*(PR%woBX= zyieQ}d>0R7VJP}Q;3YKV{@_Q%8~{5m9s+(!JPiDTn6=v(@fa}gouNC-D|Xj8crw^- zE{_24WA~hk;h6styUQUkdfBipSxIMimqQ&%n%G?qW*Xbw<zOVCQ%>d~I#-aH!1&d_ zjCr#*)#*O_`DEsso@6fFLSUT!6u?aWp<+5ZS_~~`qPRSGwm2KSP|WhZT+F0gC$0nD zBCZGKX<PKGJ~+-RXecy<uvg49<8E;t=)k}|B4(~WE@nXO#&MWoMPxUQ1DNT~$V?X4 zZXAbtF4%4y2QxtLCCtQa<?}rSWL-wfFJjb7_8xDlGgetqm8^WKbQ$M}QPU<if}<*= z`TA04Y&8~VgWHN3TODmx3JbZ$t&&u__}*%fc*IxO*VHSBaHYcXf=F*{Kzk7nUv#jk z+z_hU&5VW+3x}D<DIPbWLWqG8W>jGWixWne`|!kqhTou!6$d>V;c>z2=3}<`l8+}% z%f@(oVy<f(S?C)u%A_=b%?{(tpeB*4d;{j0mmp(*V5K6M`q9iNiqt`0e@9WII`$$y zRurk3{0K^01M?|WJ~yGJQ2DJ*$yi&DrjclJBNVkU#vKtVZ5A|*M0`DVn6*tKx$e#8 zUYHKOvjeS0q--a|0fyx^q-L4l=t^F1^sVeBJ7094>D4S!t7P1?iCNJsl9^OkzsSz8 z)-OKMEV8pqoExRxo%nOnMZ*@ZmHd3nuz$|5E<@sAhV>gn{eQ+)IopBpyW9BiCBKMd z$GGZq$$X@;PQ|$DV7Q6_ReodawCZtWkUw|Vl}$qFE!kcN6DfW+3j;ph(4$Ru`{{3D z#&s?HPD+gWwWe38ix|KY_>&Zv!oPn11ey-`xiSv>p%~PLzd|RCyF&bh$AGZmr_l6$ zVEQKZ9<bq#hA<d-4lm-{hJdFuItUf--}vKCDWXfEk?`FKJ%m4Qh+`(c5Wk;EA@(=? zp^LDY9O5GBln@WkN)1)QI|M?LU@{o`61K3J&7a!neL9tl&^w_I5Kr+?fIapVp&F^? zV&6#F_(g<map)iTyD0Pr>@E!PAik?YYvAUB5Kq;aA9@-gnHS<kL32ZO@pn#$<DuBP z$M0e4sOR8#*dG{L4uJ{rviY~2&||RploR4s@Pg11sO5x4!zSK>i-Q8Qze2EJXG^>j zEp>s`%H+_m@Y4-_08=NN(7&O9$p~LX_z}3P8l+%zgfAL+<Z*D?Y*+~#B|2%75t=|^ zcVHUZ34v!AnSluJxePo{PD}G><}_QNUfL446L^&zibv*7oa6-FrVvj1fR@jbBgh(k z>E|1Wtw7*IP8KEn{P;3IKQl1u$BP6D3*lzydb|KObmI-(P#d5x#A5`KLM@=;4-G(M zB!><mGEzd<LN_&ZJr5TNgw7x`f}t3E!hkAIO9&RxKaZ<Z{b{>6I1oC7pgEx-FykU< zqZkus;9G|@zdH-h7~>-?)umY{#%(oeo}0>?5^IR0NDEmZkbz;>w6J9_#%_0dTDG+x zjpZbn-}^^08#RY(X^q{l@W_g>Pm`9|SC}2+0g7oI-9m&aC&m%#G;J%4eQ3H5h?K9z zeqGu?w*wx9v8UmA+F+NF*(}BwPaA55=CPG#6HI6EAf&X3R;_icCq0_)ron0($M=Id zF(8tIF~yGtL<)T!Q%%-DR9jz|HUlFo-M;3;z({`XN;r8S{hNaf2j?QwzvJsVX%!Gf z3HGP;@|m)OBK1Oyob(^KNY_jI!}J{#sa~F=Dd|5PgpCSm9PUd0iJX<T#9TKhl38mo z0+(La2Ciz1OUKj8S)p3S{26nd^h}pUJ0~{Dyf`S5+qfDHRJLmMV?&Wr>DY=41BDqg z=FM}`YrAy2ag6h6>3P;zQLK^Q)E*qEALsJo^aj@PPO%Bd9O;Et=p5TkokrGpm)KB- zvB>3_Sv_K}z`69MR_GN=rhhH0u|6>_I8JYEg#ob+bghjQhQxaOM;H;~C`)=f>cpKf zvBr#^_SU%xF>ZHB?_h;Vu^QCrWQ8d)?gUQnV&7$2jLoF<9#)thdy~HQw#H`0PEx0z z+a3PRj{Tdd(ccR5V-u+}#AN|m6yp&!>BHSPTQSRGr|7~MmkqI%F|H#`ALlY@SI3q! z2oqf1y?1SlXH}(7a(xgs#XP>z6t^aX&9MjZH+_zM*PCLz=`DSp6}HEgF>&TwVONav zOX-Vj1n-G;g$KFmORTgv#@=lDGArzh4PlOoTVcQB%S$uA4v7r*bxJk^heoRVs-~GG zLnBq1<j~W#TsWTMXA3O&2&`qN|C6WJBr@g2%QB^9n<-BZEy<Mc^Yxi2(}zW>H?W!V z{euVyG9};PV^#rKj;}j|{Sq~TJiH|8{l@4`n{7r9i&PuM(&eSuz^29OP>8vYL*GNN zIMf^DiA<$KMO2H-n>*eKHKkLiBH($b8QGV{j&`Uyv$a2s^CzJe<UraC^Uq<Ca@p+d zgj&;RH0>nZ3AG_-u$qLFxz3aw9;t;x3|bG5)QfW}-tCjhvY*B9xcyS;ch;@&!|k6s z1h0_Q4{zoUNTn-qq(78WxpF?mPj4%6FvPvcoZ_B_R%M=u=3e9%rt(>Y#Jxy+m77~r z7TE`J-=o<ov&|R7BWVp|@X>vbVW_;D_&zZk+ju{uvsHO`ococy=c7`ips76~Qr}lS z*$f{MsaT%tYTcGLgcV!TQ}H=-!-z;(_msI~M5HjbfML9qZnF-n(LTj|J|a@bH!5H< zM@DXR_nUi0M#?u}jJg$4`EDMHa9!(m1?zSb%GUja%mK){=gjvbBUNJDu;gZ0V^2|e ziK#IvQpHy%skqaq$Vk^cV-AdtTo2h4j){zS-!j|BMCMhoZ@$*%hqn+zMI5DeueIgQ z$uCMXSB#BRjtyX(thXie--wF*J!a_GNR^BVjM9y^T(iTPkN4OxHc~NW<M#%u&OT)R z0dsh4q*iPbUD;)o+4pJsqxpJlq<O|Mx^mtsvm=n-HN~_T7s;(U2>I9@>|=C~fzABy zC=apnBFbxuuNfDq>$>aBgX1H$-G7>M<0CB@mlY;ND!1jdEw21#T(3o6BL6%3($2~U zDd$qZeG*+iOPPZeZU-xW47t^hX7Pl`Zue1BZXz6CV%knjIKFaXWU;S%(EKtn(#VJS zDVP*#iT3yGNs-5W%~MSM$&qF5v*zB(ksAG2O5CG19q&Vrp{`BWg#0pPeu>=2QaPY_ zi88-NlC#jft;-VbK5i4V3*`y{lQSieUHVRmOoca(PKk7`XtT%1wg5RrS0d%z65$n7 zX=<dqd#{-~73J-Wxp8WwdL>(~{+`To)vg*pIquuZj0Fs<jYu|UrbdRix0^cCA{Akw z^R&oJcSZ5xX|T?>yKrS>m#<BdSus6Q4>OPVPDg%1gtwd#>E=!{*UpHvXZCt=Mx<V~ znS8nK0mgsDvWQ=PY}_6JX6mMpi(swN%t-MFuDc7@xv4UmJ0O<n3E&PPB!}0@<!87< z1o7x~wv}?nG#CnQy$S}OhOyFYNjaUGp|KRGX7liQs<O;FodzYD`m-WDU!~iuNOLUg zSUW3HC6D8dX?Z@jeWq1`*;`@M>DUUf5p7FFo}g6vabz{8<974PEWG%1^Yg4ofxFGr zosIs|PP2S=Bqx(Akpku1$=UL*w2i{9CyO7R9T}IEIv#y%pL5rL!@9sL%{>Rwsuh2B zU1V(Zug(V+cfU3AT%dT=oskU-<6QDqG8Z_XiG>*FkJC{l^MBjPh#LONu=t^5@HdJ% z8{;1Q?PtN^Py&7(Sg6=J#_wJ-dujOfVa{eR9zQ$TSF)#e1*-(~kNM+SWF>oQ?JcOt zCj8k;1j{8@7Xeyf5&}@Nr}j=VhX(LFju+$XKsJ~aA-N{_1#xZg88@EL$cMnm6dK~N z5+_s0&A}gtTZ6gsmg?=mm&6^xcKsgIJA--R3C(b9+=mz?PXODseBjC8u+*o*f2XvB zE5Q}S^TFBTtHHVA4d6WSW^jS{CUB9MJ&aaj^uV1C;=92mn}r_-_kntxp?e#`AQ}1) z%!5m){t0-TnB(MA#B8A01%EKZG4nXpk^byJuMy{fH;NhUTf})_BgQCE+}SOmJ~Z}= zi@*oPEx`ASTY>)}?g)NV+y#6>+z0%$m;-w+ikTd*il>3!vW)m&3gMs9VDx?{-UR+! zd?T0(X84vY;_PXX{|^35d>EXBl0x-|!9np+a76qPxQzI9aK*TUHz8CNp99wvzYDG_ z{s7!i{2923_!77q8N~~w)9E8dI1;;#q0SOJLh3AycGoe~<4m(D(qPH4+m4}889ZO= z*<dyp=|MFx`%z@3@mlc};7wwt@n$gx;`ftLf3Sq#Ev^cFfI}<Ps14z;Gz!3viJA6K zi#vf|6n6!`D(($_OWYUyPcci-hhlyxJ{K<r|4Y0Q{yYDca5Xf36R!a$AubuXTfjU& zhrA0M5+49(lM%PsU>=1*E(G&r6LL#%fw&F0NIU@Cn#}87nKL^|V+5EjcUm3`?kk=E z9xR>&9x0v<9xt8+o+@4dW+$KStO8#pz81Vvd=ognR>C$2JoA7Sc7p9xGWb?7FKnRt zUhp3ALGT^od%%Aa-v>S<egJ$#d<4wzDcyM-d@8|l=LHDQOXCgjE8@4nTy{naED`UD zSt;4A$x#0s{JGSB2HTy<P|t9YtWqxzwmXxd&SRqesI=%NC-Tzmo>~Yw5Ln|;gR27U zR5F;W0<xu!by1v3wq^>zb|x8ST7V0r&Plx@aW^oJ$Dx~?;NutvnG<~7#8WtvXQ!B< zF#|kE8e9!JLTtbsucGBW;F;os;Q3;%VrQq4W)6W@ijRQTijRXgiJt`D2#(Xjc?cXi zAb$xyApRPBxA+_I1LB{-_MCE<=W2C(PC57wusx?7oQzuW8JSN7+nvc!PXnKoy5~dr zds{*b8W+U;B7P)h2ku|uO5k6`{5qzf0m4An1bgDzV6N?_I=_^e;sM~w;xS;J*OC!J z`R5nTPBFv61aN^2%?39Wv&Yt2%&%QX@zvn&Vt)DhiPwR-(vX4R`59BmXq>QSWG|B3 z0KC9XA46cJu~ZtY^;U`7g4c=pmAg*d9lTY{T5pGVDEKxp>yq2Wqrvxx$AKRd$0tIt z)6EFP6fj3&89II<pAfT>dA7s?_+{~Gu$_8_`Ay(+QokO|L1MbI75uUIZ{RP*Pk_JW z-V7Rg2EtF$cpm(R_(d?ss%Yj6I9>c2I40(ovz+)mxRUriaCI@ueQhzzeZIIc+kcHD zu<SM$cL%o>_XKwq_W}15_XFGQ&IsH<FbDA%&_!T7Z4JH-Y^SZkH-PQ5HTXubowklc zxDA4xw+8PAb3B?3-40$Yz8kzz`~Y~1n9X-1ehh4<tzq{V_&%zmN$w#g9uk)YKO!y< zjvtp$5rRF;92WTPe?jWm;4|VH;5WrJ!S9OsjpsNxJ?jMK+Guh=u${sN4*~O>GOCXR zbDbeLo@g2;1e*cvyfqBXfT7Y-p9SWKD=p6lXN&nQXAhq0tH60;X3PTdW^j>s510e% zG`|nrn`i29qLfiIkQ!h%kGLF{TpB!9oCUs8%ov&@t_tSbV47zPEf=#zbd9(@c)gg# z?*{Qi`0v~-;Y#pM@jUQe@ggvnX48YK!AHmlB?JAq7_*nolVYav^I`_nPFuq~19x8P zb-<s3<8-Jlgzu!05B^2m0PI6Mk7igw1;ow3VR0KUS8>x!M=(b($X&qM;$GlfabIwr zcmVu&3M34IMv<7cSS#^8;11$@!5r142ls>R;pZ6$7<eqz!6EQuF(S;FA<hKP7qg+u zh1D4ui2q6uu9ikM@Op6$c&nH(v_s4ox=q{=e7m>__<nIy@WbME;A3LehNr|kz|Y4e z?1J!$_;xVokoY!tgU^fa1HUhR5d5k5F!*cn5wM-+hTTWOcA6W^Cf6S_a{_FqxshqO zFwn_Ng93zfaAh&-5T~}7(P-znVFv#a^W1>);1)7d9o$aLywXL?Sm`BZYnWq*^ou28 zSQ_hp2&^<XxJT{@o+R!Ao-XbWo+};>zDhg>yq=7*%7ES=X3oD^oDJS7&IRuk*Ma{I zNB(IUxzV{-%*^<pnC10Ja+yStdrpk7I-I(sI*Z)vVrH~=#ChQN#Pz_Rh?zgWBFAC5 z6@>4k(Hs1;m_>zYLJx)l{o=9Ua%A{A2FzJp@?>yz@icI4@pLc_MYm>Vf*XnFgX7I5 zEP>Egyd2zFyb|0~yaqf#ya7B+d_8!Kcq@3an3;Np_zv(w@j)=>Xb|YQUGsE}G?=T` ziyr~sAU+DdS<KwKNBlkbPVq0`d&S8vy5?dIRy-_D10NHIz^Bq#|0C+SU*macu*2|* znEiq`#OxQG7qegRu{aO>m6&~m@5O~+*3opoDVT>ml3RgGi#xIXUs(c2@oR`jg6oJU zfeXYO*tLhK!=dfqR#LwM+(FDXfjv+iW=?_af$HGr!S+CP@GIaEFdt`#UV|`Bmfr+V z5x)(dDP|vGzW4%oiI|H8R*F-6=xm75ws$s(Bj6jwWx(6T71{p3RYGNG91yc@f47(; zU-krc1hf|Tu+-~-kBS?BPl}s>pA~b2>t*pI@M~fYWSz5&^yjGOMQJPse=O#>{FmZu zz~73m2md7I=FmUHAAytc^<j*D0!|ly1&)b1hEz^mISECV{eN2E*iUtFb+A3L9qPH@ ze5vPw8;Mtdn~PV0?TPI$zX9A`>Ku;gE9P*FJ-r=fxR`&U)Z@26m?hyWFwYKUfG&Yc z0{1O=jnsMi^G5OS;2XsOd`NbP)4_Yh94)z1To!ytoC!V}V*L-#DnNKb8XW!LX{1!= z+|Oz8Q1I*GiQsp{)4=xhc9@?H{#5Fm!~I%(8~A(iec)fj4{%{DN3iMH!_WwbPl7!$ z*SS|AmrD$<)exhW#_8<|b$$yPh*|$P67wU}g$zYDQhJH`p&CHu_!~aY&M;}PWim=! z4Lpa8?=13|vrtUWmWvT?=Nd6RUN5c(zCm0ce6zR(c&E4xIDVUib`TDc5rQo65ph-U z<Ki6flj1z^b7HoLPKyh`uZx?5FN)iOzYq@t|BztZ)CGYX?&<LaV49d;v#59*xU6_5 zI7_@6Tupo%xR&@ea6R!?;6ia}R94Nz<-lzsof96j&hI3RD&QVs?iT4Mt`8m}X5BtY z%({JC@o!C{-AnsQUv0Yei1u<Pm>oT$Ja*_)J{Fm#J@MFN*7I@Hyv4^QQ@a-)XU$?h zmYHYq@MT_SD)ff^U(M9sP#s|&<^w0@_pxS%^0CJp<m0sY2@hY+Hq)&yY}{pb^o8n= z=2JetFirbK7vk)q2m3)fYux^LY&L!SN9*9s?dAQWJl=k9|7gwR_r_uX(Y#2Nj^<xf z89Wo87`s8b{(xxIy}`5{5Uq*zh*R<KRheaO91zXL8pDUF`klFmNAdv_quGg5^Rdov zV6^t1>-o0+mwnK2W<j?m{$wKJ`12tvIPTe6_={C|cR>}4_!i^wpGACJz=lP9@6(7c z`BqAQZjOGz+DrZ+VVxg8xPm4VE&L0Q|8;Zp_OP|=|HB&aWh8b-r~FUsj=o`Vw1K(0 zL7<$;9uocHug==>0HXZj=0l?=lK#&dqaU{$qkl_mjE<n<x@==~m&C?sUcs1o`Nrr2 zqoS8>jDCDnw0u&d!a_63xVi2##qQ|n9~IK0F{BVb=MN{D^d-@(_yg!mAeAyvk^Lu? zSdAmnm+;|BX4U2EgIX`C0&5^77*7|&s!O&_u<DZIZb&J%$L*@iXewkkkc04DzR~)A z6f<qKZUNsC8?EC$c8avq`WDpY+Fs37kbiEk?!hny{2##Az!`YvPigowJPS^OdP?DA zKm?EnjHNWa2uvG^h8s3r(+t*Ga)*-dO9UoRPy;I1_gpv=u6sO{-5KhQ#Y?!}NU+a) z0pUvWc-@TOdjv6+?5#$iQ@r!gP4y}v9s(ZcJ%Zjk1T_tAr8Q!E%9{bv@wg;C?(tHP z6`nCGmPX6Pc|+7<kDa|m9*;y^=<(W}t2~a#E%3M;bG~;3e$4ZZ!SA`=6#SjzJqm}g z#PV6ZN7|@o;B>k_eJICOy^mq`ZO8i@7N2swJqTlgHymm?-eK6pJFs1mKKl~{3U;={ z+tAVuXst~4xE;gwcx1{6$KzftF0s500ZhLu3&sLN5Fyd@M~;AlPs2+3QKA#9h|r`T zTLtt7dm%{a&l~~=LR?~*{yaG?I2UfGpS~091vx^T{wg^X4{?cQ`r8!3K^L!{exA%F zmfhhvZV_Qz&*3>8-UU`4-Xi$sdY{55u3V@N!SC(jbq^kw4LjaH@P1qc`74wn9Odia z`CYb6q71T^>e4LsXCr<+&#lJ}gg^QRobf_-7rxzn?j?5Qdr^)Zd)W#5(N@W(&GKkw zV~+89ja^QnWJNhC;I()8_Sw-9^rEB7#g{qJ3J8hU)!hP}yl8sVTo@S0tUVAR@&>x^ z!9-#7He?lVu*(;27G<n>L#@y}S}JT_hF4iF5&PamtJpd^4d%T0?p?6k#_>%vNh_i` zz8dMK_KIjjRQ)3<b_tnlRz%~uJm=9LYQ$*_TMR;tRSXUz@S&F67#{FPO|5veS-1PB z)Su~;5?l?9kln%_2v(x{aE2}z<cMKtq)p3^T_rY}PJ6+t@sgo2<S3Ten!m-P)mw5r zJUlNQe*?i~$cW)3wC4rK;B~{x7~|1kAzmW9f?OJj6@%H-25`jpvhh|%8|8A60vqkQ zDkO*ld9l%+Mx7w95K6E=*x7F;uZ-4<GhHKtJHd%W)+*V7&lM;oJMh`LDcOPlHXMzN zxd`VngY)U$c)ns*a5A!2WFomzkUi(fOdbJ{9ZaK{*{h(Q;{;B@P+_$F?{FiuXzBzf z+9_ZoHkj)-S*xP;2HlM!7wyLv4g{}&&8UsowBTZdGCCj;5zkS5AUPaNLJCI*k)y%Q z@HIM^oDnRAh>H#(^UMIVXH~RptHlUUbT~tv9c)P(Bgi>HUZoNp#c<RLUP*hS$$7!$ zi16qba($=VZu8x$X!Xzsh>2KxzNIg?#N=EZtsZC2i*=?~X~FiWD`H&|X&a!?t~PCh zT-y}uMlKyZhhWCKlQV-$U@O*xgOFLlv51>k&vW3sU@MyM^*MNYkRw5{-VDYU!8wSA z*f5SeUUJGX6z2lwsjH*y;%%YicrW3v>+wuspLYiol00@V{N6rTOZJw+gA^|c?^C@` zp@M@fpc3>xLy=DNUVxYBo)0hJVTBR2{TYP|5F6fFB$n%h*>~_~wEBQb*CJ1q_d3D$ z6OLC6;fp`%c>SPr%JF!Q>S@R0g>t_*9)q>s^(sSeuj}0cai8n8gNKhMc_-l4D@ooJ zuy8Ky@nt`)?cD^$zn?<VehVvpcU^0^?r|c_@g9JauE(3Ed|pSSO_J9U>V9uq(5Z#j zTMu_quvU|=*VevX1*AaG<38Rr?{2u0<}EYzR!7T~=V+08YckWUJfjr63i{>8no+Bx zmE%9cS@&+M?LJ0zYd)cnFn@Q#Jm*VckO|>rqL+@-(-OA0xHn-dp^&ikbix*^RTyMV zTA?B*uHEO7YrusHS*-GL{^c*LqtPfQ0o>D81A3J{Hx<`JtF>YQaz9P(gg2{bL;ksS zv*LaP)BVDFUNOpme3{^v=*m|KZswV#YogiJ^6ADm$sA6rIEXRvZE_E|SB2wgu9s3J zHE14#Uwt^S<5o(!ljhz;th<#{tetzPUL}RGSD~Vff~6_Uo)zDtW6Pw${-(Ru3f5pj zs>xp)tx?{-{a_#8zP$B)u#di1JY{CAjaKz_i<r%8qnWsf>)_gGVO9ISH`w=e`{ld@ zgYFH9_=clSjq(xmJ4{!#33SN5W?iV~*r+*Vqh=!H>c5#L>!P(1#vZlC*8XYiQETkY zgt3({7PCPdlFA_dL}RDS!|S3|d``M~dtEfEYIByd;i>$3Gbh(%kJ}xQ%C{H;x#D6| z?%L?ZqV>#0_i;bH-A3&0vJD9v()&^wd0gz02<d&P%zk|-HxHQl>!aCqcvy#fE{V;b z`Y_8rfV-<1YR4QKx^qbk-B#GBdCDwZAI-ukgWK0fE7h}syO_klRf5+A*1z|X=$~&( zn}(C{yb=F@N3KV}i{D=#?cw@Hq?!gBqcd@_$exYSG6mL$vVQuo3olWV(+X~;pJ~jg z>Y6rD%KMoKxr?QsMX>nejnR2-BI3TW7I}aVf_CL~(JBbq#_OV$GHlR(^fPGF;39%% z9=R@B!G~bHeqHpu8@K+>v`vh8$Vv%+X1nx<gN`*hx9-lt;#brZlvgq%&UN{2sW6i} z)p6(9k9{pjHLZ8^U3xbfav~-cSksJ&Ww6D5ZVbZ#i6ks8*c{DG8pa`iw+t4_VmKj@ zTg%uWRkW{N&IZS+x(Uv@JzV$EKTY+prV@F&hnvXLENQ(GHmVf_&7rN)b`999b}yv( z5R-4BvdhV&p$oR4`~<nCjfMA882c5NN~cVXo1#_nFR-5a(3VDi4EeGjS&55fYub|Z zaSDBX3v!!>i|5@G9p$Tem{D}Z$4r=u|L(4Ol}fVE5nBeAW3&bt{Ksw4I`KPT+kMFz zu4)aB`qS`B*6^1wT#v&ii|XJ{hbx)G3zPD|k6QDuVjL%tKMQUCEDy5<Hrg5|u`!ag z<$-u2U7FY&+L8J;hZZ4+ntdi(in*cKL}PBv)qLSGNytYkKUq~uTpwdyk0R<3J6~^) zR;%*}BXPB#S%bmJ#?#$Z8E=sY&T5+{rz9-2*kSYJh#e()a)Zs24Kc97Jh^d4B2V7A zBRbv9;@FLQGWAY4${z=+++E`n4x9X)(Q*Ur`<+T<F8#D3&7}CJLO+#F=nfw+{_~RS zQ{9FsTD>GpdG-sCjzOeEMz3dUxh9Yc&|=xSGg={0n0q8M3wNWsjjEou{_<_<&~PIh zoreGWtHBKx=AF@MZk^YWiQJEUj0)Is4$|jc=l}HfW1Es?kg|xo`n#j|CyHH5tDMN= zt$lnMCv!93{iuypcR@}`X*g=*GGX#@TM1OO1@o9SSkV^B<9-&(EacG>enwqITNqE; zc&=#Q;t6Y_LdBu}hVbNhKXWdIcjq(k)qL*GKfSAVS-^4<0qgvt*>Y>NOa)s~9<ar3 zIo_ve5M1D)Z#7R9AHOv^*4J+`UHjH``_(K7{I{1C<?j;(v%?QGb=GCRz61Z=U75Au zhIRaPYy1K-UfV_1VKZ-U^cMFw6W$js?`xiFYVV6S=5y@6X#H|r_v7xr7q%0Nvr{(# zyMAl#+81q;$wqpqI{w-vnkjyc<aB>?+x}>EUz?Dru|L|Z)f*_N?%rX48tPdGVZ(XI z%mF*0T8h2YQjFVDZ9q;hUTaz=eHXBI^^n=UKg!#oUfLfmi~X!0?vK{3{#XzWRI{~W z!z*BoE;+q+!Jo)NHv0Sc1E$e|Xp2f*0TWqiXol*g*m^Iu3WlA&wUf>D2clK7TOcrH ztJZ+hi!{crnbT(^UOI9$bK4K*>;2KJGEToe$n=rLsi-5YQ%=87!2Et7TDu%4yrL_+ zP=mRm)CdH_>3OlZ6)tV69axM(TAy>+XWSzhm7D(GU#;~2*7;QFr=u$~|LUMt@y1W0 z)x6>#zKb3!hf%E-A4e+{zv{&X-W-1d=~=Qa{R=YUo<BA&O4g+hA|vYgo6a1Da?Kyt z7M83(zr?(Y*<Jp4=7%i~;Bj!TWT`m!q?TN{R15hEw=7{m6Tc_YAY=pZ`<+}Z!7sy8 zHz&b2vXn9J;P*5+H^IM>YbN-1R{1Cu{Cz`4mglc#1{hh6zv*P;ApWi_1^-=E`1pAU zz01}gep@lF>DEhdCuA!(Kf&Y4wlc;_JH!^(GV*u!GJac(NJ!kE1T%P9=L4xT@=De< z+xIV7*bMbQ7d9gjoK!?R7dbOlE0Ezz0GxdpbKZ*Tc-cR1N8-E%_Z3l{<FiHL>flyl zMqUT7z3YiFR<f|U2;57C+JVQCkqivPWN}sS3~_DnJaGf?VsRnZF1m)@j$lrh(VZ^f zE#mGllDI+%8hxR$TN*>bC5xFSf)7f4D)@f!mEeDf*$sYF%p7$>d^NaaUGueId-@gp zx*eQY%M8<ZLnv9yd>CA^nE5F9YdLfh{ImER*pHmgw>b|^6Mq4YiN6MO=8a~41XmGr z%(I60H*g-;h0qW`?hVC0a5FK-UD}8P;7($8Q+tZJYi)oy0v;yL0FM!~r8+^(ReB4_ z$cc7c%5n+FYtA)dd>5ScVw5oF1~D_#&0@6XoSkAcjhx%XY&P64W=7+TA3bAUc}(0C ze7fYWCzhz!sex?V2>gz?37BJbRBsLbMBEn4UC>l-59VGqGBelD;%;CEMUU!zfGOfJ zV2;00eG<zbhi@p%hK5~_3|<JXBK5^!j<(RuQgB`I3UHx#C73%NX=WX`op=Mdi}*Tl zFY#vZKyn-wwn7*#jUC`|;(g%hVt%qYB2Ewf0lr%N7}%~ghWgWBt~I8a7r@)aFN1Ft zzXd)Zz66fjb;q#4Tx!=HgI#2hM`b7l{FIoP>$Er*Y?l<nd?EM)sW%3HBIb<UFJx36 z*>K-Ql}N4uPEBweLoY}VX|Mt*C2kBZFK!F2B4&Em5O)IGCB<;GE7+b|1!i5+L}o^S zTZ*TEIh4jgEC6@42S!0y4xzU+SZVYZuLe&dqj8rFo-Srio-3{cUL@uxV}-arc(oX9 zRA+;jHSA__OV(D~B=iCA5)T6J6AuC3B_0XpfH4C!4s35q0xtsFo07oHq{n4u75FLf zS};fHXm=C%3^-0<3j}WYC*K8rS9}ln1M!34&%~@HzZbKX<d7Zho&x(&iIABY17c>z zu=o|QJ>?2!-emn>K^m-9v&9#|x#Ca2dE&3Y1>*0(MdF{pt;DQWJBa@PcM~%s_Yre$ za*$=je|ZSQq)`hzgN(i$>Jew2m^I*HF>AoM7%$<h5od$#(qY)G2DVFw!8O5l=`fi2 zW4Fw+qT65M5No=F(r5~{$6vuhcd$MF3fv3)sLTul9}_cA*rmg$cZ<Mw=`gq@*e)Fg zw+6E>$y<=xg6+~_aGb@-t{sNZ5&VM;bq3qxub@tkeSw7K0bqOl71SqyBT}CXE+d`; zt|(pvt}0#vt|eXuu4fO7f<vq(d4LT=cLSKcJ@SoUj!ctp0he5}v<uu*>Z~Pse<#h{ z4jv}H3p`eQKX{6mHR(+8KUn`SkZ=SVOT{mNuNJ=n-X#7AY{dND?-MgK{!RQl_>edW z`N=LLM&OtM?J{C8*TLCk#Jp>f-{$9JfvY7>iz|U&7qg1B$6vvG8}NHlZwLNF%*FKI ziu-_n7Y_&9CB?8i4a{~SV~ah~c$S1E5bQc)Xe<Xeq&h|`I^b=Ziu;0Fi~EB+idk88 z7Y_mV6%Pjw7Ec0?6!YskKEZKkF$50h(X(Y>dlVLUE%+*_^V7+xESh2dxJJAMyg|GZ zyhVH~*ogOncZ&~z4~Xvs-_1i_=qNJ?r`pL6f)9&}!AHf9fS(XQ27XTbB-kz~hTW&Y zc1bb#SukhM>E`ob&U}!Ww>}ep0{@*$621oWcnTW&7x*{vw_tx-LY=i+y7&(;&l8|| zwi)g6Vldl`c6l*43tU5HYJl^_%umh0aa!hgx}!AOf_saZp$3YXp*UMk^ZmhN#UsI! z#pA&<#FN1D#M8lx#p}Rv@n#+vyGFteXlxd9;fY;G4A1Ta-!ApX!S{$?2HT~>Fmo2n zTg4f;x4@5z&w*beXQO+E*g7kYfZw*v^oMXk8kyja#MQxHh}mNKM$GT}58?uFFdc57 z!l!yf%(}gdxCmTP+yY!x+zMPXE}<O+p5H`=SmYXtyMmjF**<739tiFzX8qq?JOSKS zJQX}xJQvJ$7j&PcY`i$W3&K<hd%?5BED;ODED=k^4}n*SSt8bnp8;Pdei6J?{0?}B z_yh25;!nZ1rz8CtBIfpcr13lWK{0zg#bT}_eoR~j{Dhdx$etE+x$xWMoJ3#X!e#uC zxI5hcLfn`2|2Gm?qx~pmjrO~kHJTr}hmMW~+x5lZ@!+V`CxR=A`6a9-o(AS*0`1NQ z*AugeR!ELRV>JYxsX#+pz#YYV!M(+-t?Zg&n7JD~QtJ1D$BWs5nkxPTJWI^_V}ba4 z@KW)Q;P}-Neui+Z*g-U2FZP3P7ITUBPH_;tSIp+ronn63?iH5;|6R;;ULO{-#dR#f zaa%*3k_Kz2=fyR_uZWqhZ;0!G&x;#@-xoIrb6E;wu|4=}aaZv7;(p*?#0SAH_a)K- zM}1R62|fZ2iCN)rh?HiIgUgFgfvbqQ+`ESO4R9SXhcp|AKL9roe*tbO{ukG!x0mp5 za944X4{0wBf(ME@H*41yBS2-rW2IglJXy@u+g$O)Ky$_RJaJR7U3LuhHefD0j?+*V z2zK2uxF^`II|dH~Z;|C;;O%0bTX36rBKUUkWbi%Wso)32T=`urUJiatd=1y7+x5us zY%etIdSo!qA$VDa4ufA4bAa-k_-pV*@%P}5#hf<zQp_U&z7=x>jdTBe;cDPNEF=9J zK}ZfKG+Kbu#jU|H@lbF%@n|sDn$aO%=TlwG9sRY%i@=;Fr<s*tyG|L*UHr|Zz8>6` z`x0r07mRlnUk~mn<{I+;;%(re;vL{IVvd?|^$gv)4Ln2q5O|*W7<jSxB)G)i_>&OU zNaHE+M)9-YE#jBK+r_VeZxvqv9}vF}zFW)@v<JkWfDem#G{8~ukKmJG*8d1Khtr;s zh6g?)<`CLD;)>vp#I?bf#C5>`7W2^f-^7i<N%+vy{kCAc-Wl8nTt@1{xh}nugi+9_ zE}jIgE#_ALeDRgwM&cRZ=Hgl4w&FS9&f@vto?<SP?=M~f9!h5YzY@Y2Y3u=W)`_9! zO0yZ_hrsj1N5G54kAhc<Pk`5op8{_XzYN|@Mk@yB>=)zV#1Bd+1A$9GX{a3dAL2^j zN5xgZ$HY~^XUMq;M>!Qu#z)h6SBw(od?3cd`Ap0f*QEr<?O`V0Nh1pysZlsoGcgSt z5;uo>DRE11d2t(X6>)cP4KY98T!KV*#)2D&*$OHWF95fSvi^r5Je&^FV8^4I_*!sZ z@doe^@lD{-VgsHiW+(MZF<Vw#M?&{+11}Wc4qh(4haO)e;Xd$sF`HRi#cW#b5T6F` z7QYUDfLtpvFTf?HWG2B;F_Yk=m`U)AI0k+R9H)gG2xp~H8~nC7AIxO~G{cteN8%>n z&%{iQ-^j3-2Tp>^<OblNxFI+qZUinPhC6Ymq6Ch5R24J5Yl=I7>x#R98;Xa6xt@id zjRLn3PXTul&jR-l&jI%r&jSy$jQC#;VXQP(f+vfw0nZSx0nZm-3tl3=9=uA-e6Ue` z2Y8$KZ{WRRChI-o$H5Qsz-Yd~6A+5UPk|p3p9Vi6J_~+U{08`C@p<rT;_txc#D9P< ziaDhFv6yoQ--zREul**WA~+R=lL5K{91|CTD~g+etB6~I3&>Z%C;VDo#vR1?8autk zDd3@E)Y8tF4A%d!Tpq#%X|N7hNUoFUQY{xV<6I+V23#+04ZcC#7JRdq`DUk>`DU-U z2l!5LFBbfJCG>&D-^KmF4~qwYkBM2aoD#EN@Vt05_!aS$;5Wnz!RN)yHy?;Mf<Gh2 z@s>A3xFii`q94RNz`u%jgMFnEv9bpo6z>N|#dm|tiJ9ptiSGwj7as!G7C#G)=Sz4Q zLL>1RaC7mS;I{u?d+z~WRk8McuUXkUyJaQ2k^};Tbb4qZ2vQUTktztH(xfOB2ptjF zpn%5?q6{FtsHk9fg9jB96+70Why@h|MFgzac>n*|cPM&}&vQOJ&wG8(_vM1Ue$&^Q zwr1{`dzSD%a7W?qz+HtYaOfq>`qWRDWB!4{6hsUWt_7Yzu7~_*c~40i%mUF>!pIow zZ^8}0HwiZd-zt0xc#&``@N(hPz;_6<9^5P34g8>RPw)n=|Kcu;+V2zMz|Lf=@KEpz z!WH1{!jr*o3nL0^r|`AlkA-gq?-6EE?iXf}eJi|%fqxRiIxyE+c|$BGm+-^jOmcnn za^UL6alY{Bu&*u5iri3`74{TiR@ipJ>^-}H<BW7L486o*IJlqiIPgH>Dd0<lS(C>I zvj?0c%%_YC-w&Q8ya{~0Fgv%o!gztjtp#Fu7Y<8>KLM{6{sMfrFe~5#!u!D+ggKLa zQut@^Gs2W5yeP~`?d!rR;CBoo|2dQWP#m~qx?4C8yib_x0^bOif)5L`H#{QT2JDU{ zi-}^{fN&RZNVo?$Q<ze;>eNeT5%hy0U-)uxZQ=3YhQiap&4g!yTM1KIcAD^g;4_8) z4(=_y6?}p4^WY1G<5W<-SPWl*M+$!j9xtrWiBA{i8AI0yb7FeEF!hj^lF?SPknO9F z<GY2c!Tx^XBJiUz_WuY_0>dV8!0W(zN*E2n+9q5Ienq%3_)Xzv;2pv(!5;~;-G3(B z5xh_MZ15rBbJ+j?D25Sm_)YjSu&YY)X~uy4!W=6Eg*hguB0LA2BRmhBC(IU6BD@;h zMEG9tDdZk_`t>lh7KaDGJ;@k*xxjse{owP3gW!>5WC{I@6Q-X@i3gqu-4aoyiT3Y? z_PMcjw$X>7iBO4L`(dcNTCETBvPYl!Q3xuH59vi8h4^uUy)desy2UPBe$?0EVxPM~ z@7NXUX7_kZ*ZCNpUeZ^54C{K2>lbL8sk1+U=gag6UgqeHylmFKPZ{(Decq?=^Q~SB zBho(1%O-v1ZsT<!E_TUw{l#uX-{lQ`%4hKVj=uIYxc;Kw{Vepgo%@!4;d9t7*V%hQ z6Ych1eajwrZr@UWj4RS<v^P{&P1UuU;5)JvdqY8}WzN_eDt4bT8$%?$Zf_{xPFY|+ zNxKKG?$`p1`;Dq)@Cz8b!nna0%VD%zU8FmI5h}9X3-uUYdt9s+;fmba@&)4j7X9+| z`rvGQ_;#NTeHl7V>GFfZOjq+J$&V=5tJmvScKWI&mVX&455&8oG*nkNTB8T=C6r9% zpUwBn(N8HXO~H`a_H;lw9@Fo;4Q&q^dR$0`ejiVDf>Iv^=TPeV5TT*e$9;TI>bnjJ z7^S{0UYM14I4-HK8?gG(_lHn=d=tZ@bYX&A^pS5Tv|)tFZzu56ZSw5|?jkw*?Su{V z4Gkqk=c95zzMb$rV)66G)pR3%5#?dHx>|7b8Q_s<_;doDq0-0I@HAIyv-s7B)1jaS zAM}LhxN|9fr#b9rraE7Mr#SiWd!^F_zmuJh;PVP+3tT5T)Qg|!a3yJi!;`$mJ9ol$ zoZ~^Lu}&s_$2hz2JKDJcuF%GtiCah=uoY>gxjg+6O!>@p_{A3wc-SYtc);BRjh%ZC zae;F>g5nW)hPS8UCU`@jxt}r6-6*f=Zs$w5C}$u-;)4fu^u0fZYMj~`?w(BpU}yQ? zV@Ub1fggA2*|rMS-gK&9cwQv?{oHKj*^bJFBfuZjbLK`eb&bQJYVoFw!FdtC%HeJx z+sTE`6el0?yBuz8aXSgvq<P(c|zm6R)!Zx9oF{AQV1D&;iflE$1<68Fi7m%Qu?m zY&sip^Oo}{9F;R07Pgf^1q+vN@gX{&j|42I>;i<KlHQN73qFJgY439>AN+;*gg%d= zXDh@Hl=;#Wrw*>rJGS0`IFxxoKREevjqhM+FK*ITq#7V-G{jSEe09|j7_vewa3j7l zMMa;S&=JO3`Kbc5CVT}}y$hFuP*sLGQ_Y55y%0Vu`co*oKVMJ2bJSjVXd2qg<oYV+ z;VGd9ao@gv#?Ug90e9c|>M$;?!Xw9DZutfnm)0TfeD@7AhBhI7mJOf(SPgG&E!(gE z@l&WkDgDb&p{8n{ZuE2L5*5{pe-51yuZjGf9(1}R`Po5d1ujnooeEqYnQl965zX|g zY-bW~;r$zJXCus?%(0zTaQ_t7v55Zwt{i>bGS_xEkXVgtTRh-PxDJB<mvL<h^C!60 zNB;bPYXmtseWh*r*2Ph1sexAa!lP+sfm4|SxcPSwl`E~~Gj#YCKWVLqc=xQr&s)Gu zPIHyzdmnM<r1jya*!+j^Fll}1!}33bw9?Kc+kO}BKdm3L)8(gnYub5aw|}EO7>4ud zDb=5c3{1OV9-{X8pP;AyysLEocHBwY0NRKBvuHn%_E}cOJf!AI8*vd*b~rpz4%e{p zRP7Lx*Exe*U;LeQyI(^&@sDvguJop>==Ullr>u<G46eHKOKZ;KV9VhyLgn!2IoqM4 zXNtr9WG>6cLj$wad9~n@KH5_K8MEadjhj&yvL|x+S)bJq)?lyyC)y9?4X61ju2aKS zVXTe2XN^?D`RGwAYlr^&*H8_7(jxu0&}DczUin)nyOxR4Qs*Mn#qd_hx~D8tscxnD zA^pg2p@t(4Golp5SNJGkF?OuGjA=DYMO;W%smA;Z&2Pb*@+#&s1@lGU;4#EZd3n(c z-eb~zDa<ACXO1u{I-+#fBcWV%r5<@ClpQzE*ww{{3?Qcpvv_k|T{)-#Wi<0pNY%}l zxqq`T0}iUYG4rsJ!W-$oyNeIUex}fiAJxOSzeDqShVNnAQ{bm?Bh5Ws#fT;!=G#)k z8S2n&Rl<AKx${*xrXJE&RJh2-UA9)?T%2JrP=&J_nY-+0^De(&EGA1k+Dx?yillG= ziduEDGXu%}a)s~dwJO}ze%+;iL~PZK_o4O_IICU_Ok_jtztPmY!2sRT4(FD2;eFqs z_?l4%;8JRQ-C_E#QWO3TQ-Y<YBHW>>)6au?t{tvtqc3>U4(GKoL1vh{bfGd8Up#b- zrLM+zCEyk2CTsv|md(mVoe9?aqsF#H1&Q30@IW<~yG+#*m${QYPUW2}F-4TTlO-lQ zOYda$Tw=1?s>e-NYP|`ShWKmazgkRbe4)9k^(Hv?4i%2pAGyL~)M4Groy_Pf-Qgyx zx4zFE&PMh>?+#a2h5B=McuV|#X6u?1-bzzM$Q35F_#23Ll98@SVS$w5F_HzcCWQrZ z6U_C|pw^`D_4XJ{MMmY~&J^YuPc$py`nS5v#Cs{Qi2Ebe+7!N`c$RokKHcw5(Z!x{ zgBp`rWA+)xhY&$o7Vd)W=q%hvQPad&Pq?d6&+08+bNlak!_~v4yfV$*JcryU`pK>R zK0H>1F7buegkwx@1mz@2<%m=3=?{J3GctMXZ?FTENZTAiP9?GJO}dpoTvyf67yH9C zt9$}Kp+T#V{;O#JQG#{)4!y)5&an@s>c9KL#p+i5i9cLWn=3kAbK-q>%<H0DiL%=7 zfTgFF8cZAW`tNYWohS{2cZEHlAZu)E?feblnkS)h(6eD+q~5&RA4t4bBfQ_ISM5yA z)IC14-HC$Q;clrXyZvA1whA;#tZf*st=tz+#1JL%T50&sZt+K1H;}LVD`ttI>hLcI z&#RE5{5wo$?Zh8<C08Cw&$E6i6#;%DXC(b_bXlnsFp`WC=N}IwRVY3F^=7{p<>U*0 z&$GT_3d28+{kW%|={+aR@GlEzg5MD4Y?7Nj=sy?yp>Q5}w{QXYOW_jmLE$>!A1V)} zuLr}g;(+NG#@xwB%fOuCGJ&?>4B_@*9<N3FGr?5cCHDYB%hT|A;KpP;93Q4!n3>dC zIK<~~F9v3SIW!&t^1vK*Gccc^k1(HrYp=BD6I>|F2jEd#w8xy#8Y$ca%(YkAmxJTN zoF;R07^g#980LyYNALpSu3)}|=;vJUYGF=a?iRife82GJV6N5D|0M7x;Z@-0gzo?w zwF&rHi}aIv6ENHh2ctIuz7PD71b7h4^S&7ABVaB7lQ)Cejghy5Ig%y64*pGeC)kC` zOZ(5je&Idfpkd_yAsC|K@GZEQjGCVVHs`^E3&Bmqo>|>OnDv8;#Pr`5+(Gy(@L9s$ zz|_m7AJ&h)!u`Pg<6<};h9Sbt-Vwrsz@vnRgU1V3fX$c15h*1SGsK?t=^Eh~;2VW0 zg_tLN515O`yrDRUEnG3C;UVxEVP-YwNwiOZ9}s>F%mD-K9|u1!{4Drs;pf3zJf@$Q zz+5~gzXImsG5Iy{d*)Dj7~X_ompJSIe=htn_$y(S*+Jniz+5oqM^{m_N&O2jTToE! zv%y?2rXLn%o^UO2iEt77A5LB9iS3?m5;Dt`6LKCZ%>;N-8kudE>h@%IN|ootb4b}= z?Abwa21GyXptyKUt^wv^Fu4GHC7ByAieccej}A=u8sSsGHwyC=J5RVBSPP#HzMGuR zu`!zBar~%oD(p82^I^=F#o-?rZ^d5`2c(_+v^X4?T|2}+7yOZM9{4li0`NZJBJd&M z67cuJb-+IKiaZ0D_8G!0z<ig(K5n)sR}+V}a4>on2yhzM=vjb!gPVw-{@@nEY!PjQ zM}a#CUjaT#_<C?p;hVsHh3A6%n?vc5z^yP05eKfnj1XQ0rhtG?um(I{cpdmk;rqcx z7XyCSBB-=a|J%TGgkJ*B7iOiVPCWe_V0&FDhVQ_43I7USFPwrG)5F3+@MFT<TeVrZ z2H5CmAktj$OJZLHeqERn?01BzqwxVa&b#2^o>ATaQ=I*Uc;ez7mHOz1;_UB*+k<}* zJ_Br{hS5(auveJ-tkQ*tf@8uX!PSH(aPwy^F-(F(u`nl1^@XQ{n+V?uHcA~xY%#bq z?SskJYY$;I%Ra(U@CCv};0uLW8I4W{7ylc;z;j)A(lMHT@-yRLwt`t=UlV-2Fk8V~ z;X<$$W;`o|S;Ng4@Q9}s_yMtR12#v%!=4rVaZdS}a0eKk7UoOhdEs7Qa|S&8@Eu{! zfCmo+n=|0Sd>8Bz|5L!bg|7ntNXC#W3;dgKEwBs2FWSdz!{8S~eK3y(qeCgUiZDB+ z9O3rhJmIe35@9w=bJjb;4gr^m{V;GV;c4L0gr|e?C2|P=5nvV!=2PV0<=}zzgu-hI zHfOqnIbtzqx`R&zn={?P%u;itJGdR#9O({b&v>=O!`wArB8NR+&GW?GEdCm03^*`* zSBV3k!02MY{xY!9#Q={28(j?WRIt&-0AB;%B4Musn@^F$elhrEv0njxLzw-_yJW7F zt%2b~ad;5CTlit{m%@*N4+=j8{z3Rz@UOyefO*ydbM9@hPxxK1(b0hYPO#C@0Dl9H z8zl`Geulw(t{lweuzC_W0B$VI4yRl=25v3PnH@hw#e~`UbQaDB_Ymg3&OXAm!51Vs zZc$itp*S=K8zl`yM6uc!v2P9Lsbfr_EqI!62k=bcj^OKryMpHkvm-K}E=Sn@;KgD; z9K6yTN)Lw$7}kmd*V{OOW@7Ao9u=Mirf7=xbHH1KSAyRpS4qCtcL>)-j(#M}mi3u% zBk(@qCg^{xLt<zS{!y6kextmBNLiC9v||E2!IU+VdxL|*{lHa(F8~{z4*20%GEeN; zXHe&wVJ`wV0GmUJFM*+{I9v`sMVK8+Tj4Qaqu_zSlfiw&ekOR3@HJo_O~M4&3N91A z5j;lt7O>IdfS+5DzBOAM*1~~8DF)^U^;Y5a;6=g@gVzXe2Hz|EJeblshJ6LhwF@$Z zZ4};+-vMtG{tEn}VHDB<7+x0#3cBABc7Z<-W)1&1G3%yqARQ-t&RrblBH1op9@dSP z;Bvp7fr~qcau}rB&GJX|o+aUO2rg<Zh3j%XnwO9C7G9d_(6TVr-umkcmxb|x@d5fl zTvfSN%frju>^(o#E3OGd^oHe#;!}Nad3Yke-8o_f!rrAf^75wkt%PjjbG_nPBsFQD zKd9R4ek;SpskgR5WeMonE5mvAf{teWYxBx*P~ELxgR}eNj<~_(GT18EUZ88Og6(OY z(BSoo_py{Vh}Qe`XjtR!7xJ=QZ=t6wl*;w<8tsV8UmZSniX~1R%}gn6+GO7JuS-;q zME}*{h$~J}I8L^K!~}VJ{GYuErlTugTpYp5*BD%mt$cBghGneXHr>oQB|LwWCa))* z7ni%6xp+8JFe_i2Qyl$>`1L86tsVCfal5)3fs!j=moe_-*Tb`2di2UbmH1D%ODuD7 z#^L3zSS)jWfp~qKK)af*GdFMlOotY)!Qk%;dn|L&50<&s!XYpV%nFjmw}WljvtXGz zU;_-^9!NXrd5qnKj{{QACL&fs$Xq&dp=E!f*R2g_#>XON&vuSJ(|lDBh35^jW6o#v z>>%T;I@-Ta=J|~5U(;Rwrn_*>*bgTQABsoLXK?STo$)NJQ!*&9ab<9Q%bmef98xnb z2YWJJ1bZ{Mb=H^h6Oz8fZw2`PF7IgOcE&RNSQ$nPgs*b)!Giq0o6Ea6o6aqg&T!x| z5@jBtRK(TZ>r$nNIn1Z^dKCRy;V0nDo2EFxb%jGNz3%RCX8+;5fn4J|7#@hQ-Xe7l z?4seX>AkMvc>!7BMl_VE`(Vfk--Z~xvWyfSOqUMoJGc~tKchjucpXl0>st4Ovr4`} z>fUpd8<95+x1*1~ikWvxm>KNtXACXFi}c`o!r3`}cn`yjU7PSU`W~m4OKmN?sh)pN zxB#D`{QEuOrgovN58e~buRe#7y!{w{Q(c?!TZO)3=8^3gy3xJi0d|VgbMHmrvO1|# zlGO=M#jH}NaGNkY`fT=hsuk-O2O)@!y7?YvYUa~)>d%|To52ir)Z#bcn#FSlRDZ^} z1pl+SXIc%U@d+A>Sq}!$_$B^V)y3<=VKrEvvMyYtM(V-qAXLrM@pa*9>OOt@I^<1F z{r<XemuejuO*M+eOnU4<)nXotmp4+kUmtFWC6aOL!_%uhf+tmhqy93Dzb}*iGVTjk zs2zIxec>wkTlm}!xx(p22)us|(r4*0i`r);Hr^L*>-BKbXj`YBycG3<#NrL%Gh8Pt zFim{CDcsKvjHnnmc<9hE0|$@1LT|AH@kILO@Di_Tq;tPWt(tgtTX;Zbya(z^r402h zGV+0c+%%)43tYeqV-ezyXH!%jtg?+6?oZmEhp?0)@^8>_%%KYH;nliKm`RLDa@@jO z%BXVE6Q?k&yySH7OyLmtI$^vH%@BruYJlg9eF2#BD%v*$FBfhEeu#`z`3xI{8UK?; zh6)D^i_A9==!x}#N-^YYFt-?yi@;QnA#;ZDv2YXcUg0t@djR@r0p>O&a%(Wx+Q@Ce z+-}6PQPNmh!(w1!S;9Hs8p3(t0%1O79pNHysW8R@R+(^pa4TWn#A(8ug-}<93G;^d zDvHz44u;<1&=Gu|@R{I2!ac#mg*kY;Ot=qtjPQBjNy3A{(}XVpUn@KwJVzLE*0^=M z7_NiE9l{I1_X;lsKPbE!yg_&^_zB_rz*~hM0KXv2_t;y)e0zT+{1o^L!^r<_FdPtv z7r<P9XRd4qQyYi;71&12Cv(ij6-V+RaJn$x5JnaY`(MG;#GYfZJYf&GM3^&`CPs#e z0NlQEia12UZH2SJX9#l|(p8x9klw;|!RHCr2M-f21#{HE8*K*WScTjMObs7$yeACP z#Lx@O0RSD&0dujHd?A?c3o_*)tH@|eY||V?kl~a(+Xl=g%}$o~0q{m)HshDb@Bk;C zXM;Jk7`SpvW`FX5a5eC!!qvfF2-gH35UvIOUN|4jJwc485NzWP$;Dv4WXN^ERfJ2C ze)8j-aA*vNI^xg?+*G(TxV3N>a3|sJ;IoC#2J<v8CNKzWWT@ba!Iy~r)!+)@>%bGp zad^4`25Q$Z@O<!W;e}xC9-#eN@GZjkf)@z0wl5Xt41*g*=>Ji$k*$K+3XE(O`~>(> z@$)ozuo14pVH*sa#o-0;8)Sd7oVeMgl0Ot?x$YKbSNf%J5PVQL4E`>0#b@DPU8+%H z;+Nrdw(6k^_hS;UK##}8E-BK_?l<#?*w?VVKo7&k4%XI>ejR>Rb<tA~!1jQC`2c1S zn{<bRn5OK*sAI97`vJ!L_a4L?<8ONRK};up(xF4)e0LV65QDI35UyPgg@f)y7OJuy z3@1CShM7?;rge=PkOr8k#8w*nz*u68`(VU34}Lv_Ny9YQw&J8gxB3RQ59_Yqgo~X` zsBqiSEi}Nx)tYy3e>L|F1(1L7sC@T<4v_!oEgyNJ`u%Uhp<|yn_@J<gt4Z_n7G|cg zFVW)LaH%hqAKQD#tw;SD&WUHE)?zv_1(##f3BC$3ohZN?4bzDVTx|A`M-R%cpu5)- z=Edda`vrUIIA%683(D{inqO)>?x6fs*Gk;D*S;Cna$bHBn_=?6eESweBIo6wg?o|n z@~O0X^t^n^elY7e6D`=6hugt<`J8(CDH%y^x)rhGK6yMzYKuL<0NWJK%cmdAI%?o4 z(p=tV9Mn5EBe><@ES5Mn*NsGwX%3f4r#juhQykX2D;*a?Om-+_y29ZgV3NaCtBDR} zToasA;5y!+s^>U|C(ev@7Q=On(*drdoyKs*<~lZI?|@g4Senb%?<pqjfjjorHOEt6 zZ(W>9W{sWwuq<%;AsRfww}{7Au@IgSXfBst9m-&_x$aJQRt~=`gw1sUT&}`V_x%vY zcNcHp*B%)3J;psT{ywzWM6~?V5YG4H44}(D7)klIZ3J`EUFJy3_aY5`|3Bc>w|zZ0 z&Hu7qdL-O9&edAWxd^|?8G^gAod>`vPHV*NataZX+nEoWREJ{`kJAPZ<#i|l^*ObW zCN|ua!pdJh3Z613SabzOe+qUekhUBi>!ciR>%)e-Cy;<Eu$ZU1$%ec5rSQd>5@&G1 zixFY_fJ;Sj4e{v$9!1Yqh)e2$G{sk$E5wD{fMX2a@I@1$mTEXH#6yk(xh8lpRE`(} zMXCitMne?g1?sAiFl2>R;hq9zit9%4oX{6cN6yI)aSvsnatq!8y2v^CAud%0x+rF3 zY54MS<E=n<V`v=WX7WJgt~@S62l|?QO{at?;tcdNhL)iLjNtfPd4U0Hz3!?a;UI4- zFivqJS6j>8?9!uDBwtO|^Hij%I$dv5kpgv{{z^qA$2mg|rgi3`j4A)LE<~ewZ>4qH z19bV{MoMWtSj=AkUSvty*<_!eQr5KIrYfY5A3MxS>tm_{az7n$_|_vBPUh#DjcIUB z*;WKY!QBi8=Txr!_~JI6&zpYM3-rWuw9~sV4$D7*+?A~S2jM5Z8`H7<HIROKcgE?m zvYujL7b~_;oQ91dFbf<OEaU8VX<MxLI8}#@!A_&v#$&Y%q^{~1dn>1;Dbi61TQz2I z6C`0XNcI&>I$@i;$%=UOjVX~rhp#5J$L1?D`(piMN~E}CHKRLhqwlsjs#1%2CQwat zBZqBM*<f4qU8U1qk$P%`Zt05DfEepMSLBo8H+lar*{CDt8-Z#uPu+oEW6Qf>uUYdM zJ=7g(bvDltQDgYd;=2mR14kKpIUgRkW1V3v-$eusP2$U$_9t*GHSw)vblg@^$l*Hw zm-f+z+>y3LQ(&n!Gm0V;1;v=jC^j>SKKPF)^tq|1LM!x?)JSm-yHB-)xuAMAGtuv4 z^y+M@EKNTNA2p4SZ|Q@5MDiBCrysV<(qFaP6De0`>DHb|R><7$bf(45l4)J!iL|kw zQu;1Wq;VsY=ck*^t`soT8o?6lpqR~#Xg2AeVal^T&GU7@8_B_2yTlur(duhhsXeCT zIdS3~UM=SN5y>LjW9rHZc&fR8*}2E0^Kvp?z1thPx$bn@Z!s|-m^IeKa06r5!??GY z5NG1iYA(>re36=%x<BcQ6txP_wUf>AVWA~czS^lwxs$0J`%E~d(8<)QEFhjp*YZdH zu4e1^{gLdDNv6;^-v?(T;|Z8#iUX0hz3Q_5EwxqCbk<3xxzxm*tjtSIWwy!}u*7EC ze1Ku*0q%qMTE_cq<DJKHwSkLC{jor#TZEf@)TQhJk|Kp>dsB3^v`B}l6-d!DTKRD6 zr#*rM0}D(hp8kxjC#OYPs=oTsv`EdIBk&gL%vL);16}4~K$Iq{{SnA@(jrleQc|5r zuD#n%lsFN$<K<C6wsq70vQuSmuNJA|)0@u?nr&u*L{4EOe)3Y2+iOR@YZ>Q+v{E9% zu|%chgM!pbX-5|81PdO2-2PCxtBg&)a#tC*c318yTa9w9+)0+fn#t}4e>|Q}MUp&& zZLo4zSq}Of6-zp-BUec>H$Ey#DDY=y%ZQlWq?s*)tAfpJ8O#}znJt5J!DhA$&I6m- zGPoFQX3OB(;O#bML=>S=i10RYg4`6mQ@A<!W8oIyJ;JQ#`-MA#zZLERrihmDbOT$+ zMKWhhslt81X~O-Gz7-Y&C5l<X72q1elfVVSlfiX_r+`a^8Bdw;3~(#qnc&le7lJzp zuLO4k$9Z>aU@+5b@SR{Yy#}uZ50U`)f++{4{|CWlsttY~Y^K`am%wJK4SoeYP5i$G zo+-Q+OmQ*e*++?pnQFsu2oAT3!%yHl$*2qXXRQ-vFStRN_2^0AZ16L}d@)hF%dj=U zuL<XY{~=rme%~<i?Nk^(5r;P5y~3w~zZPx}{zjN(OsO#Eh`b>))fNtlJu7KGIW75W ztu4%XWJ6)}<5sh{7|_32ErlsKXeZ1@K}jzoVngUE%%|)n%%|)pTnkJIJ^kl{hY8mM zj}k5ej~9-Y!*GQdC^9osaNHWKl2dT74{WC3U_ODFf`jodIRyu>iLYloVBXxr!kATB z8-#gtFOu=*;NNTJNLexbLmbe0toMacEv(Ol@j%vB!VF@j-2mnmCr#Ye!n)!YX3lYq zh4!o;+{I4j&E*IeP$H5ih9WqW2sZ#%ZeuD1w-)=x;7-EqC(agTmR=yt933vq9OX=w z3AYAQ^@`jMJe?eep*;+<#o-L_4Z@wkw+MFyn<HZ3zbCkIThck;`{)PRz^8vim__q< zVOG*D!YroeggKgtzbpo3(Hp|dqIZQ0z#j@Thjt6s1%D~b+&U=C-1<Sd8TeOW=0pnm zf8Hn`%#-A})ftAWG~m{laIP?GZ;@~jxSlW*<4~LaSsdlU%=Xs85Sm!+h1oru-AC}> z2W)m9f!W)hZ;q6Op#la@cNyty@WsN5z}y#2`(@y9!mGiPh3^1!ghxN?z|?XfZvdO4 zW5JJs&B?LgEnstUEch+dzvR)eFuVgcN5_J9fY(bzpM%ZOv9M?NX^xHs{|MeJetrW# zD~#D|^5|Ij;f}P|#Xc4MjxfcsJHc_@X$Xd|>3}|!mBJhs3$6zKS?qJc%9Hd{0;WWP z{u_ZE;TGVCa2s&8@LAxR!rj1ignP07ZzP6u;m};TKiC`*iv)&)%@MKSap2D4=PIx{ zA{O>D!F|R48gPH%8^J?_=YToz=S?pFk1~w>=dgObIIIL;A<Qzqfs8C+=W~lN!dnZ3 zv%pJ*^T4Zx**d73$goYo_Y1S1cvQF?yeTdQ*4U?nTY<L;v(tD*xE=US;r8Gi!fZj6 zJCVA8_lbQE@F8LL6F&+M23PJriVuUqkDh~fdJ#A%JQ5rgX6q;>qfZTj>kIRR)I^v~ zw}o&4m{J+~uMh4Z%>LjkVfF_-&5^S3)Dech;=rdFAj~HiDtr$365;c}qlGU7PZZ_@ zOclNie6{c-@U_BI!8Z%fX8(Vi7;c5b?ZOMeD}<MV*9b2Mn<HYYB<sWzv<I_Jm?L7r ztP?MYJ?q4FVb%$ALM;5SPM8y7<1m!LV2+3dvr?ENV!^Bv`z0{z1XXyMSX(gP$>cMD zslt3OqzSVHWePKgY6uSn7YH+l;+5NsSl%t^fI?+$Z+9Gb6vn&9>MG3g?j>9U+)ua` zc%ZNufCv}C{!-x*FcpZ9R@_vOiQ>>04pW8s^ycVT+z_AsTCqP9e6uiX`$FM!!OMhM zKkgQ0PCOty5d4TRa|K&GCya@dIZ#qx7mrZw{a0M<E@$X&(<9xWWwc~EY<KFfaIp(I z>ee$N-Rw>s^-Z`!$^QKru&&ohH@FJcX`S^nUUSdVui%QEIn}R*b6QtD@@nJz@v9@t zpyJ<uCZgP<*UgMfM6!jmV0uZ9$HgwG(9h0_)KQP=gR>whc}K@)M~dCAHbg(C+s%&T z+cnFLOn=JkNYLE~H6<z2Urpl(7%w(5{g+_GgS^kMufcY^o>A8u(K**dg7&#_-Qb!? zk+T}z%5qn7FKbgH)o*_~gwOacm_OfLG7Il0vk<W9n#gh6halB=Hz_M^UN&#W*Tr_d znTe`@i`?f)<yPaB9{uXgk(?eAQ_!>6o+gO;m|XvJyj>ufZ;pJ2T%TXs!8Rd^Tp-Nn zK4b{<DeQ$Xe*&U1!u)Gc(-CB$?*2olN}N*%*%ovgBS~%x8jBZ`D8}!j2hSuFr`>@b zycYvgTrQry3)%fTTzpfJM5SW<K%{z9F`irBL@~ZI(?6;h{|pj1rWk(&;Vp;lJ?`9& zAk&<7u$k)g22XK@!ta&N_4u9a@MCUQI3Bo8az4VHO>}m^&jjZixQ=(Ym@>|phIqz0 z6Yx96;a<Jb4qwuc-E***RE+oWt%)5;KXW&XU*pHK>1X^}e(o5r)MjVP`Dfbf{g7~_ zHv0i;vp0@cm?z*uuyQzOv7JKZo5Q^cF6S-Wi`$_nGSy+z^Emv<px1d8_CAMWVZW8} zFj9l|`lX1&@xj4z(ovksxepc)roY5;_br}D=dHX|XD~cbmVTXW)wP2BQYp39Z$~O2 zJ`uFn>DdbHgv(Lw^&gVj>-}fL3EJ!Q9SpsTUudsy#w8lMk|kQ#>?g_!@f{8A^{Plb zCv+~uRBEr+#qC0SeGps<LIdbhsl9$EMSpZlB&#-8bfCUo0Uu36W-X#pef<E#R;sTb zNzt|DMG7-E@ixb)GI(!m+2`nU=0ObJPfwl)p?F;1N7D%X<~#_+xjKLk8goYEXLa+J zZNzgTm(HNgsr)F1k3*=a|4hy;{5)gYf7Swe@$V+{*b4|?Uc{67yRTx%^noLWTK=A7 zm!Coje=l;XKfwr$nz$Ff!RIf)YYozMD&F|})001)AENaS<o%@iOHkMRgUCV4*Aii} z0+-HXBwX$ej5I~!r(h^hL3a7SM==J*(u>#6mwaF{BTe&j1{#>cwXUFl9Bcy9$oNXF z?s8is5YL9QE3Nsf2<LG97hle0eQ<bgw(Zmfr#O6bx}1koQ2Q(&zfBNyIv4Q%SU;RD zM9a@}t(|V~)2sheMC9~f?s)wVA`0hhvd{0PpWexb<x+yvN56erBs=$E=80oYQE+}h zSZw?I6gQM!UI$V8-gN7X`H?DdW=TeKhPKVA5E<oUmwzNeXS5)v;#52sT*1~{{dblk z>1>CadY`tOyAgV;<xu7N8Lac+vfXmN!2|qkIrHFltuiZgE0n|fyHYu+u>3pp<l*JD z6layY7&-#!4kbi;YdhEC^3XFV6;9sOc`l9tRShJXy+pq_Khm|J1w1HjJTv<c)Z(k) zmK#T0Y9h-ELiAc!=~g<DmCMIci@1@XD}3j(0jeeR!`Ho4Fi(%uk>))YBfOg9V)^ce zwfUm3n(H!gA=aW&y5Hhj1vhRLEqaRgHP4s_(OjE}-e&HTi?~Hs>tA#vCx@rgs_$Ja zHlF!ymEgbG_+9j3YNF|a$m0r)=Fq}Ob5)}2EQ&OYb5N>Ur?NadA&I)?c3Y?NJ}5${ zTb0k<I&}iv-=W!u+*fT<d0#)mTx6c(v{W88orPzqw~Fqkr}75)F~Snwz*;yKaal`s zHvyZ&W6=$~)1LaBMUlHzKwo{kxuw6~9%<Ol+)|dgrOT0*$y>@Yw{#QD=9aR|E%AMk zyrpatGnG4vX6w3(5nC%ggqIS1`{GE$kcrf9B7GcLTX%_mZ*gQW_79)B#CRINq|#Gk z<7pN01)d&R0#8G9=2GLS`_f8JKN(LP?-VW3H!qEJ439?*RF^Yfl7jaJz4e}@kuw?< z<GJ0VQPdC|QftSz!1TYRgW%J**l;6$-YYPjol@f+se0hDNPfMGknf&6bDYA57z0Ml zYp8Jov4jUP5uOMdC0I?X>GjJZRjO4-@JMG`@s!W#TtL!8;|%@bvPgEkHaw)aJQMfO zj~*Cfl;vzS;jT7MO_SKTqfUizv6|h46r-!IJ8EkJG~>E(tn2dM*>cLC)`O>P9v6AD zG9=*)d@ZOaE{{a8kNf)Nk*ewneaG@hX^jPlomGqHR7MHO+aATFo3BfJyF3z0_fUz( zwzi-A-p3mfJMW9cJ>GFcDh7@iSuuXzmOa@<iCm{Q4^&I+PDJugUXy%A!*EHW^odCC zR`K_dOO<l|I;`$^5dLu#Q@O+OBQlDge-xc5v=#oHgS@Pi`BREfDf54ljI!t79x`&< zFw&xY7uD9<pX9hv$oy6uki!<YbJG*%oy=0hn9x|M!kkp33D*LfeS`2{0L~KoI^Y_@ zrC`3!87C*2&B%C2l&aOj$oa+4g$`&eoaJzjcqMayK&I4Vs4x?|M7S8tF%<pO22T*K z3+4(a?K#`MMwmBrlW+^ZkZ%>ksbKEeW`GW0v$6s11m;!;+OxYhs~O<#V6&P5J{!DE z{PY9ABHSPRrtsz9cZ6AwzXZoAt-b&Tu7r~ZgMSbn0_Nf=?JotVq$HUy37>EUnCss3 zGZq{Z9uGEq|6o4}TubbygNub{QqEIf3^%}`QbBtum@hL%x*W{aTk=Y92jRQGJ%k?w zS1M(10$(WhFM~%2ZwHSOej7aAF!KLX7_JnD!{8ahzksh1J_5c`*o_KWsfbP8s)b^o z30@{#6}(268y4>o=7z-wgzJDe#l_GBhNp#FfL{@&PSl&i+@!cexF4942<FNV@Mpr@ zT+C???WqQJNO%(XSK+I`90Jl$d?pNjG28&IT&dvVauu=X5^s+1!{8#}4d7DYr@<Wm zGE(jvZYBIS_%vZo?)U<ypD)4PjGP~auVCmc4%|3=o-nr?ag@#g>?4K?e-FM)_y~B6 zupgCml5h~rtws!+1D+|&_J5slTeg3`_2}sgILsIB0bVT3Z3-)e2Z8SrW?#UuGQ*Ar zo0Sdlc<>WqKMA}|m~W+5ggLNylgzKE+ycW6aaaugNSN*aGvW2%eZpMXJS6-um}4B? z#G~Nfgg1iC>Idxq4u%4b@$)#?=xU=2FF>V^*P;Uq986N>fXq(DC~kv$fH}*feJ`+4 z+y+xjZWOn{!@wQH&j_$l+=l&SV57JV<}|=4Zi6R+`zQU!jS?oeZ!m$Y;K0p0WQyI4 z;x_npuu<Fw-w!s5+hDf)8RGvb@HN6)!8Zy&3+4!xac%=I6n+uB%xI6p;T0Ixh{JC1 zJ;DdT4+wt;=9G#NaXRz3unYXOFh%Ll3uk~i#i4(0PJBx^3;dq28J+JELmnJH7v^r} zuY}n*d?VZ(d|3E2@Dbs2!EU^2nHb030b%wHRfLCws|#NY&IiXCU?dE+#eq7K4Ta}` zn+bDEWJ}>&!KVqcKj3hU@jM6aD*QZn5ZOt-YKIHsU6uR*AM7E)i(3=LAsY@nERg~D zs+}pE3pPt9u+IZ?cuha0;1%TbWCC{zbNsSSxGMM|;T*70+=hR~^8)QN(Eib4tnJ2- zoHxBK%)nd<sazcVNSJ{sv!U8LM>2<nIp8@W%z=y>cS1jSO6(3yGH-$hqS3x4IJ2G@ zN?@oi+!UNI+zDJP+*zxdDN)_E*i)Jq?25kOQ-gG~^eB()oW;vK`Ym2I>B0<LKGoxS z*{Pqw#V+Wos|2InR3|+w2;0l_Bf;o02pG=^!PH5w2}LK`-a)!X7=9}B<zd+N){lpy zb(Lrp{t}K-eCR}?#qLuZP<+@T63w@r7J5J=TI8<TqEhU5!OXNEHtMW{M|G}#i<f2k zS6rN}Q_u|{w>b)HGH>qAYId}>?iNMpai?K|Yov@AdoPJbk2{^S!TVV$<xO)bTU6WU zjefsoU;u)vvzSLpFPolT?IOOyj)@g1AApQ-KRiIJxRxe%e!O^?vk)t?^+K%pQ1Zg^ zL;$|--L9+fo64~Z#DuF%SeKs{Wmng=W~Aq<klxkMdy97iyx8b}^x!d`$jK-w;XBo5 z>48_Jw@zG@8CB|JqS{pwF4hlDjNYQ1Cf<kUrF|Sqyqg`p*~Yh`56+BEMAo)@57Mzs zdPV<WzPpW$;m5qu`}5V$de<zJs)M3QN{$aW_}X|U-Doy!Ibp8CZQW2$oiRI_l|AJ0 ziUy+^=2reSYF6H)akEA(%A4zvWuDBG=8c-m_U_ATMDI$m54dz@UNpZmcfTAfB=#oA zbM8DqA>GM~*UfT7AyIh)g~Wja3W=jABl~4niXgk(y2lTpm|mC{4b<(6<|bla4unP4 z%T?o}vR<C^09o%Y{c2vcdb~YMt`@JO@B+6n;&k;T%Uany;)O!pNl4W>9dTLC0VEiA z`Xj_NhZ|?7I_x8-INXA9r85}6lg(c1E1acpo#gPfJkjhup5SmN#CWF`Y{ofHAfB-f z7uU!1cXAQMXlE*%A=Kq)F?GO3B*xQD?`6^)^<qQzhhS{TZVrEq9UeVV;QS2{pw5{s zaurv@orj&i$1r@wPIo&Vy)8f5-1z}9R7!!n>$HMszPetQ7DVf`JQprd{v3n5az-Jb z<t#%;ieWiS3GRe5l|LzF3iX9Mlt1a$3PH?yTS2s-_IdCQeNTD_hVFqA^gX#1HyUD} z34PB`V8{yXaOsZ=qK)mXwyshbZJa^zH#9XVzG)eH&DMPjqlFot!z;8i3-E+(ExSZt zUl=V=59s>~qfN2bcsES;7MBhbMQ?D1A-u06gDd~zdUa7WKmGv{cln!BZs*iPOqMg3 zkK#;$*W@{!DGujxE{78;ND#Td$rWhE*{i=jo-I(e9?tX(hrp?f$VXk%XyDA{^fLhw z1w`&Tnk;hHL*(xIjN)jGsvk3`$XE9vY~Xy}qtE}gt)~@7tE6Wk(!d}l32~~{D~qG~ z*+0URHugLGdi^8GlUE^3n!l?40M1ZKv`eCSt@y;Mx5=?;IM1(->V@cYzCe7cuet<| zIqUEYs-LPL^JE!yo?@-e*_omTl|(aDbv>yh+Rc6=MQ<yK*7Y%r%29bi{Yy#oJ^Krn zez$gXtJ<1aS|@susvm}P+H^j6lc(@do}fvPpBap@RvHmaly%K&8c5ZR>qX1dXL>}v zXv=DxIHenb&g1lbOrX>38vSIwXk#@?AF79v?V&U4M;od=iH`N7<K3P|5zMxxp1inZ zq@GhP;v}XuiN@V}*VE~dM86i%*7nJEqY2$Ix-dIVMT<(|2q(XlYN5Bmp7MmY$dTKH zJAhXR^R0cSaAz<}i~hTS`PLzy4c;hx4){sozTjt)9Jjb&$=MVGTmXJecp&&6!h^w- z;?U0!@F&6?iSHF21LnkvemD~UPIxN#XW^T{3iXVBIN(mJ+yuEAhKM-a0j7F1J>3hg zDa=l+Q21qVUE#ODjfCF=Hy7RmK2?}qFuPpF`91hdVVk1s?qc8w`W)e!;PZt!qaG|= z56mS)Msy1Ja$&9}juq|<zC!qXa9nr*c$P2+(AR^_CP)sB=ZeE<uoj*SULrgfe3vi> z$6WW~P0R;BBD@^TnHcRkXx<{sI`Et@2hCK`r=M4Ow9*@5coPon^XRY>yjz&>35s!O zzZ-0%IN)EvMv4Ot!~JLRQx(^ARAe^zEM#?5I2TNjHSP1jxrQ+~E`Xs(9BPBv+0s)z zaARSN2CZ`8=HS-CZNTk?+k-m`p8+<K8^ptw(nsvOf-ey60lv@(N8pJ~<zjK@4IU|c zE_j?UM}?Dxhk~aIUk08nd;|CfVGX`TcoBGk@DlJ+;o7TU;L<0b_zv*h!jFNC7zg&- z!H*<*_KSX)g5~>0{V{TWNzdSAn|_U#DZ17GjIOOFdeHzg0^d6Twlj5$ff!vsW){>Z z4U7iuXmfqtKn#ZKpkRK`j|{}<x>ilIuzvu~s)<&EFdn-U(}ti~&~G~kwrzD!+Fl9U z9{ROwpzt?`*5~RKu*Qu%PuH}3)Ec9jcULPkHNE0GPc*xtY~b)QgD<Ka%N-lX;XIJv z4Y}hK4yae~!?`Q}>~#F7H%st~G1^_Q#q$0YxEveeQJ94B+9&j4yE#NUHV!W~;oNNO z2>uA&T%H(B%6kx(6UX5T(oJC35#zxQCkNuG|A~S4&3%K7^n(+k8};2oqn%IoEyBTg z!$iw|!KNzFcX;&1KN*QXVMgM=CP(5Ku75QW&pI{|&(t?u5<PAkhAFku<V5KuGg0Ck zNwM1r%0!9X*RcXJ!)@hduZ#j>S9Pp_WTLd6ZZ6M*baQ#wF`$6<;&NgEQBHs{_7BD# zM>2DwWdCOA)^Gae{s(4CETH{=P1#Hw8GR-NQ(QAYYWj!y(cev}{FE#e?u|HZe$+lW zKZ>G<jhRwuYvxCK_t@xhDzE>dRG5cFQYzP+P%4X<mq$y5qpv@d%FoPam&Zl7qowjF zOedDg9VV>H;YHcG$yO8nPqZ3NUs)*I@<xpr)^J3{gtCSsMh+WS)?kQr*{G2h<&GFR z&Kf&n^00ANR1DLD8+)t%C57i2a`E6XiMb=AIV$14g7e(JupF!EHdCV+$5fa9&?g2= z>k1-s3#A-qgO9bYg(ll8Th~1_{ay?qtxLMUf7!a$n6Uq&t?O`myd8LG3QDlyWut}+ zzN{g(PK+7b@S?%vnd?Iv;{W&&BS%$U2M!xsQQo+$tf5@%Up8?>g+3~fNGzKX?V0kg z<q-dV@Ao?iQS-87$G7cR$4AM}$##6~JdZW8|2-XFdE$oaq8n1M@4$3?rGM!7HkytP z2c%Ij#O0xX-tk3D$Ja_XdL){qzq<MN9p8zi!ikOIt0G4l%vA8P1|#+Vb9QdFJK1@m zZ)LmjwB^O+{>fZC_a{rG0Zq#L9WEz!e5TaAt`vGxc9mqu=l_p&d@UBG)zI75M|YlV zuQo4lXhc_A67?run-_iVuPYsh?J{-Sg})yxoJ8qxZhNddYio+7vUDE!FG`1VWDFMm zUs*Z{l+J5^QZSF1W^*{%Y^bIChh~HC)T~hM%=uacvH8c8%&jYbUo!th-p$tW@5{S8 zCQC*oi$vtz&1m_5U*4^=*F+;a|1(c*J!gdT%*i&M-wD1q-ua&pe3w<umLUE9{e<a{ zLvIca@}#e$!1h>QX9n9x2YF`t^e+Yn|JBfYWwJH>PY%5gx5E+u$95+<GDu){)LSLO z4@7VJ>xOQ46aCji17`n!XK0Yj+{%~GiE|<|GCw-{{@*h+C`{De7=7_i`nX3-ANOst zk4rtVk87Kp6H(-yoD)eGH|P7POD}&Sn(mRsBHd1_On2iZC%%KskeXRpLs|_5fX7;m zEE>s#b+xJazbhOr;$gtHo^D4AhmGUJ5kgWLfrUW!gmzYPgpl?h8zEq7^qg+=RJ7U2 zc5-Yorzw5F6$>RcKFuEPUyk4srkK7@7L)g%6_Xuw&rAQh2(KYDnyOVs3?E!EqOyNG z+PPI0RQVsfxBq{D{jX;{<%v&UjBff9$-)LxJU=9h$9H1!94A>w%6rhPUW?ZL^R{C~ z*BmAM^U*cO-FWHC==#Ktt*vP^mE$+**#70{n)`77=f-b-RLX|f3p=8sfv)wLr|w@k zR_Jzr^y$Q~xBs*i{hOT~8<JkOBbxEwD69YOOlXzK@5+Ae#IoYL68gD+SyoH_N6Sk8 zr8A+##1H;-to^8ILEj}?kmtk}bliI=xp%?5hqAJU4?M1qJ8lS9*~^{qI*N07K~=*~ zbz~#|Y|6WjO1;xzfYf^$9FM)DxDteR#^o){Voxl)cC>W4MSLe^*N~RVOHufV@2Djr z^)_NYWoIT|Qi1=_OA5O;K8r^GGRf*KI-`mAfy6I+qRao}9rf=QVWw{XRW$tj)>T%X zl>Tf!CjFrdpsI`_t~{ZHZc3Jrj3Rzx_WyqDO_2hc)!p=YbQJN&A)XP{dR_ZX3EI(Q z0eSyJ1=L!H4@7@F*#QJ+Nrj1q2csKPRBlrEQ}PGl&qJnV9ZI$=ZWKOl7K_0GcLk-P zKS~OJnkFZ)7~%b)SWak7fquv))0%3i+b)e&yXc>e?U>1EHz$tmPBX>fK5=YUYI5EC ze|c=zT&Ew7#{QCKbNtwD-OqpeR{D3wcC~!5EWP_kH1zvM^Z$v`xzLXNm8Fxw$otPa zw12Z;emA7UY^c24Y;@d~xXl+U@x=dz#>dYr9{*=^L&?z(Fzm$&G+sjIz~ix(kP#>- z?^DLjorMVOFjlUQo|u~KxIA4=|K{eVd31B!kZm^Fy+yCedmj&BIPS<)yPX$l)aQ;A z`$>e9qf+<#fJx13>KDjSsUzsYOMMXRqg;!C7%}D}0q;Io`DWk;QSZX9zcEtB*{J~p z2n@wfYSYK*YS~Zun0|{x;It!rJWp9OxI2Tf&&YBX!Y0*8$8Q5Gy&Yo4*{X~K)45G} zY@2%ky_0zZ>4%Vlx4I(x-$DSdFEo>>ar2-r%)KF2fXb`BNH4I<@-M|Bd40{-@>ul1 z0|?<O=K{DDScIf~Eyyk_?Kv1+{?=KD-Kc+OJ9i=+ls?no4yDf#FhS|FLBJ?|)<I%W z`ka9als@xNBvAUi3mFEbPi_W>(&wFs2}+;a;Rc=0-(ZSE>GNWwPo>Wc>|Ub=k;BdP zmcuh2;?B27W1874IMtaCp5k;u0#`cx7}jKGH}3EXqi{XRIf$etI@IZ%;QRxw;~j2x z8RvKr&sb+Xe#bcccFSmIAbetP;@L=MNMOJ=Bxc`*0BPs5=rUYRzh`+D)!`TW6uB)3 z`xJS;PGjd=#9rVWG4<6hLwKix8)Oh>?sp6mMHuW;q_VVf+QSCt##Ym}M`ATjoq(Ko zHeHUStpNAlJ5SC4x&l1f$l3NF*c;?W*_{{3{y<Oobhh6KP77?&-$!DN<J^4&Ra^Wh zr!g|kcB;cuibG8amvcQ5a68=Ok?K&8<8h{<V7yK}+>_7Qi?DtxEyg0v82vsY=W!vH z^F1C+In?y9QDM2g(ZdRv>e^3aeYCluB-r&geP=Y*uo1uBT@vicoq7T87Z3KLA1jc6 zeUe=P?tBdP;=OwVDcTc@<;VH>!M;2g439&v{pcJFaGy}{d_HnGFo4k+js|!jM{p4D zBr9+lo+CJf{&NDG5kqhoxq4tAZaO%Uhm++7?xKCg4A>V~c9{oTIxqSTR;jL^@#_uh zwXs-Kx%CsVSY~`99$Y=hMu?_x9d5>}Ht=ZNz=L4*IAuG?tcP$ZRWE!<hek+4y~tFp zz+L!JFOgN?TsW$i$#!5FV||6365v@3>Q$3Mz#NUao$L)9p#OTW(SU4Vq^~pnVBlp2 zc!Qi3=+3)%lbjp)Oi!;8%Zb;4Ax-V(*4jV~JdpaF+Ypo8iQ3Boa0PZTihWGqYehl` zpmJ<=HbO-E(<R5=gY;q*(5JRp3#(-E$O=_p(+e|-IgrKEyOcjgQB5Ix#L!7J+{uH+ zqTEgk10%7jZqfBJW7XA}x^rf%vFfU)X2y!K0dh@dtUztlFYt1M{yH;udMP_R^{`?v zW?bIYy!(e03;cQfuhA1f>QU7U>DqHI&VN{6m=$|ib=H~LvG?pvcH-OYn4ikhN2<mO z)$6*jT5Mb~YmqwLoX1(4!58;L1<B*aKG-s2rUCOR^yX@@)~by@QY|)BU8ASw#76bH zp3k?{W-cKT^X&;71{-40y=v12ga{|2hbuKZN?$d8p;zAU83x^XG-%ReqxW69P4!sq zVxBsvel$^V*O^*;08!+PXP6&t_NUzTRimZ8xq56uReo1Y)k<M2j3LqDs&MCAD}S!8 zStHi43UxJ9ZIjnW-D(WgLu<rJ+J4ClZJ)v}m=i0t_#%YN;{*V<e6G%jF>gLIqkRh9 zE@cWe;7|qsk-|$z!QP&#f2|QaMNQP@HDiS#Q@9gSn0Km|)#xRqN7jth4!_S>K4PS9 z+$uW2GxXY;u||<kJ+MD?oW1htuWH6RIA<a)oNmglquDRIO>V5JTBFa)MS?H5^!2&1 z+L0b8s_0>7F=ESxhDf>9;t~B^F3Pr8f0Y|6$hrtYojk?3C&S%mI?Pkj{knFoST&WQ zJJgEhtD$;Ct=Q@9d0tL%5^F;gHPpv2R<l~jyWsSOw4jTR-9z$q+?*%)MFZ(fyB*xi zt+F?5eV`U9^72G_UhFHMw>t{Pw(?Vq&O`gb6%}I}jvYC!;$+qVp#9M1Wac!Zv$17* zRKoF{#Amxle`q(?2Re8%Px3~ZC05msE$|$79_t;=V!PcZ6Dv1RB(856>(?e;iju0_ zihMO0#mm2GD8@=1Z0=&O)V02ljVqk=qsfsZ+iX42BvZGc@_1FAT330zDs?6*k5}cp zUu9t^#y^f6RCY3ODyuoABlzRtJt`;3x00(Tc^8?j3x6&)Yiv{G9}f*vxd8mN#KUm= zD(bV<PMBK(I|?&M*A%2rPkAu(5{D9SKjAuH4qWJ`KKK%0&JsrpHvzL(r=K#g(fI|J zgKwfea<n)2R$)q17YU!o=U*;{LEt-tF9hE!JQVz(@Nn=3;St~`gvWum3Qq*TB0L%V zjxf`rZUJv-26!JhPQ%||I3y0&fqxXf5&WC*9I#RDh5tohZr)&6wriu?3tkE~y1n3g z!A7?iydKPMf&L!_o6||b*xVgY9#0CxRyY_%Uodxi8%1C6Ua(R01^)={BoT4(8H&Cp z(loHq^M#*mu+j4c=Ya=_pAztJ;c~Fi^YtN5TEbuyeG%Yv@C5O6Ciq&ilRQe~W?|NY z+l2WtxLvprc!e<Q0kw}9wiS4taC@-P=Y@So@MGpYRv6BNVT*V=2mG8cr$sLdUj}|d znC1PhFw6Tx;VZ!A!y$<CD)5(Le*^eyVHTf_3QA?cI9nIxR5a8A^BjC~0hoIb$wlC* z!fX+_!u7yK!hHIA!fX+Zg<F8jh51G{Cz~S9w&3<|ls^;b3<D3tB6kD#5bgo)BYXjv zibC{r3HWj{I-)f2SYf<htSf}sFU5t~?q><J+u(qNVN2Nm+$@F$a9Bx3$WriK!p*?z zh1sUf2bbaJ6!2qW&obUD%%^--xE+|sXEDyRz^@DQA>Sd#;m{9;55$4(p2r0-z@^|X zgr|c!j-~z8V4i|To&)|#crn;PPs*beS*#IZ7HhUJi<SDh^iu?m*B1lJwYhL(a692s z!Dk6~0{0YV(eRuOM${X8F&X)cI+i@aRCtWoqtue$OvZqSey*i`734n+i)qMAIxIhq zjgBowcJ#B6_QE^}gpAjK^^7oDul1rZ>%^<Vd{=!;&Q8X&=Q!SP&SQlG#wgae;*bvh zNthMtH(}ggQpXlAC*DvdQV$Co6<aWG$f($Yc@wq8594eo%$#T<9A=+<1`Q}Myu6a% zItKHG&K7$HK3AB52MDA1lP8SAKXTQo5PM{d#g9=i&Z^)k!Z2Dqx{3B|1%Cs_X~>0v zr<#%Z_FG2AtCml&MmPg}k1(_J0bvxsl@MkQJtfS9pBHAruL`p=z9n1_=_fySjKrG4 zVILiEYs?9AlBlpbNfgYS_(lA%Xfoh2Tr*i5vE$f$x)}EGYSk2b){n;I+@$|<!?*>O zWovO@fcC-+&{>$--p!l%?dsUbbh}drJ@S@VH>gKHeoKt%(ayYBcRQ!E9xyM~%`P}g zug6s_*1yuaq^s_BE3B<<dMU42-SmE5OS|dTx8d5Uo4$$H%ev_ga8+}3{rQM=v!05J z9qq1PnGf65y1It#oBDEIeoQ>BW0}g%>7n0V0N1;8;lkKNyZ3OtbRmpW^j8ZJw!A{O zUKFdNdg(1gors>YC>Dew$&HI*#qJ$w?F;nAMX`K)Oqu>*QLM;46R)hKJU-|4SkS!* z#yLhEq&<vw+LgM`?Xe=eOLIL9SLf3!EpwbiFXT&4qjFuZm3{>-?kT6C$J0HBJNas> zuD&?-J6YuKwq_(XKvERmHTciJ6E#3q!xm!5@wgllL;j7H%KHj@L#Ce;I-(1N$?GZR z#pT{*E*{x4$nGBjcH(m4TG*`_jLPf!!g#QMwe%AWy?OS*|A>k~r4Gn`{mHUe=wyfQ dTyZfvAhne4u{0V^^jQ(R?oZal{-10i{68YyH*^31 diff --git a/tools/sdk/lib/liblwip2-536-feat.a b/tools/sdk/lib/liblwip2-536-feat.a index fe3218fa72d856ef020356c408a00d744b074f6d..05098cd31090e6fec7ff6b0aacb7163c76c235d6 100644 GIT binary patch delta 234627 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 delta 236579 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 M{Gx4*vi;<L0lTc<>Hq)$ diff --git a/tools/sdk/lib/liblwip2-536.a b/tools/sdk/lib/liblwip2-536.a index 85c3db3bd3c678cdc4e3f0fdf262805af169eab9..e7c15646ca7c06e0c7958134cc039fa053d4112f 100644 GIT binary patch delta 209150 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	<=%E#b*v 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	tzvep5Wo|UJc6=nC<Kd@#A6J*%Leo{z!SI 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 delta 211284 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 OcU1h_JMy^n^1lE;CDC92 diff --git a/tools/sdk/lib/liblwip6-1460-feat.a b/tools/sdk/lib/liblwip6-1460-feat.a index 995020bde52d4c0f5e856fdbb4f95a6ddd193c10..8f9f42ca0c43f048faa02b5ee633147877783590 100644 GIT binary patch delta 283429 zcmc$n2b>hey7s$zX5;Ma&dg@mg^i>Ic7Y|QC1;i_nI#9wQ9v9(#e@nDSO!EeVnP&k zQITNaC<r2ALO~3e^HGmt`ktry9qH@2_a47{@AuvQZBPH}t+#UM>guZAeY+NYx_QyM z8sXMW%UiTAYtlR~uPl#;`!_GINt5!Xj-)Elvg{_7)u{3R=o$V`J^bJz%lcxEW&QBj z|En`>scjkm?bAMfo8>+|-EHfyo#DT#`2R>R{GY_sd&dmxzjMYEd}{rxGyJa<V)u`= z{-ZN))FA7h&g(z4;{Lt!(WkAre?G(iB#dv+*)nJQ?N<E%<hkr#EB@lMe>%f|7W{uU zhyN)?e?0<;V+yRqDXahG>1%q#`j5`=zp=Qvzva8*w*UBiuc_txFPur2-DbH@|Cehl zIm1!-<C<KOVg3I*!x>ge&WBb?oi_hFXIKIbR9<8ShM)LvpTUkdS^qa@*sUD8u(Rbp zQ){%a{;Ox&!?Ue_b*3*^9k%fEpP$dyveN%A&Wx%S*1tM46J}V>8IHogbDjIGmFYhB z-fLyP5c`+Uti>Iytnl^!e7^9Tl@&e1QE*+e*B-I{yJyYf_pHBihHF+|X_@n6$g24t zoH^Y;v~mWtv2sRSW93W$&jc?5U-X`pb9rMcXZ>m`=cd>GE2r1W?Vb^tyQ0m`&Iwy= zy}GZ;NSi%*;q)ov7AzdUaM6Ns6Q_-zJ$3S=$h*E~I~yeZ?2p`^mlXM`#@a}6je|Rv z*X*St&*lx$v&%E%cHUg8mc8@2oR<`Jb{6H|=JQykrID8#7DrAuOo;r@uq+m%t!B-d z=p7y7vtr6yv}(~Rvi=`+)g?RUH5!npzKlHG@*%Y{vanS_{C#nj<%#z$iEM6FqJ~8d zw#rkZBcHW;L|q=)(z;wViM-l+nEg;(q*0sU>dwfTHn*u}k@{`V2XAcqseLeR=c;zU z+Nype+;ON{8hN$j&Gxal$oz`wyqv6PpvFhyJ1w)Hii=#*sV@Ayzf)7Sbmu#rN)#@> zE`61n85!R77ijMs*6ntshDXkJpGCLRdo1GRbdNUn+i^Q{dS0Q_^^v=JHBeI`FZWue zx<&f-Zl^AaT+w@>>ag>--p{ARU73J^qcvD>{fEk~GkL*Wt906&S(8hrj$eeVoj<8` z(&WXZ5VvaDqDAzo^Eake<o|26cl*Vc>95zvB>pwsmipxPcKpuD(HEse@@76&@E0O7 zuW5YN&bMc7=o7B8Elb5%=2${T0rA*CMiO~EL{4(}OAk23VV@TqaJYaRboe}S$l+<^ zREO7-(;a?-oN0xP=_CzVj>TDWw!<;8;2I7uCf9WMYI2UlJIJ{XA12pw_-k@)hwnk6 zRKCM);=u(D-xrVYRiR^enifS4e@3q3a2j$!)pPiK<U~kvYmSRolMx8wZe1?S%v&qW zxZX;JkUDn?GkohFF;HnY8ClKDcv_el@Vqb+dPF!6d|a4mI3ZjNJ}q1q{Go6u_;X=A z@mSx2!wjq(h9AYEJ@_}_3a}UDO`V?LMB&lkfN&K!LwEu>M|cvrKzItcp73mNW8sAe z-zpaabE1v#YH)?{rQq(umx22VUjZH@d=+@O@YUe4!t213gl_=P5WWdK*Dyle1jAyn z*aE&#_%85j;cei{h3^AjBm4k(gYXXUO~Ma@w+Qb7-zEG6_<rGMzz>JTa1e%F!f%83 z2%iE!EBr3_pz!<PqrzvvuL*wyep~np@O#2Pf<F{K3;v0WW*la1{9O!q6t+AN(1Oi6 zgDma4hKn1K(bm}|G!teMZ!Mew?kLQP+)bDjypJ#&RHYZ?PmjuAsG@~*8VktqF&^@z zE@o^g_d$NCFynWHFazF1MkhnJx4C$mFx_q!4zT}uSPXRh968f*d`Q?2`OCsg&8xy} zS|5`k#KrnjnC<>sVWuY*{Y3~JS`pYU+z^~f4#R?}uOSv~!Fj?J;5x#+zzv0mfSU>r z1Gf?$4(=d43fxt=3fx<mO>uzmbZ~f>7}zdH3(o~l5MBVDE_?xauJAJO5@9yoRl=*l zmkDnGUoE^D91-3EzR}^Zbvq2Vip8DaJB9BB-zR)O_#xp(z}3P}f}avT0DeaJ5cmb* zBjA^WUk1M_%+~Q%45H4m`38n}#o~MLN5cOAe<A!6`0v6$gMSi^RhIRua2hxe3qNZ( zbtpp^b==Ak<_)kwIFngdPYj5M)mWHKrCgXdv^K(d;0obFaChNia9?3o%t68pz{7=E z>Bb6Uw#%9X4l|~mV3;8my}`4E`+`@IYdSUjQWxJqMl4zLHw&}o-yxg^-X@#}ev*v4 z7xniGqrVAT&xwKU_zg0WOQlo7^z;K^dit?&9{6W+ZOfvZ0~c~WI8N9!IpG$Nrwa2X zmu(pN&s5eHi%M{@@Oj`8;W6MQ!sEa#g?YzoFFXm{MR+Q>m+%a5rSL59P~j!uQDHG$ z0>gOWHQ=ejmxE^sUkP3yybion_&RXZpN-&4MXteD3Eu=>FMJDF3x~JDaElo31#cB* zlY4}W{ABh%A&jbE?Gt9jJRqD0J}k`2_=<2N@SDQy=-v@-4n7md{vQFfgyD0sXbt{W zxHI@i;jZA{gu8>i=-}y=J!7IUi!vbGADkgP5S$~-9<xAr6#M^rVi*sL#=`6kn+mfx z>_#qdhGl((QP-@2!mzT=6K16wBU}eOQMf*Mx^M}24mk{$Y>SJ;q8z+jxGi{<FjH`u z@KEs8!V|y|VOF#oh39~86<!6tUHD?~V`O$7IKof342Q{xJ}%ZPE`C#(x6XHj*<9Zj z=AH8gGLnmn^^1#bv|q~UHeQ%+lN=6PbX=Q;dXD2_7ncaraTDQWa7$qhI@$}fTkRs8 z3GOA#UbRw~m3OEx`XXyo!c-?<mgRV{K%KIt3Nx2x3A0u&5N-foD%=np7H08XD$ELd zg>YZJ^|R!>ohP5`n5w!)a^I{}(;~CpT%y)S&b(P^-#<9g;>2S6=-|lq6N^>5Nby^h z>Vn9kw<_&NhC~j$)!+VQNF?L!{wgmr`Rz)3*RaTAFyL-_vQlM5hT^wf<WBrnMZU-H zC6R8YD)F?v5x<inXHG4Fe9SwQYE$HacPi~SM(+IWoheE+j7)yF(mp;u^4PnJ)w)Qd z_bTyZyyCq|`{<g;k@p&?YxGucAT^Toe!$*$Wu(^obz;0|q#Gi=-Y--)L}tBTH|E}s z7<oiiy^$KZA4>0ajO=;8jtWH1ykA#c8S#Hm*PnEwWnB`ByhJ`s)-QVlIgv3R)Qu@a zADgCE4azM<xDR|#|KH3VG;LPaD$kiah~%GXmN8S|AzQ_Vc(G$HGMBg!kr`(iwJ4^+ z8+W;L>A{PN&%-6gyBZ<JF2axP^<F@WcyD84Z+D6uK2xZgN4`08U3+$kwzUDjO8uPd z$FG8tg;V{7C+Mx;#CD8iesuOPJfibqJMzpoxz}&a$=-Rx$KQGE54@3UK3{Bq9;1_A zPHdny>;0Ey6~^S-=%XX6ekfEA>-^+EUHe&&-u`l89s3tg<j5CwVqWy3M~meDqtN~_ zCQ|FmdjB@(nl@|U<XpSR`Y${5pN@2R?6?YCyxy4Uvlm((6+4(h6`y77V#e_jkC6*6 zadmm|#*|R#ja%$o*r?#3P9*oM#;QEh_pAS*Y%9|lSLf_&GIi#n$)%I#%$<+;HJ<oa zW>Cz;#WUZ0<B8pe-1xxKwZ;SrB5!{`K;02(^g~HBE0d6wVUv|tIazs&WaS$sE7i70 z?mz0r>_FPrnkqc{AEEf@8^cKBMw#B`&C1OjR>m(|nFY=>GVT@Dc&o~~uxaF>Uo!OR zw-aM_e)5k)Uhjpr|7(a!B1cPOB2_=eh4Y@?anjS|+u!pVeqHwTmV_pak~XbSU;n-j zx1P6EXWO5YT2`Ldw6lK=docAGE!z8YF6q-yed2KEEm;LG=BN*&HU%%1s}E>sl%(F5 z>wCQBzxjJT`)}99HS()>M1JabJ*QDjoyf{xUy2O*t!U?x-{#qoispgqYo{aykul~; z1Q&}v*M`V9zoqE}r8;JIM`<Hdad;Kmi+TaK+dGr=9HqMW^U<e!?3hb&u|s;VQq4zv zg3b+<<7ZrAy$`@y+!p-AdUxSB-d>MR+ndfivb`Dk=gpr?%%`*wZ>b)y_kI{K8MqoA z*bgFNF`o0NldAjKYFZ!mo$;xy5D~AH@KquV@hz``DRB#mExuI;s9K3@;6;3EGL%lk zMOs4Jom9$!e+lh~R$_<iJ!+7ep$B`^kk)>rAm~kMYi3uL!dr|u;VvAy6ns&r2x(ps zvcMOHcsp4h;y7+u=%+Y++M{y(nSRS!7@7v(7lf|W30~D?Xg1<-QRsJwR)jt>4mns_ z9{R>O{1CQFLyy4rf{=xnFA0rAn2SR#5syV7jjUN1x&r|%2wef&`Jq$rVP2?IU+Yzk z3aVgH6gm&T$d{hzOq1vKfQz6vdHt=phQ5f`r@X3{^67dps!-jf`^KoQ!@9x?PpAcg z^oBN~L}NnNK@uC<4UP--f?x5WzrnMF(DzBmp3n@~`a)HZBw49l5npd$-ks15@kVZi zzJi4c_17Q9s0Q)#V69k2S+Q!0eL6v}j8#o*^6nqVQ+$Xxn)wx+2I{D5VK|;SLLZJ* z+3J4%QLI{u2#$|a_3ht%dTpE<tv2aT;?!|fqW8qBNX<P+rfRSHBHpz*L8dB{DP$|} zw4RxuTGSklc&dI%aYU8-1Y^}tokCz%UV?rqL3LL*YHy-Cuk=nlc5|k!p&Ddgh-c`P zP^pHj&KkfTK9gH@n&am=V&230%0%P#<wR9eEzw^js!i&QzS5_1Gh)y_$0Ahmsbn-9 zWTxt;e9&yG-}I^GszRqEsVw_lpRS*ziZi}v{yf+kzcDBv^c#8j8K@^Eso7Oi;oB9k ziTc(FR!bqf<(#Ze56Esryh;WEu7c$g=PXU|TOd1fPF80E^wuJZR*MF@sbAHNdlU)? zK{pAgEYzr$FDB>}epL_gz00p!#xrxQmZ#$M89z$kfbN{E+N!hqqGVM7)7E6w0jAT* zs!e$&#{CV|U}Pa9ynX<3jdiC7#3hdd`UAd3bAYXCVwLZQXq@h!qUxx*dQpnP7)C#r zqWY!3%3?dLH0&=yX_XWMZqRiDs!!NYt2b0zOgQa;RXIn751U{IdH$}D1+m^-)Py#Z zVX3@!0-G}qmbu!r46X{<mB1zwB2Ln@HPymvvs$RZR?FR}Dk=qDp#2y}x5AO5lwzOa zd=f%w`7*UmD$^ett@{y?!XIdR($qoD=M?_P$U0`u-Lx}7oi;VFBg`fJ;FLxD6M~Q; zt}_L)XP9C00cT;E51$*VA*v^HHoU@7^jak=#lFIAFV;C$$<<;#?%%O4w@Nm``Z$7F zV6088FX3a}hmc+7l05(!E5OZ;ENrhprauZH^HSn$wd{gkK`k>A@-M+oZTb@P7fyC8 zGud$^lAAw$E|sY87>tDtm|KqdJz7s)5;gkKQVU~HWno<m^;R^$isDdpmnnM9iHQ7J z3l~x0StzW7*~#6DOz!T`g(1~E=0_xEogNcXwUSK>xfiPG>6W!uUlCIItyr>ez&B*9 zYQnVO*{=Kz=(K>&AHs_ui1mI4y*Sq4npq)TGgTFa>myg378~pR3AP<Bg>7Jy2|wur zq^%DW{Ocf8R{KMYe8;wbI7!+9`TRc=j9Q%4{!`{-#l?T9#f=8GpN`b2&g|Ko@H#$- z?9xxAs`$EFQNsc|75l1m)3J5>9bSZ5c3O@Igj#fN2vgGJGy3yXRn(MyQ#xm{(|IdM zXA7_@PUAN@UuDwHNV;-zH)#s*c5QX%G*uKHc+Tz^3MI7%qr!Tdem9_-RgueBys6kT zIkBi%kIpo3NU=L|BwhEzW!lVk@SFXS2s!1JK8Qm0L5{F<PYBcI9QZ?!+@%&;ao~27 zvu9IvhYXdW6Vg?%YkT;~PJ;bTIw74gOJ|;2U2lYC`~V7?(Axa81EDZm;u6;tp2m7R z>#^x7BRq~O)U`U#MASpg=2Gx61wAGq4>KRKyF37k<bYx(-9THDlYfVX$xf?lDRLpJ zGZVuO$z-Oah%bP$m$Ox;v*WTlXTZy}xom%qMxTm@;Vf`MvH3ZoipQC$FDlkyN7DTW zBqo)po=$QfX6Pol6?4%e1@2NU(yNg_gFH23EKhP9U)z{osdg3`NBKEprXG7osAlzn zY;{G99&n|{t8Z0Vx#5QJi#edILA>n4>9x?M-U=`W6*$A7tiilIX>bfL`*2cs@E^LJ zAgRKstkJwoHaLhEwjoG)*@rWWK{PA+yQ+S>wu&hAqF$e`?&hPm>9cudH_Wg%;6zfa zm#X^}VCYf`{3o4#kWuF&oYA8-%FVV0=q5LMYX60Yum3l%T$}urm#ln^TfMkg^^R@M z$a^mFDo-3@uM$w_@T?ibtgt*7=q0c}p@13VIq6Xz3wru*C2E55>Y|3~)#^Yag?o0V z=IWFl+f&6R|I=&y-0HS1)Gp6oi5MTEs=sZmYAC&FUuwM0x;8$kI<KwD@#?u95a3sT z^W^CVZ;va|Yxl(@HEN1TF{)$bimGX91MhbQIC)b+^ESLsk8i7*>1`cVJ6*OVJu7l} zVZJ^!CAq0T2^u`uP1*XP*FC8Toccj~uqNnEU*)9xYMBQUmiJP<K9rG}!ir1dIGnbX zr&C76*Va$e_J>j!G!JytsD9n`eTi}TrRNz@RM<^S&c$Pu;L*)F7_72-=;d{jN+bOj z&)0ol_a^Hj6O#ja<m=u%edQbYY0)_$pjW@*Dbug@tdXY|cTO0fYb~s~LpONCJ3x;- z?ro~qmdDr9zr7U9Q^R$2=Y-n2^Knl|Z|SOPsk(Y^R~61Lu*%Ra@nEV8kiM}nlQHXV zg{)#duA8b1*0&ymnAw_d#3g!fH&t6T((k}lmFm*&s&;-8i!Yz4RM#jqv(~`e3Vf$A zH`jBzt2wHreh1pBwf>!#wz_r?T-xi7Jyf=N*H>V5v>rk4#Dj%eU{zQzh?z1B46Ktd zN1JE}ZwL6YFnZ8Fg(;AO=E6UjTfxk7<Jcf%b+P(8_Pvc0IvDyV2Q&U;zFN$@<m1)z z&0?n8AZC2;(!ri;g=$`XZBJF|`Hxq(=zSNZr0ZjS)Q(7lq~bh2-=OHF@-Qn^U;N;p z|EiBZ)mQas(%(p|QMjbVIT=FsiQK4G;x(?LW~oX&te+~(9^jbSk8#BSeJA?{=<8@b z(6R0!){F?*H&7peb$F0ty-ci`P_j?tY$X`Znqwt?83JWwpUCMZnl_V8Nt;P$A6Vir zk&khhztI&QdTxK!DVlP&^EBSyaV5J`p5})@4ppSz>#qi9OS@|ZaT*&W4zlk&-M><0 z_8M*^CbhI?6imuRZlX8B(HVvdbtohIL~fEZOmByG*_7j$f|IHj;A&DnQe(n1)6a)% zIaHyx2jJFHtn1)XJjM~T<)tBMj0f2#a@wLSXAeM>+2P<YDMD{SRg)r-n<!UN!?}f~ zL5H%oIDJ+4!C|7@Umt;YVW~MLn&Ta7mJOXzM)rxE<xM#sG)<vT0N@yglXA+)K9RGT zDOOJ$#tn2RBl|>Ni<SyimIun!O3O6p)P_mA!-C|@CX*Zyf0g7R#wS)9J;Oovx%0MC z9~`Jkiw7E8)AgriJ2_QARgs${RO(uTRAw<EkR#n3Bg5CG%vi-3$$|VIIS9k|X?i<c z=!Z_FrcRj(yEGJ34z6V1bVoT47d6A-i*TV1Wn`boi@-|sIn<&KW#p(o^{6vLcNnZP zr-`$M6rGPB96NE+8D(Uj$jiWLCVp@{iIX~%k$oaB2di25!Eq2LbtpTi-$iKp_+S<E z&!MGrsCkhimt+o|=a`s{X-KpgJAk7F$Sh4WBPz+i1&)4gkuy)pK9QTsI!ccnf{G{= zf)3Oo{yGJlW@?BOvdB%*uyM%|4Zao3Y59(j-jN@`^%h~e<E@wSDqKzQ(r&^%#DYSy zPb`waY8ifTRN<s!%E&&Eo7N)*#QdcWW#njio9ZSybVeP@$j}Mn;xvzF#kmY-DzTQ6 zqaLxcspa^=aV<{jP)7ENJP)ic#19TrxuBCL>=XHIFw-q_sEFY!X&85l1#2TY+F(p= zTmk`(2XWFdWn`bofq&G7`rtHH6&x%%@+G)d3*%yPn(`{9-;^uc2oBS!z=AT<sfe6a zoDP=aYRXSKFq2!5Q)Y5Y<fizX%(d<ix0I26B4<%`QuGmrNf|t%(4<V{ru<e?!?KRy zWF#mf`&QydkBQA~d;PZb1V1vR2m+p}o*sK1hB_O&`?B;y=V9de2`Of{Dx=yusPKeZ z=i#c*3(*$6bw+He-nGF_(w7fceyZ(&3Qwr@595(^m&o@)#uM^m!&MKeehec|h&p`e ztrhwXoC^7mxblR2*a$?ZQBOqUo)M}Y9aSjjgypxeq^Jrao)EPe>4;Xs$P=Q~BH98Y zPlygeq?;t>X6f8fPU1d*1y5Lx9OcB0?>=}!w0)H0YeN`$LiB@(`ohQ)q7I`~4O2?P zVP-l;<H}Qkc~p_}05~R5C(oe8S#avl#Fb}Me=a%S(OF0xa6=fEx_G5<Ddbn!Xc|;% z2E#g9z*8<j<r($#26BPp=_YV0n9X*pi?<2agq$xFsKc)EG2y!4y~5?-Se&W>ek}cE zFW>BNKbjdM93yc?dAy4`@QBLURY#d^C(4()c&&>gF5cwg+a1<%Nx7ZEpSUbov!b5< z?&3ssPM+@Kd>5NnIFgvwE_pW>4|MSuhxP4Axxp~s|3w2{?c!@)e6x%1cJZ?={?f%~ zT^x&2i29%E;#v+noknw)MWu^P-ISC~aLHL8qn^%oG3#JdzRbm}gHbsjrlP#o)@S{> zi9@e*$xQW=FgLs8cewao7w>Q}t6$Xb-MUk9Zf5v3m*{O5zvtqQUHqkszjN_f7h9fl z!Nj^a$;Bau^;gNcG2twiMJ*Q>xwwIg%Us;T#qC`@z{Tgem`ie_dB7#PU|pGlNN`PV z)MB2CFLCizE?)2A8(h4_#rL_m+QrYf_$7y(n)Z>);_ogtE8L~j>v+#aw4sZex|mPC z(ZqCcaaR}jcJTl&!jC!_=CT;=;t4J`%jqRTvt9B<E?(v0%UsN->S$PzC^P*xMh)Ow zU3`~|A9nFB7w>iP85jTE#TK48qXBaTY?QgUH5@fGb6HflxSxwhx_GLK7rK}WQKNod z<KmlLyzLx^tw+xptfyUk%Eh0%_^gZLaR-S8#<iYNZtCI+7x#DZXv0qZv(9%}@byR3 zBd(5&@>v&i!D3Y2*2R-u%%yfw9j>m6@=q>~3C5qZNHwfKorI_564V78y<OH^;1=~` zlB3#mvMOvM)$t07#MyOZ1jFNcawCUtGdg<BWL1i{zK_8*E+=sDi^H>yLgEy>lq}WV zr>MeS;{C9MbKZ|5`y4MPlEwQuE}exg9WKv;cMromTwZf7XK{%Jd(2U2FjW<{m+-!K z`DG`b3p?cEOtOSs&&c(aQ&kUyaST31J%5ZgrP`i`X&~|ZO_wJhI}SU*+Ar2N(uQe^ z+0!tgQS2nMBSoe9I+rICC@OKR&1?A*ePkM*o=bJX^mE1Xqf6^oa;D>=CPwJdhq^*? zsa_0c#S(?C6p81($Q*0o80Dz$foe3i7aCRl<#d$^Phw}BOXd;UNdBC5v^vi~(O2sE z)T(r51TOYNtA^wKCUT|TKEtHLJ|D`Zy6O3-1`?N^$xx6u4kn9yxJy3KC7(v-qZ^KO zMn`XkchORQ)TR1_v369SbIA{q<%#=qa;5(5e3MqJPb&;dWQtSHMWz8+9;!Q&MW-LR zwiCiYaH{ZVm(EnOBx<HhzTCyD$$5@H;WaQsN95~WN?TlfH#y&Na3A%-4PkuDrL&(b z0UvP5Uv|k~bIIRz<W2|nAq^71Sr>Z(=i~)0?&RVs7cX@2<u2aj;s?m3PGTMjApGcK z!7f-t9}AvwDIFn8%1*lYJ(tcGF8MDm=AO1_U`b^0Cm5CYMMQF377bn8B&r0Rb}sn< zmwYz4z)8(|y)`bB8Q$j-z3JlY(7Cu2lP`9hmAT}7T|Asz>F6wQ$;0H;j{FLjd?R_4 zOq1N?vbf8|yIj22#Rpvcp^IZv;i;5XmW$iDc#w;yrLsiD!7`V{S{HA1@nbIjn~Q&T zaTaC~qJH*taixo^qRbjSFKPfUb@7cZ-s$3JUHqzxKXUO;F3w0l7onCeW}#FMpR4i} zdYNVO)Wz&<=BdJX6ypQ1E7blLX_?g(^Hof2ytKC;^i#Q>%wq21j5a~8Pl<A-i)-n3 zp&G955;bx$m$5{hb#XCw4@KquT|CsqBV1hN;z=&PkX$JhjEhL372gchq!Da%$+=4? zs<Xw#cet3VPog?cxOl&dpL6kx-1HN5aMWeNWh+tnhc4y@ps4&C7jpwpRL%`RQRaG= zC<k4f6=ha1?gok~6}h;ci@8uHs?*NJU0mG5#b$IVxyTJbQMX)Q6Xj`OJ#Ak?UU->H zdXbCG@Kb!*;F520@fH{FaPcE9=8m6esC!*}oLp%YvZ`ArTo&B%6Ls)|QPPji^VQLT zscBi&k1SU^oNd87;7sM=2gf5gQ}ghnSFFIhA>PvV;f(t7EZE!-^!`wAV)c(J)KNRk zSF%xsau<)`b03P4$3n7<U%w$^Fv!C^$N3!I&nFxVS9rWZ#?XKVmp`f$hm%+>(1Y`s zM-EBlHx(ZJ0T1q4Q+RK~!&D0yp$%jn$gqoBvZA}9HCe_>H8_^%bQcb8N{SA3E+WgA zWhYriBS+&{`D;54KB7gQ!`x;QZQ|U363wA$NPTq2^Gp|q$#BCoTq?})_^3`fgW#h& zxgMAcUCAY^{I`gq3HWy5X5f2-n}Z(|ZUuf+xC8h};jZBQ!o9(N6CMCQEX+ymSA<7_ z-voyli}5hLBNh|EXN0GKKM_73{0kXn&r+~auH-^+yf7o0EZi2HCfo^ZcFaP*7dTJk zm{bf~oJgQY3t_>D1Tv@gIgvnK2IfQpc_p}=@ES0-%vvE-Kt_mf(aFr}QNnDu<AsaB zQ-vFVXBkHRm%(7R*upWh-E6T1w*YgI06lFDzEqg0xk|VPnEUvt(+{kL2ZL`B9s#~x zcr5rH;Yr{JqX96h9~Fz~;Kzk$gSpcogr<dyb=1Z0lckw`<YIm^fSZ<a!Kylkk$IL^ znB#xm2D#Tb%o>|32DY3+Vb)&W7^##GE*EBbw-v4f?j+34riU=go)Z;x%iJ0)+zZSb zBjrr+xEPc_4NUQ5u~-bAE_?x)cS-JqW@=UoGc{|3nHt_0Lr4i)s<V3*%)ZF%o&_Ta zXZI`^;~;1EEI6J0kJ&y8Lmn)i6pvVOj*!t2F@WR3tXwCAsdHMm7|fd_^;w@dLqcYK z`c{~A=tp7Z%5P+R8OUOL^~O3527wcWhkygZqrqvy6To%J=oy*fMlNn9%oMj4M%t{7 z!t6}D3A57-_Yy-M45P_tOU&vC!gw6FrU(bXOUc<zz+qu#^`*kpxk@+>%ysY7XRmh~ z8KJfUZ*w?oRzGYP3sw-`G^xZV39cz7_XqD2t^ywro(g_Zcoz7W@O-e@Jqx!B!Dja? znElEJqH_uO(^!;01Goi-uf<{um^WO?w}F2Vz7K4px1{_baJ=y2;AG+bVD_lgISMW& zqggRW&F)z+bF@_Cd|tCU(|}q=rJlm5@K%3eme~+t_-l<6W(BMgE&@*xt^=Ma%xs@8 z%wBJ?FuUq2z+vt}PJ-cDS_p3xX23TKGvKYl>>KVDW{cowZ0NQGyoZe2D--jqFjM@z zFzd%#WI9Cn&K6k5V0}%CJY#{aFyMUW!92mmDZ*@8>B23*HHBHZxIKq%+05z+cL6sN z?gnmV82R4=hSp-y58P3>3T$?|!lNl*v(pvK%4K%Cf>(mgPFL{NV6)Q|yb;WO8H~g& zV6)Q|d?(oKbOk>EUJw?gM`2h)MxmkwT5E-w)to-0ycm3gaDDJ*VRpTD2)6;>E8HHu zL%1W@>~w`coxt1)KtIhQgr~*O8y3$CGbfG+4*(w*t^%JBJ|BEqcoz6W;icfug)aer zD|{LFN8xqg-{RT-BNo@e;6<lS-T+P%z5yH%z6qQmya}8mycJv^d<VFm@V(&1!pz-r z;UnNy!f#mmw$GAl>npBOkN8m}JQy)mps(2;S6aPvtxEIe<xwo7-8_TV090=!JX))g zjLcdKDH1<cx_GVONdH5HI`_u3A<-Gk0D6B_NB>qUzCrcO_1Fcczm2HOIy0v)oIHR0 z%*OxT*Qu<=QQOG=NjdspMCDZ{Y*5o}@50F!EY#mbR8}_W-*v3#UaxvrzjnQ9qV&G& z;_6kG-JpK7)rI<@o3K7}<&8eCe&i-qr1lzt{Z)*v^+I|btgqdAv#P5;(76w!wT&Eo zBTa93AT6NlZBki!LvBo<#<ro(5(|!Oc&9{aO@ET<(K9w7fmwBG2C^FtL-z^`Dxq)q zL#ds9e3Po1+Y;kSx~ss+Bj-HlJ2X_!)B6u3rs}{gDo=lRATf}=3zqD#Xo>3bhhJCd z5w{>E4SOX9^txMAR{f{`<m<C=SR@YFl%g>`p<jl>`mg>;{bQ*ABI<Qr>fh=7&4}|? ze^UQo_&ML}>+uKentJ7CX3{}BkR3n5`D75|%uX^Ibg|wKzl!r<rl<lZj{#7R2Hgl| zqppKzQ&M#vmb2@2XHx>%eMe#}3`_dS`Jt$v6ZH67k(@Dq^7C@27m0ckm-;IG5Y%<w z%G^Nq{m|i{gI=<Gje2>vR$HKR!4?(B=1R~V%F$`=(s@n~gih|hKLxvE^toVL>aBee zYw8_akc8uX5(71k!?H}mYwhwYAx3|@Mb)X#0W0HBfs==K3~qS1GJYImM&s8|ciM`u z>;6f764Z-Cy}jPLGp(lHvQ>Gpq&t6Md|DbCAZ&4WH%A`Kc4Xf1)bxx0WK#t5KHBI< z`XvVHUk-0?kR0d)r_os4`zL1~=x?^F%+?%(x)YH%?p)z^aXCLA&TS_;)*-$AHkBEC z<4@wZjX3?&KZ!Yb$uP119yaJ>`TE-&9Hw|p?1vn&12HrPxXU*^4^Ef?(IX2s&qq4F zn;NbO8+Vj*s!-J+W4`kq5lyjquNQTWD|ejsPCqAz`pyBW+rQycFf2=T{Npe$>R$)w z!Hqo9z@kBIZU)(Z)J{z|kN@YqwmKHVonHTno!XvXdU1RIBJMu{pW{6y3jgqayyN{J zo^)w|K^n87JqNySAKtzM_X`vR6Fku6!=gX=kc!4!q4#g~rnaB^Cock*p~<5R=*3`{ z7nlFZi@~^iqjKW&0(#r7*nofdmAKa?I_`$*hXN_7el`&v>(Jf`_5NT=YVcO^C2F-( zkH1r8rgKn@QvBn1t~2g+Okt2C>1c7#`d9rB9OOO<u{+@nH*y=f6Z%NK6+!u<o^3>B z&C%c7?oG{o`cJL`*TV|cj%gho>GVNO|06w-F{p*8>sFtL`bW)}?*?G&kSR*N?k*LG zX?Qa;KllOGo!zBE|7P=k%NDI#mFXs{a_Xtv>WsV9)1lHtL_>Xp>a_*sdU-TTxZ0Wg zInI2*K7A%0+x!c3+!Lx!ja|q_dmYNalhKm)@iAqHI5zjs(mkF~9Sa^r1Z5*O-|5MI z>s<H|6GI1B4!7+IRp93o9X4ifz{OszUw=ZC)Zs*3T=@woLAHd3*7cFSiGD;eExzr1 zu<t~yuJ<JFoelJWCslv@tvJ2qNtLH=*887SZEBVwA=pfeC@L$J8<LZJvlW+$rOnkD zyH(?9E1=-@EmRt^&|sEbs1O0E5TC?t%Z@?plg6HbJl*Rb!994P&*0=ss38R>tk6x! zv!<aLkQIgQ<{i_ruSN9yb8mw#+^pwnnb1ak|87+?YcSmSw{aa#;soSa!2iU2Tzot9 zJG)h;T^*-?+^yP#$01Dr$!FnJ3bvPV!(O^Kxtwc9LKox53S9yP6=IXIL$4rAPl)fh zy=HrNOy~~8C^qyKViXtRFfTr|0Im{3mm~R!A+9;{g^nSLNmj;Fu=b|RW91Ab!vUVA z6L6bTA@&h=Xg>156XK`;yrDjD5o2X=yPY>>Q#M`jIl{so?bA<TSI-Xp^HVCj#?5e; z;#V&tCv&o<F0oRQ4VS0+b>ltQrQ2K&-J_Z*3<hDUITn#m>83t`qmR=TA%v7(Y7;#D zB|BXo+=JJ#^K`Afs(wR0)TK;T%#x7GW&=oBsMt-Usq7($cgj-5wu)~|*sb+~y%=C= zeZyW=u5Q<dd6}T?eGqQZb@!=mDn`%Rr!G;c`rCb~pZ!sS?zCUEK>{w^k5~2U^_Klu zIQ}dm6PU;VyZY`x#swymyZIhQOailu@Y~ZjQ@_1m6|0N2{WM-ocZZ8$a67bY-z~c7 z)2h@z5m5`Kea|Z7o1$kwjoIQ|Fa$Fx%JR*IZZInb?s9ya^=4ROP55I^tMl_$BQZ!z z11gu&<8*JZ$#PsnV^A1YsJrg`j2hv89Fq88$G_v^%hlVSQNyq)|MzE9uIg2t`>YzE z>|YY~oad13H|gu2Q_GS2p#!R{_FHhE+TDZ99}DlAn00jRAA~VN<6=GjfEp4qN|UJ6 zij}VE-ni<&9Z(~c8d+WNJp8iH#OYgKP<bj>?|VVj4!*-UkMhtP-i+%k)?dG%)|Bi; z8q^{W+guU6xgRIC;0NLBd}zXk{2U#iCp?Ia;Fs&u2i2AK(}{ZKA(a(0TK5|*&P{Z< zTyH$22C5PIqeH65ek)%4Uqk`t>dr5!&+M~4U3yp*m+-Mj)$}q@1Y(x6t4+soFKkuF zuAruu+d<bM7vNp^uqvqe5#!SM4+o7+EQ4uAVfSHmuUcF^^@!@JRC)D|mr!Zc-TJqe zRSWfuZhlOSz~$OwssJAXdH9$SenL}wo%D+85;SicA~rw$brdbL)fip%ifW%fkrCN! zzl4y!#I3l)cg((9?FM)(9fVoM4$oBYc}00*3NK<=<#1wx9RVJ$tEiaE1||ZfKX^km zEobkh3fdycA~ywC!~zt-yY#A<``Ja%Q}=!oUm<9t*T1P6s-=3*o2s_`NvwY7O;n-& z`qwvAt)|=IZF<q9JXF%P2tKEnk*MT?6yLR`Ck@kzp5{D?cw7CR*ZoeYg-KT<+`tmX zd(dKi_=Fl}pGwrlZ>a`$b*vuvmP*SFKqF)1J^A9ZHE<o8i|-J<8hnvn{gx_GJ@xjt zRAJ3Wp_yuS=G7{IHhYL1cG%VsfA!~YsqHo6Scz=w0e%?we{X}P`6g~*b;qAnmkhll zHX}w?-kp(J{Y8p>am-)dA~`4B-kOeT7A&!UpAminsf@lK>V@)GsMtIPp}|Do11%$? z3h^+n7Fi59%zZ52@VBfqsQ)}#v2k$r1II~nw!@dOdem_Eb#hJ4+v4CIKKhR5S8}eS z#IJTl-|>XW7)SEBo}353(F8@OP{cf*MI;qF0UXaEVSL5IA%(fCf;k#^S>$cNuiFTp zO6_1cDHavr_l3KGKN0Q?{z|wK{Jro{@Xx|{sIsul)%ZCT94EXG>=#}MP8GhI>CYAe zYh7*Od%(rQyTB#FFM^v0zXawZHxuwOm<v|PuYfxVp9BvfqZn8sBZZlfRp2l!3SgKb z7R){KMhx;gU=AOsQxANBa0Bo~!VSS()JmPE;46ihqa3qQ-VuDga3}C4;jWxFyiE)} zV6jb@S-oAjADCM^=@G`B))T^m!25(*1P6qNgI^S8aU2uoJ^c;giQrR)k^fU*_&_YC zgFh8MAN;lOZ14}lE5POr8X|Nt*t|gluK}AkXy7Zr<_#M78nAhT23`*~Z_vOTIpvx6 zMlfg?%o{ZDO<?l|4SWmOyg>tR0h>2y;M>7mipyNN3(QxzWY!xl#U<Yl<^&h{K`>Y1 zk{<?hB`!J4%EhI)G&~9BQe5&LFqh(z_klSrMt%moO!xqJrSJ>jHNvc<oGzn2E9rH@ z$G|rTzY5-LzLX24w_vzKEKY&%6@DMgFR0L?GvLRBKL_)(Ka_t7ep>h&@bkjofsY9P z1AJWgSMUj8k3#vM76We!9||XdKNn5`e=8gU|0v8I3cm^00Groxh)`{CBAOv1R|Mt^ zA-O&{Lzuf5_@ou$ym1p43dEuXxSnuZaAV;LFdrD`QD<-)VQzb<5bg=?F5Cy)Tev@X zG#P^f#MheY;_z%S#KK~}FnVC?5;D3|9#^_}oiO5IT`$aTf0J-J_%>m7`&^Vve~Q7| zh3kTMIUKg?!>~sz8iAh`W@qxeFy9NjMNR?Wc-O@r38M#gK57dcrt<G1XTrFqg>DnT zzY8NXtQhm&2o|`xTRvz~DFe&}E@a-UGKF)%oKc~?7Pv7PcfWeza^X^N8(}7(Lby5D zeAE{D?ZM`ww&0Gaf6iBJVdw-NE)Keb#|mT8)qG5bfsFy1kJ^G~fftI-9Pl#XdEk}8 zyz#6NUIJb#yb63BI80C3i`^g=mx4D7Uk1KIm_66M!tA+r2xH2?dQA8R@NQvtVw_)~ z|Gcq1FT5FiM0gAP|Knn~7Zx1J(gAy})56=q9|}JP{#2M9*RN#MKKA*ZIER@-3Bpz2 z6yZtWbm6Jsnud}8%*K4NU^dnjUIcC`yb|16cs01AFmtP$@HOB*!t1~Tg_%R=3Ev1F zBfJefF)W4$V3;n<{&|k@qhRx{52<_tyh7xA!Iua>4Zc$NS@1gHgW&6hUjuIveh++` zaF|``HZlAN-Y$%%L+4Am2-pKQU&;k@gY!PoVb5s3lnXh(zWAcZ`RsE{xDNOY;fCN- z!lmF3%$IWExG4;uiUk)hnfHf~w*>zn@;2aKgnNT+^gt|oZuW{79sy1k9t}<to(!%b zJQtiNyn_9I9Wh)9i-y7*z-7X>fxD2ioVMP}#g)P($ho1yjlrXY%fRD>+k&SGcLL8M zhv6wlI}5~O0C=hJP_TKg2%YiZOGVC_e3kGN@Ot4HU@bfwe2egW@a@9v5AG3O1`c!b zj44|K!=u8i$xjNiChr%%4tz-X1~5M`Mz?J1uL|D+{+Nu;zX<%LFmvKN;bvfNiGWVn zEXiTVOa~k^`h=N9Tq{I*S8$eaKQKRSNcmuJk?>e>1L0}lGGV5^h46*ocEW7BofA<0 z^yn%WdWr>8-(Q%$-VkB-dLxCI;woVd#ij`F0Gn?!!Ous)^F_W3e1Y(O@P)$9Abg9n zd0c3a1l}l|4!&796TDS87ksyH9+=;IqT6EdPT_iBPTWw=Y~L$f4t`F!75EU?d?~#> z3@?dAFYtThn$82m$HENwOW{25cft(ptZ)M`mqpNRLtv~hBatNB6wGIP>a<}0pCtyC zeJ$b6;3DDv;0D6Oz-7Y2!7YSGg4+p?26q;o0PZQwI?-Qv26(t(<o`?<_%%evi2eU0 zVOAV|Ly~gd3+4**Ho91NIru{1mEhIFtHGQNrCZjUYlLqCZxCinxhX7$J7L%&yd8X( zFe}vk!ViOY2(v;xL(W0(2Yx}A1DThEGr-)EL!B(}JHmP3Gs5BeFnlJ4#^7&++kn3p zX3@mskvqDsgcG^sG|2f$6*4Pn4Pn-mJmEZW9bs0|hQbW1sSo8($4y{pB^Ia@Ry$$V z(n>PMTWlReg+t&`!c5tCVdS<oRX7hkOPGmVAk46q2scCc)|E8Wb_R{txOgiWzTnTg zTet-LfH22;JB3-R9~W*8-YeV|{G4!m@FC$|;FrnaJdFQfcwH=pfKLjupZ{2x74R!z zRyux=laX5m{#ke}SRtDzXQhi1-U8-_swlq$oGQ%v6s{$PeJ~UYKMk%g{2aI)Ip2Bw z?kqeM@}9!O!Tp8DfQJZ=1CJCQ53Uks!lpPJHjm#k#e!{=)3FR}F8BiB`QVF$F92U6 zybOG$FbA>ggs%c$FMJJnlkj!m+l1K^w<V$cqicJ%i^Z+5ctm(B_z7Y5^ZSI^Tn`9u z1HUMIFZh`7KJXjD&x2119|V6Od>Y|f{GcKu@gDeV;qSmd2=if-Q*qQu2FD8r!1%(q zk#qRPuNYB>52H1Nxph8IxB<A1Fo$9d!C^Y!(`Zw%-~(tY;SS&q!WH1I!d<|<g}Z|X z2=f7Sm@pqeM+*-IPY~v(!lnsNQD}d&#V`XF3x)aKZJF>T;FZExfY%6L1zsn74VbUV zn3#27zMvv&@V&y^*S|xUL%PQdBmeJ!VYgV^1%6uie(>|c4}y;fKLS23ybpXr_!;nN z;pe~~3jYoKx$q0%Z-ozme+-M^B^Z7aego`Hc2aNxoGAP@I3WBkI79dgaE|cT-~!=q z!S#f{12-1_0bDK|{t<>YV)zwYA)ILAiB&iW+*g>N+8!jF3g!+)W_2cbtS~=!FiE%$ zc!qF8@Lb_m;Kj-8|KXVL6fP8t_TbgR9l@6icLHA{+y%TrxEuH;;U3^E!o9$E2@eL} zFFX|du<&`D|J@~qDp>3m=Jyv~A{U{vK~sEHcq8~NVGVv)n4QT-!gqte5WWZecj1S? zKM6kq{+%2~0M#%gq&R^+4o(%`1I`s@H(XcvZ{ViF>`Yn<9|l(lzXI+d{5qI>G?|#M z!RHBo3l5JL!;dhWFZ?@rk+4FYSSjoUUoIR6zDAfcVH<>V!8Zx#fwv0tIdGeB8F;(H zVXHX|e6PdUwF2)J=Iqxq!t96+3bP~P=1uCeBYIt!Ghru%dw|~;?gjotn4QvB!j<6f zQ&9f&XgUl(i^UwU3OMph!EwSjfc?T-!KuRRKeB~)gKG=#1s4my2rd!ki?t@g$HOqR z62ob5N8yjb-G$GB`wDweF$W3r`<larePDh?nThd(rw9kYvxL*Z{FE|vvcOBhVH((8 z!(vegzEqe?XRZ=v6J0Od8LWkefNv4ztK-{+$ARw^<`+yJ5?&3i7QT{S$azW(*TUji z;SJzJ!Z(7C3G=fgZwTK5J|(;h{DClEXniWY8~nBKe((>%&x5%gHdKW2KLLY{aWiv* z?|tHh&w!JKKL_)>d?tH6m^>0r2j>gd0@o9+2QC%ntDEM+<>0o$t-+ncV(0)vFX1lW zN@2c|8!F6qH=~5dgU1VVGt*SzW#C!DT*|RP_)_pv;kDpsxb?X?X^mL$mCIV;$H3PK z?*U(5tsb_Y$*`YYqYpf9_gAfS`U`fY3h2qaROm->vA0~IV-MQ>?W0%dVYsRR`p$!} zy+MD^i>13Ag3|8w`uan#oU6~!_((*zcoD{i`qCF^yFtH3V}&k03^&8|B3$gRuh$0- z+ly6Fb^9ZBoDJn}M`1feZ#-%*Q8TswWthtJ7+mbnKg0hQu^V84PLs}_RQ>tOcEH~K zCEljnbz(YAz?j`Ez0&QDLH^ww-TxTmv2)Q3xxh-Vg;;gaw;Z$U+Pf0<0odAm=ISqT z^<Usq)@eKwjYR)Aoa>|PEz5O>SKz+lV%)TxfB!OEU;T>xr~m)bs&$KU^Z#GG)#|wY zS#0<L_@F*RwsKC#eb~KW`ePl`Y-nH|R6Q>S1b_Uylbz@e@DD1u-39-;;!4=re9h>o zQ3j`29JK;<6^o<H|3UG_#L?u9`x<I7UI1UQ#U^^!QCG!pj@2*M45WuI#zd;O5z}QK zg!eI?zC><NkR?<L5n4>_U`n%~8xwaiaXEG47Xa~pFZd<_%d7Y$DtkJ9V(Zb9ghj2a z*!sph&T+*y=thTZXR%Ef;lxt-p%dP={b6=7-neFbUEyDhpSbc@p#W_zgo<m;8%5Ga z1dfGS7e#gA+Yv2)XZRi8fw$Fwl}u+G5~eHzc(AYw?&G^~axlP6Ti%2gyTHN6Ahv>h z`4t;{%VX({Z`+08Zb(H|LbqR_;15C}p%-<rrV2j^eHcKRWuJzdgubuC!lP{d3qSi) zND{}MrnT2Mf*oX#|BK>FE65)BgcY0wt){`{$o-;V1#IBvRk-oZ&4xYPte;0WYtvx0 zGA3v~4--5OqWxIFqx+n+8}zCRAAEaP!KK&#JA(E-zZV>zK6CPHENUPp`g_vLql{&e z|7XPB_X^pcK7aBQEMy}m`}6dklXi`80X(;Yb@8Ku@o;7bZ%5dk;3|0S4UR)ZV}cwr z#|Ezk#|6uw86V_+vxFcw6eI>;gT62LDf~&Y0;>_4*FSFwbc2;lUyzeED#+J1cJL*5 z<O#MnUS9<V*f19BT|s}D(Mf!v=uK{ZGX$pOlUqp1w}nM=`_+&q9f3z_$-PP-@jr*a zl1*V){)fo@m^9`81o29)WLDVe<EBrtk_VE#e!h-N9!!q)^9_0Oh(}t&5bsZ?|D)(Q z!Ecern0!oMFn^+zJdW{6@?&?Km0U#*Sa!Mgzhjp-VeRUf(kCBQel9Ia>Bn?fe*SY5 zhqL^AQJrEUR_4#r^WU*c!+aT*GLXTwGR2cJh}_!05AjYJMsDNZfM}!)C%5$<p%<f> z<aYjfl#g8nd4-?<yCh{iquSNa+2WK5)bDO3{e--Y4|L<cJ5yr=-DzR@xpgSeqXiAh z-vllKJ?Yv`M<xY&5xsuyAPe*+$69t{I0%kn+qCc3!%o|Iel7wDm4)$}bSO?=eA><r zn-|K>v!N94{~MwgYQb(I$=?@_LoK=EJ>WMRRa-IIX;u<nG~|WaasjXZUN{T2BU*kA zy+iFs!V9mT!=_LN$I}CpcO)nI=a4JN0l(R}*eOgyn&14F%Fg60zll*7at;<YZeeV= zx*{*sov)eveEtvhpta@aB9%~2vXk^sFLJySPH%FO|L+X54>{oP41Yp>$!Y$E<bLTi zWcmA3sedv!$IARDPFKHcH*&r-cQIQ-jmz+(E?tSF*I*W_HO%4~dx@8=fwX3gTI3tn zQsY@F-*_GI45c@*Ue$ON2~nFFT+TdL<#I2Sy5nJB4-kCd7)ISS6)teZdh_+f_w44a z=Fx{S>PzTln^=rtEV9^PC{xjEPq);#VmPT$MAa&ym3Ol~`kq~wYhqZ*81g7A#7_dw z!3eRat`59!H?mLI)g9lr&$Crmt<TtnYO#Luj9oKe!aB^b`1IFov;Odm{gH~-M?SO* z8yjywp|@LMS-@(bK4mpH3}cZ=$Y)H5XZ@CNQK_!|kzK=nHAc6^6?+$kePsXE@M>m9 zisG$J-GYbaR>sd1MNeCoQktfCx3JpmReI&ec2>xQQmhzE9&)(d-dKI_$M$#X4Snk; zc6QiUw>Q>Tz`BFkLf&4nHskx$ZThoNdYJIwshMw8n@aJx(AGHYVI1B|hpe#BG#`5y zY!&edT$v{2tcNQ)O8Y+S+#EsTT=?SCEkCuJw9Y~GPnf6JD|S-I<TUdyEbcK1aM0Q6 z!VQKQMSCe(1&PlTSEtQ->!)^_{cEhQ{?zVizaFQtPBE=TDI)Kyso3Nz1HexZw2zOA zR;MQsQl^R4blTiTzgQ`)PAzqx&+J;s{GML+9>sWe{mHABKo-6QvXmLm(E%H()#Z95 zE^Fj#6fib;TtTF3j9@M8QiYfXXK{$_qbELgNRC#gYLr3BG<w00&G=0J)TNM~FXTsN zjORXfd7?iIPE*cL)@h&Hsj5+Rz0d7t@o~Jj+Sc3u%d7FK@gM3-W2?vgVt*9(mzUpl z^Lh@&*;p7KO7av1T3J(Oj$bfs+=7Mki<&nnE7#qVJndA|>Wh;+(+k5aGllf?C_@&p zTJWfi?1?VU<I)s9uJSP7Tu62JLS&IjbNEhjy2IbWPu>GDxoDjgHcsF_<y7N$7QtaN ztDhtmoLpzcpi&_?OSlZoXCKPjfQy7Xg83Xoc~5X#G7>;G%hSO9!97Gi5Zq6g1I@vn zu;XAT3?sy1JeXq>dNdI{S$I15eBtxK^MvPt*$Y#j<5adT^5tMYACa#Hv)PlkgRd1n zfbgx2Vt5(MF#wfLg0~8P48B|VYw!cYzkqiN*G7|gT(~ZHuW&Q)bHc5`hlD$VUk01S zdDCEcT`V{+dQzAp<oAV_f<F<y5X?<&jA$7Ay)frRe-^$DtWa;Lvk@F8yb0_V-p<L{ zR53gT3;s_TI^cM?0U14S5mH$uTncU>Y+m9B^X*Y*;jZ9*!acx4gjwF^V-N6?ZxhBF zIr5*6BvVCc9N2vA0ZP-r3q;QHHXnO{d^XsusROg@&Bq?V3&G}N58%aM^RWl;g<$is z2QZ7<eCz?d8hm@yqsw71UweQBUoAW+0pAKXAA5j&E13N%bL9@OS&|064{VmCfjOaP zmZX9Afz6UM@YCQE;+EYdA1~-n_+1#xk~A1T2lFX|7T<w?C8OQ90(;QJ$X&n*!rj0r z!ac$1!hFE2Da^+*j$!Gx63j;oGFx0D^HB#FSRVY0B`sJ4t%X?x9fg^_d~%`=v#yWu z2Jk@PP2lr{?*@+%W)4jheiqDo1^qe70+}O*W3X5xd>p)7_%-k<;WxmS37-OUm_UzC zgCoN4fz4MYApZb-tH?hB-zoeJ*!+)n&WZg51E28d5$8h9S0=zQ;3q}S7c_i4;c}F6 z=pPqu4K`nyfShjvPm7#y0?k(@Anyn^Uzq^2_`VgLKH#wV%mggP!eBl#0j>gj(VsK0 z31IV;3Gh^KK;-9xGlb`WbA(rc3xwBz>j_^2Hp|)IPXt`<$irskmRZjRi><KWlPd$h z9c<RKfjP%**0X^h0S^+LC%|So8|19vW;q-9MeroiIRQ4y*&zQI%-whN{|oR!vp5fi zuVA>07HI$+SGzbOY(svdFdBw+i!d(EQZ?SzaG0fP!e*%&m~PEdH89;Cpj&XPo|luD zSG}U8=L@fDRegRt&kMF%tDAT9RATSxrMTG7x6`k6^z_HnQ*i~P6?zdbt@Lxebk*sd zJYQiFET%I|GxgBUo+bDv5Qk|RpmV$6;?=XdcuLeEvw`mZE}npW|0unui>FR(_qtp= zqd)E9DNuOm?CPl-)4eP@N!7QjC!j9UV<1&|`cho%yUO(TuAVyn(Gx9e3sTes2`S|q z6}CA1O4qya#Cu%tFNrU-f0?ZNck}%5pLV}a4rIk}imF_%&kEF2-K(GO=BX9(eHKEM z-{wQz4(QL$^W?-&#@rXCqt4SQ!##BZO;TWrk4eBo0j8VwC+Tj(JzWdd1v$1o524!^ zLtUniICC5m%W7<2ukRb~DM;p$4$Kzu-=W(7NY-x+_te5B^|Ql0?Tfj><Bz!?e*849 z^)R%sq@n2fF!ysS*k7hckMPv<Kah;!c$a061YSwd>qmIT+pqfccOyJ`weNw$#1?eu zO~W>^#FoT(JRI>YMpCwJHqz5}@QaA8Z(a_@LIM9naNwIy+cf{1@YlCs72=x(7o68l z_a-${-vWYr;l>K?0Ak`K9?=gjjze04y%240Fir0t>B$dIh6h%VUvv!zYa^pB3Jyj_ zuAo!v!eAE<daxje5X*uJ@}<F@aC|}V6l&g*;2nt0;vhfFu_(xeDGP%f7%vE3g7TOj zEWq!)Ape#3T+40&Rlk{bN_ra|M<Dr$&*7<mtsXzhlWFhw>1CrlZB$r4I?9t5=F4am z<Q)%lJ@Ca7{0S0ounT@;f~(QeVuJ|?DK2;bI`P4G;bTJZSEM8{coyFJf-}LG>luMO z!aq}8hQ<<n7KyWhi%>Kw$bVXH2WKKrJV8E*dxP5`k3kNuglT+SF7nKN2k8wq-wRiP zG?=}?R`1ZCIjA94umyZp!AB9W9lRQfo*?%Vc!R?si3##95gYsgnG_fN2O=6DtPM^G z@-ZvXva9r?qdh&;a{cRQPh0<5q%iaY?}p|6^L4i|o>Kcvl3qN<Q>bF~O=CPGlTRU{ zp#t?hVm&(hGHs9bOb#zbG(zR(sVSWOI2D?k$Dozjg-A-MmEwTnlI(jBVyLw-tjR7y zL__V2+U3~?>87JGtj#uWWGakdUG`LZ?HD#>bM7qE+1T8WUBak#p>ODMv#&srhq@ZS zH)q$NRd-|9lHHS0=&6`@w`C7SS%mr;!yVa~NJFU7sNI#l93>eVq)tM%ExQZK2is0* zxIg<0eH&^FJF?r-x8aHv=8<gf5DSgM9xCYV%J$N`Dm4LV*`2+c$(x|~ot1sr{1=s> zN$MC3&t{LK%@nm3hUc?yWI)r@LomFUZC+K*Gs!!e{Y*eVInGmzY=3tgI;{3Op~|yD z<?G9;JbA^JGT=2F*d*PJ42lok$|(5FH*>bWij-RZ-{SR)Ri64N*dMB*1^Yg=Sg;+& zdrFn9XOH)EOj?h~#d_a>jeSTzJ|00P>UUt@WH)MfT6Qr!OM=2ZxZ0yBs*!-aw)uWN zt;Pgktk($smZ&>U@HFVax4T|n3%1SRM{K&m?~!MLApYgCm1hOMK=Qr5j-S$+t5(n$ zkPH>%D*`*%Oy51hQ^Y!Vc!H;(cscy?^*awvlKfl)<?BBUY61Uy@X=Sf0G#Fz=(LHR zdf8m-=Nm+Clelar;2ZKF9QfhW(21Uc8pfyL#wW|}M{h^Wr?*cg>h%*n8O3Md#y6$| z;^Xxj-Lce-x9ktl+<fEspLgv-{o+JqPka6CM9+wc=HE~UFGBVQf(=l!gH~WHiqY#^ zxea~=xsA~Zmf%+f`Kr*il2RF8-!+&twfx^g)pu<X+*$q%re+=4_OrJ7)|0*dWqSK0 zPiD<+$VA_UHV`HG`A;T&8_5AH>9K%5J;{?%=NrcTCeC{!?x@DTo9RA2&CGFcA}9LM ztL04gR3JZKf4ihpPoIo>Fkjz@i@yM|^W9Ici~RZe)yba1h8Iw@<2QKR)z8Z7duR}x z_e6<LLNx6&%<_ll0Fxd}(nV8{&9wJbd*R6d|Lu(HF7iPC$ML#qiYKGSQRJiV$yG@8 za6kX0f^YXJl*MTOD}KFhil<GtIJi+2HXSLx(a$Yp26i?AtJW&oeq$`V0c$@@HDk_O z1aH*eDb4GnQ>J?A*gvM|mQy{G@h@O*nd&K1i}aDHo}NLYH<Nm?aBSsQ>$=m7?eJ-y zo>1C4&C@b@B&w>~9gm__gX=ERA5KFDnXMa7$Czc2UNPPCTz)pn1pn%I50b!vRmoQL znD|e=oW?m#^CCTQhNl7k>+v-+JRRWn@C;AwU^`@vT8s_P=o4_CYB;j`*BR(oVVyq{ z<uFnYoat$d-Kr~RdPd>@SHC^elMTBcW=5TUYMk=_ls6oy>&)^@PcgZZVsgi8)xS`0 zp5^I^e|7f$EKfa^pp#~M8r1xqF`ejSAQFtWW~ohAWS}1?)B|UG20{If*`8Kvqdqy? zlRe5L>>is5<L3F23WTQavzcLcz--lD!$j=0nNs@I(D-*%CZ2AM)4j&&Gf-_ed(kXv zn&KK<vOiuAoP+)-TQ8sE$wfZiI0qS&t)HEPz_azQxb!wYlzABVQ3TU|9^+o-VVlQ{ zVtw;r^Df8~goy+74oTUS6%D$JambG)wC|$BbCCtvdfQy%`@3^JJ@a3Hjaue8mW?SK zV1wB#<z*hmuN`U+%B=T1&-9v4u*N-LLP3=`lPzjf(;5s#ADQQ=ji`S)&y(F}2eL#R z{zGr3iOp`K$7mlmvFQz^21i*p4`WDyku=R4sCw80{2t6G%t7-#BZ4ON-x_BZqUu4s zd%mY<30K;vfS0Led@4;iw_#q%$?$-e+4YL!pmc#}f>SrkjJN_ZX)p<ep~}2B=3vz> z%<%W&1)jH&IoB@q)DD=sKE=xdw%1pcY}R`gdRo>r-|)WD1j<sLYXaSx%RqHtQPkO5 zm$QzGJOkn9dRPYe;$H3Wu7azd&>tbh{fj)yVcULj)b^yYJ&cDF*v?w)S?(l1A%>|L zhvx{0e_9ML$Lc;yJlTzAG7)uSn1?56%UAuXo-sR<!cFQTwD>~&)bFL&FY(k5a`UYk z9HSv>hWg&1Odnd}S!=(LphsNbnW;|b0~dIjU~B)6yfoJhmU?O>ae+qCAy$cQoAi*S zo;*MQp>I+rGl=cdN3UAysc*mF)Auj+WMyzeZDw13AJ$udu8hgGx-`@$;1T|n(oaiK zS6b`rWuE3}T$Rfpd_>P)=4obsm7s55=BZz6ENWp^4aV8W?6<leK#Xe)yqMnn?9-nv z^VCb8gy2)pHxs_TWnTU6by?@>b)Vbe>K~SS%5&p>LmjrQWB<!jx*Aiuh1D<J<QZF| zdgY^@^!UFzud8z&kIAln;3?0^+IU_&av~<P`nHpvhv$diK`l_|Q+Yg!3|8n=d3;Gm z-^rtt;|4Yf9Mi~XxI8%Nq|jyX;OlihEAZgcFjxBWFdMIt{XF=}H@Z=K5ByUpW>O22 zIqV5gA$W8pqt5XdMMlQ+;9iC34sJe{MJJE9kWo>2RFhEyc^o05x8%Y5XLQH+FJ$yg zJO(FX4kx<h`(Ac_oJGcwz(#;(%!4bxqdUI2N;|sa`!;fIM~920Ri49~x>orPmy%Is zd2qd~LKWmOo;_p{0O4ET(ZJCkj&W>CbsRR^#o5?!+>C0g>N#xYdg?oTEpkmYaJY;u zwZ!3<$qgND!0xw^!z;+84j%-ERheVpTt275Sqjl@<jlS3Hge|J&!WRjQm7x)M^E*~ zHgaZ0bQ?J{Ai9m5iRODw>NB0Sg^{-KAKS>82(Cq<65|xzM&1<MQsm{}_QLJJd{Cu+ zZ*VW+k>E<<3E-i^Gr*&S7lFqcM*c5{VX9cH0M8O;(JT<Y47^l$BRDL4C-_p~yTMlp z-veGRd>>c~KM3ZVDn|NI@a<8Ls$sZCEFK4&d3q>43EoG!G)uFMT==NS(F(2Cgi*Pz zw}nxatoMXDH}#<~i}fdRoKyd--^BnqR^d1nC~C_m%m9MIaN|t116WsbMb1{oe@RSF z*>LI#vre@6Kg_)cbW~N__kGUEoSDhYWHJdMg#am}00BZEK{|oZ2_2Lsy?2n_1`rVx z5d_?TfE2|BND&4pQUohfq*y=!Ma9OAz3cn`@42G6*ZZvX_^tJQYkjjI=XdSi_dfgV zLYDTUuoSl~*<cN|zqf)j2KqZWEU?`u*$R%rYV;S&jE$aNr(yi`^t!N~6$di{d>iH_ zExNC#*TIZ{o?Zt>vHt1#bqMr8&#!|Sn@wUF!ye-WvL_tl1Eu(=F#2BO6=BwhQ^M)s zcZ6AcKNMyyy+P&%n;H=G)H%2gn2Vw48Q&d#6fOe)E<7LXLfN311z^AM{opv^W#AOy z*TGrBr@+;O&w+!rL^uzjkuYbfn+snC>z&&0>_c#OQNID!ySAbJ8F-+me*qpU{1tdQ z8LcB@&(#^^0`Prd4(dZM9u$rG&{!_q46KA(fY%GR0&fxS0DeaJF7WfheZZWhp=SfZ zdL|q^1bj@?$ADkutpqeQ1;SgRF&BJZ_&)G^!ViM43a<ozBD@CtrSN9(H^RrkKM6D0 z^+FK%#ng>J6{f%Mvyq7u;Ztz5@aN#N!ry}R&Td%v9-JoXKY_D_e+BCUnqejagDQPM zGdL2g4`>GSJ3tdL9{{%n2N{a85P0w%nWNvkge!sv3ReS<5Y7dU6Rrj3K~%KM1ynPI z3&BBQu7l=o?pR-VWUV)IgHgSM;oaO2I4*la46%McFU-b7Pm9A$Dp*g8gEPVW&Q3?! zU+7)i;M!olX&cPiq&IDYn}GSoNb}9Xdeb&H*c3z1ySAax5v+G@BWMhS-n9)*0qb4c z;54w_wGCz<^sa3%OSs;(4Q7?ro3_Du;A&`f_+=~~Tw9m{s;4(tLxZJV@7e}4Kzi3U zm;utew!xjjoyBrju->%|_3mK3Ya84bJV?w81&<US3mz{#3CuZR{SA*Lf0hW-!1oHX zSLDgfG&BeNu<#<VKDZg`Y-Ao2^>yG)!jFSFKTNxuz}tnlfO#(h)whCQ)ElfJJOkl~ zXuJUC0y-Kx0De>WF!-GC%iwo}Uju(2%ogoqVKz{o3x5UvkMQ^4?}UG1`|otaGk>^k z_X%^f!yb$3$>2m`w(S*#Stc@s)4@EfjOHtY_2z7F4!Dk}R|gjgvmCS}2VtllgksTX z2-YV(L%lVa6J2z)9eA*CC-6vNwtC}*`+=tj4*<^+9t55*JOsQ*cqBNuRD|ge)(CSH zv{4udWNZ~?XR}TCA@FYDN5T5kX9RRL_;sqIKI37W5oQmmH(^7)EckL*J!mkguZtnp z_0NP;!Cwnk0)Ho*1^z>rNg9Ffnw~L9`LTz52RKf+DL7e}^*&9w4LDP8u!e=+5cFxy z0RVn_7q)OmT8Ig&cP+(wQ#A(-_>H8x@N6=pi{HFbypkLjR$pDhOy1`xFir4#z7!uP z$A{HlDaG%R6T<48I4|Mb<ixPL-v2D@LKn?l<PK=*z0JZ&P!CcAt)h`4hR}=~nZitf z9AO4LPncQOKsXiLRG8V+N|@QyPPhtKZ(%MM4usyq9Ohtn4>JT*$?zU#FjHIaVFoh+ z^d4p~J=S}e!4<)J4>Ooe@+0&N%qDrYaAoiYVOGV>!ZpBq$;n86Cd)xBg!z~-1N5pe z3bygKFaxCbEu&$8f8l-0V738z-!hnixGm-x`=5lXfq8-$H(uw0O&%LYp%w(aSD94+ zKfPC3SnpK^TTs_~mB9?O-m45oWiWWoCpS_v`-;eHsqpJiiuLwnsM8(2JsC{@!~2sV zpv4XEPX;p!Mu}zS{TwpW9KQvnSZ_~;IvwTtbu`2B#3`GSebH-$QPINNlT!frVS6$* z*omO`CxhwG5n2E<mU@3On6Z3a)bTK`kW&HpeN>7|wj|S?TcXYYeJ_k&-r)6&w5#VI zyinmTKmKA$ae^=%svt~<cyA-k<6&eAGiLS4>EUrhp)j3oDa;yCEX;z*8T{BFEU+~8 z5RJxQ9tui_iol$eBDV&Q6z&EdFWd_}MR){wmhdR>eBm+RMZ)92ONFO{gR4cD2VsNo z0x-Yw(&Gof&k8>b-YL8eyia%onBTByek1s}@MiF9!rQ@b3-1N%t;gxe|NRj3-eXuk z2)-eP4ukd9W2nCjz9s4>!FszfS{s%L7fNj`n1we=nAyQ2g{jWMTTvJl#K;s*1?NNs z!-iO2>xf28a3kT`;3DBV;5Ncdz#WB~gZb^Bo)v?83U>sLCTD~LI#HN4Ynm{x-81Hh zz%F2cFq`fNgxSdGt;BGMF?dweQ7H^w-ANCSNXBMi7A}6-raB|DL%1&Z1>r*Q0kGa+ zR|MgxXfOt^2zLgb5@w-$Tev6qUE$tfek7!4{lPbd2Z8mrVyLrV{zY{pGqcP_b4o@w z1r4tVOqLj7_MQpCOqB}4OqEK)XlINn!bo`|SGYP@?-+&$jD1s4=a`_Ca6>RZO~z&- z{hLGJrKSu~8}MDiObNX;7!{YH)?0(YhzPd^8?j&(G`%wz%s}g%!C>|gdS@`0otEAi z3}*J}oxxyc*;<bO=ukEUy)_t|2i9AI!TDglH5gnEyj#pO(0XSu)EQ{KGZ@T3>z%=H zkg27227_5v^v+-~8>Q=X2OMP5>8-&KkO1MW!C?FgZw&@i1?#QBU?!>F8VqLbu#p6G zr~vF0X7a`eHv=aKw*u=O!!X|!T#4;3Eq8}dMGUcUaq&9U`+y6C`+@mUmg)n+O@)Vm z^;Tl2j|A(j#NhGZu3}~~xTo+;a6jQi@ZT6B!b8x|Ta00OC3u3UZvsyh-U6O2{51Gp z;l1F+!u!Dw3m*Wl5N3n6m5lo70B<7)A^0Hd77b*Jv0pd<eo2^PORi<1<+5PC-5AUQ zbyn1wue>XkW~zX%2v-C1^B2`w3vLRtJOyuwPzd3B;UX~alcj|YU{3UrnP*O6W{pR< zFSr63zA|Q&gc-3a!i-q1Fdjxhn34Yw8i)pC)>N1=YbDH>wHId0x(YL9J%t$?y`TjK z8i0q0I(yVn!iC@o!Y#m4c`*`0-5SDd(O^q=uP_VU{le^0*OE~k7|V^qjM-LUJdAC^ zjM#4BI502DrCpBPUlQi{GrX-B8f?+t5RFvuSz*SK`xt1MZNqh8#`vaiL+~wOwhiA4 zw*>zx%;ucqI=aIe<OByP42Iwnjp1Ov?NEIdI8k^WxT5gA;0)nKV7;vv<{t#>?ZY|Y zLfw>Rz-$d$3A0gZFN}^YXmk~U`Q1}E1>8@V4b%`}G;qc!VU$NKGz)vcR&uH^Q)Rwz zQ}AM8rpm*@#o$$%k^U^<kBLT4@FwA5;HQK~fVT^e2JaDO3cV=I6yoAL#+WH|QkW_9 zx-e7d3K@Co1Ai100T1J*Fguc4!c4mFg_FR)3Ny7>b?6W~5~ncQF2g5WKqJD9z=^_z z;EKY*))2U6j}Em37m(41qRbc#gmtwPX8yGjW`S)l%qrSdn1SdiToc?+nEk~NVUDIo z@nTMT#`-!zG#Jv!!cD-7$hqMvw^Y~*^_9Zxj(Ke|&7jRPHVQM)TZLKWwh31N?-ovB z`_H?TX*mNLF9{<tjN`&Jz!%AgiUWMP6kiv1Lj5!0NbuLf$>8sVQ^CIoGt2%UJK$(# z)ilbE3+)=?$gPNjudhGo80EHJTc<j#bZ{H``jrlBU0<(mK~(EjI((}2Do1nm6=^jH zt9w6K<>0d3>W{+Y)0@<sM`5v(dJCfIQxy~*)k0$wc6VEco>W<Dpc_z=*Fbr^I*EsM zWvhx`>*!$J+^UA+2}^s|LN`&_kKvJ_y7N&}J;_Hy^#dP$REu?ZIMgaUth3LkPuIcX zXjQNt;_uI@h3g>}s*4m)Y*SeqAhuSMH^7cto#Z2+%03Rw{m-kRk3+Me+6&QKpzMu~ zSFNXas?!^x+Cx>?<d}-bs!iJFCw!Dw1)Ci?SXMV+v!fDr+26O>k!>#-if;#M7gVeY zGggfKI9`3V*%81+_J2@!*bEGD^$z-mTO0vvW47wB#gS!aV>D1cyb*s1)sI$I8=xN5 zd`b9~n&W^`yjaAXq`uw)cdpbkjjL+;%A_*t+A*g)FmUqF8sl<PQ}YVy)yl73J5TA= z%C&3Nt`*)<-!QcJ3CDvj53jt?AAeV>irX9&`n+Xg=E`!pq5RL*`Atx?T2LqUE_jR$ z@IAFLTT5=cJSDelA0G~zOX09%emG3(t@B)#1}lv$b>wMxJPNkqC|gWt9FBNx(ZM~c z)=xBFIqbgG4l0qOp&M|<<MaUB$}xGU;Y=VJ-Y@XSnMihchv9FS-QFp%<otWN;ue^) z=!CNz!{>CIhJtUYs<z#ciDg+`wmVu!{{oGp_}>OvftZf!neC3w=3e#NcE{)C(%_m| zE(W?j=yt?^bKUp|v{2jCpF13TtVmPsdESv$fo?QM{R=Nb$zp9~&zlUT?2hW2=N%`^ z&1&CHM>q2o<=y3|Yc5mGcR?DZ*6c!=sjfcX<*412N41z^IMC%rvz#;ZZrmU!W>2Bc zc<Pw_s#y%wB&w$(D4Fz|)A?b)Q?NgE3Jvm;bG4aj+-}6CqdK<R5vs2poJ)(<CeW#Q zG*=N}tTvBM&Zo#-@YR}8yqAL$ZY+WiYWE(;NH|mB1xF7&ro7;I5G!Y_y^cC<wAD4V zdXrX@Y4tJs!LNPcIIPoNYDd@8(aO-N#$yi54YbD%FZ5&HULDl)dmRnoM_`|0gn3EL z*ypHIL;JCZW_i$XHJuuJDc(V`GhI4BKe|KAIio(@=SZ^P;4k~MgY80&+Hf!!a*Rp* zgKp$-x+R=kPR9vw-aO^l@5t>m6lvz})c|>&I}Zkpy!+vFWLYxLV#{3z$Yl(2>A8`2 z3x0aCs6D;JPATpD+M#>*J7#;`KOtC_@q?*uFS9GA4IejVNbax!lLrkSFmZ71;2~3T zhuky1Zml|XN}eihRhhznVeEQ)cTIJBx$XIPX7vRK?$84#9qpa}c4dysK%E;hcJPXG zv1Qe_Z#oJ?_nmU=i3;9f^y@ct^4LNB`eo$j=hZbPju<-(Ci{)W)qCShZOhEBUAMH+ z+I36s+04(cRa!H@)_-f}*DUQxeqJeO`{d{6*C{3E=NHr|ZMfi$|I(~e>%YW1YLzy7 zNA3UCtQ#tG*)gC>P}ee)O#X^k!q|1<_ZZm|=3Qj=_xQa^W-EbT49XGK59wcZG6yX9 z@w6EegCzdA(xPPf5Eo9AEFUsai?Do%O(aG|6gXJGPcL-hkPE-JsLml5esdAXk|jVz zC~0O|Se-{1aVZD=E+b5*cxVRI6Tm6LbShJrqqiI$?nOf>5b{JL9ejsyJ#YhIj?&tb zkwQ#>uELCHPhk!ld8`r5Fc3q88HiEB^ou8X&`dVtKUD;b-VL72LJbah?iH>JUM$Q} z+QY)l!7GG|!B3JU%bqF42g#CsJbI;s&w+#d6w5cGcc=m8Xz3$i4%2w75!D&$?}RhJ zzX%tA{}Se~k?jr5w*W^9w*e=UrL3g=!?N}W8gN5j^23!?{PDP>5^gSx;$XBDMj{!V zgc-Rzh1ntX5yt3FUtvLa7)ia92>C^K^irZ2q(3d|B|y-i<@;zEObdD~5t!vsuO$L= z^u0>Va9WVZ<&@l7y+fF}pl_r=2pAt8^r2q^z&t96%#=Q-Jw~Zvi1Zd-FaxBw@PZj2 zy@eOd0DVr&U<OEU;RQ25KZrU5q}LTeo!R7r!zCZQ0;O0l6G91P`3tWTVsXV!uM>jn zbhMBbz|8wr!mM>2ge!r&3ul7$_FS0fyT<@guL2$>oCDUob72N=99%wxcMk})A?Wo( zU=}F7eh7RASg#)fHv#MQL*QoMN5#=@V7+7r>OH|*M12fc@5qHZ2A<&^x!?!DdPgpJ z8RM_F<U&{tjbmbYJ@};X<KTD6XgxB(di@ZXvH3*Q8JjPKbHU#TGXnZD2$-)2{!`Q$ z0SDTh*dR1IK;ZE+^q>>CtZ;X5dEs7QeE|f_OaOCiLGyh1ts%^q<qIzX>kA-YW+}K( z)E@!s3m~Ar5*+L#8fzf%90fYc*z0vg;EiCtt_ZvZJVwmy1Wyt^44x)@8oY#DA-q&% zg)qy?TH#FarZ9&uci^Enw7?|Q>xaNhQoVi%%p}$8hroH@V`84k`>HToM!kFpW{SY) zMZE?1L*ceyy<`YxI)cB{YmXodfuPq6fyaaOnj!FfuwF9+UI^A}hQORp&`XBEOlrMk z2+X8TLg&QDEC+M*8F>{rQ<&u}NBA+6KO;|sr@<WQ(ZWmM2Es?d9muGA?6tZHvnuuy zX7ctIX37l}t_2<=Tpv71xDlAkg!JLAO(Dz|4JI8guB2y7I=y=q%-(OUsJ91i6z&P$ zD$G>eCOjFuTX;Hnzwk`(OTvi!UB(F!=0QWRAA)BKz<T`<cro~@m|;@uHA7He1O7_X zw}H9HnStH~{?Qq#A7yWL7u7auOdL0Oz@z~+N)6;NZ2BKmF}(X9RP*yxO1xb*;eXP^ zFi%}u?z*OqJmRYI=*P*a>gXkJO?9YIMCH(_1bZ2G0^eQE?ug~_+soOHTl?#(4$1Zu zypWwthUx-Uw!DqGf_iFbdAoyks-D_c-riu{uBYy-V0XY<{gV}7YMuIl4@am)MSGZO z_E+0eVCjh>^=FDb#k$!^O-Y4eyw0b>)Jj!0&CW4@Q+ZY0ajJWo9c^vvr-r84S@w!7 zB&%AUW>>Njs_IwsQ)za<tfD?hv$O31Rnhe5SM&1eP@Sc!r$coYRCk6i@*E9i>-*tq zPP&~HH5m2rHmX!RBz0^3X5LM`MGH@iK~WD|&~N6G295u}-^?9(HS5$=fwVG}&BV}% zO7?T*yf(Tvvw|BL9ivhj+vVLJFY21*I;e^o+gatdpbNFQyyNc!?3Pe)yPj3|Hnv;T z7=+%`QJtmF`Uog{i<`m?*;~xh3uSNd<!JR|V>_+JJ`Y`R@XUFu58QX^*YWUCba&CE zdKi$%QFQ+)qgphv3(R6Qvx%L7EioIL*p0Ie!Kyp|OPGaeo`LVK_qvIee1;!gb!3BB z*!LguC`X~4?c<4}kwrX(H>RJuqtG6h$ZxWqVvY%&4o){X9pz}bs@hd(H%Q`qm3PAH zFca`6!yoTN>c-*za=WRWHarODj9Bhs490Tz%$(Rl80ETh^a!yWn$3*my6hRT{6arH zb|(H#i{%FPsj>G);nP{{YP?BLj*Wo&q}b80cTemVj2I@yR>R*3vDe@-whpJLrA_Vl zq}@=9I>h^|4F3saQq++pK!<;mI^5K5fWq=iQ#&=NHyp*X&$41K!A3-^iG*;(HiUn6 z>?-82GnQLbU9qW%iaT~Q3Q%P1K!n~CdlGJYV;@AUe1^rjJ%3#bJ!Q-Un8ekftJrID z1|4^g!c8-FAHrwFZbDchV$-1Mh<&R8G`NlUF^H~ZNCE3pre48C*osMm><HBTmF~1f zS>XOuy0ZvjuwwhD^Uds<=3?b2vRhftN2~Tlc6~o%9rI%bOyv771=Ok{yM}csN}VjS zE18d|&x`C{{$>b9OuG3o9(@w-RGpjKLy|kg`Ivn34R{hv;3X6>1t!bL+=RyJTyr}q z$RpQd8fvvg30XAIL<>t2>eFhW7M3M6`$t%rz(zQxnbujI(2@ZwGB+YJ>k>L62V<IR zVM9U&by{j+W5O6DNK9+JzjkxNI3#UMF@>P<M8dQ5wWBt-HK8uGx|oen%AQU*h(wO* zs)cO{f6=+_TG*LzC!OnIvJ||Kz;8b>z0C@6XMe)|bgjQR8@X{PVFhD1(Ch%=Xu>Hv zFxcb@vJ(khb`dkwOn(Z}YY89Ih2iEY2&WPjP?(^jcQ)ZdjPkU!Gfls$+0xE7Yp5PA z?b+D3cd4bFn(-n7yU<3ac%DH5xnmw@82oKfnqxLGnGOFuRj!p?mD$*`RY^8}Oj9}= zm$tHNVD9p8E4xY52?Q??`v+t0->o8B+eOwbzv|H1j_<P&{*<ZDvSaz5Ld?rFpyLkz zb*eWcyZ!kHb(uyq<MU1(JJ=}GnC$m+aYLCV<ba>E@ns6hu_&8G@X1p{9c^vr)_e@6 z{@HK*0!&yu3q7tJ8z!p;{D~_Ujm&jAw8FzGrH!4_I2(RqyK#SL#OgQc*hH8N#41E3 z)rk2XX^id0irU<?YQ(NaDKTRYLczi%xr^G^87#y*+Sut?&%>s-y#rQ!{%HL5b|?#D z0YAScdpo9r<NV)w)sJoL?4&XXl(!4r^;mEh`;ECd+7GAdw6)Wdv{OB_Q-;-@_Isv4 z-*c~;(AG}KyaX$<-Po^<_N7s5H+}*2(%Wws1gnYK-WIu@s?N8y3#^kU1nunfvTwjg zckD=HbpZR&k;z8P*8$bEogE+Kf(I*>U#lWwzhFCIcpgV6vE}$Ubo{)?*ZVMc&>8+b z<e+yM+48emc$bqM{y%8u5wg?Ygh5%sme}p*R|M}$vd_OADehfG4j7*O@GZ`}n#&@} z>88-TW)tig{$CiwwPc6CuDadMPB1qqcd^|RNd%qn7G%U--Bpb8m!K9F+qqG^)zrI< zPG|UgsN=<UrJU-BuXm>(m8`j+H_~`_{e{Hg9%L@RuqM#PZXVd~S*il<?MiLi(fLq0 zxY5b~HG{gJ+}WSOOnA`*ck%Pp-g{sP!r9ILGMw`sB=_*IqWU2PlYRU@`qk|A_TZ=j z6eK&gIrN>eJ=86DVciU<G9Bzr=4>^%gMFu2P95xEH#O_1KRVduQkEb^%$F^$MmKo` zMKaeiL7@r4Vx&H!>U2cEIZ2J~Xy==Et4$s4qh^iJz)p6SX`S+f9_Va0GR=zWwJvs> zbiGCDZrhE>^F)XA(Qv}-YtyAhD8*Iw212#F+J_uwEp_`YJH8E1$}k(Sfv!6NsbK1A zY1EqwkIhLL_?yH)t@|9W#Pu&BN6jfT`vaPa1~}7jD$|LVKh@7r9edbYI`u`&O@+|w zgQLuKQ}KS@s54`uSbv8gH^R=Wp)(61(wVh%<{b5Oa2}%`ce>Tzpqllx8<*o2ee(cS z;gzum|IKwj(&dm^+taSvkj2A%sXiR}7AET-L)Mx{IQJHVlF)>e#XQOqVs@*)iI$Ji zsqxS=>bW27WiKimL>rMNQ>pwD97cIeW=45_rZc_f56~{Zk)HT8S17NOIof10<F&An zdaajTGq|0uG%0POnKn_O>G(kd4P4JlZ!477$=Fp3<-cHhbqn(bW<_`1=~XDdl=;?A zYtRd$SxW|Gwb>ucNqlqNpj0fPe2(^4o7~m@zKsZ_uMExVZQr)6H=@<pzII(4;QUly zdu!rMreLDQ<jcc<bKP@kuzf5_4e4i3$Gz8A``L5MajI{By9%U5{q5IGXQ=Z43|H~N zZQvl=Yg%vn)VRTREpv?8JlGy-#;B+v_EodC`g(|+hRdp>huUo*^&D!aSvZJd)=)bU zH@UAGYNy0-O_}L+a9lSCGa~7yLnnu#Q!=ZDz8;235ZKGOer=z{^a1u0r?*m#N7#qW zr`7Kx>^Vu_p&Z1v(%oA7wdBq^QQAMRR*bas@GbA;NVIrE)R!aesTF@ja>P7oPOgse z6%#v({bbY|h_TV>x<}0&WtYw2rSCDD%`JbMVfSftYDMLX=H3!zqtj>6>gXuDLEhca z@jj*tgu4cu)0y6p%LL=^S^}%-RLlhEKSq~zs@iBf**fM?ZAROJaVX4=(RM|%NWC@M zPQmroUysHIueB<1j9twN`Blp?c-K&B;uyO*Ht>hW*eA@bYSvgg#ric`tsiR-z==qI zjkP~dbA`$xeT=XE|FCga;b!E-(36kY9V)0>m+kmapPlxxf4zk_ge|<!q(;=MnWtWR z&#o0HJ>y<bw{~6Sc^^fpZm8P(cI8z;4#Z95C4W;;-%PYU{C!78f#7cuJ7~5#_{G3% z$$a`f81j`&iPwU?l4<a7$Y|2|TY~H_*)6NL;Bs~Vzn|bXrph_D!0`ZtiW-f{<diTM zvuL9#@yEflnI2{?vD05kA#&xK$?}0;7q&&&VGfZihj}BbK$S4-Hn3`#PjGJ4%n1wi z*aTDy^9?cz9)Brp1aiYXlw32+MQq7f-SPW^Tr13rQIO31FguWnoV#Zo@CYMLMnISs zHyH6Ez)z#RFe<B&F3f4p%EC<58p2E@p2SZNiox}TyMqgbdxKjF_XigX4+VDt2Wfc} zgdU<X9^6-WGI+4?H1J4a&X0^0z7IT)j67#7d1x+~v3y7vIbp02W+c}LBa%VmaS<5H zCxscy=Y$!{UBZ39A>kq5!@?uMFAFmQuM0B*XM`E(i^B83mo+2(7ecr$8jHc73A6F} zQutBupJbF;X1@b9f?N;m5pDq1)7Mbv)K$EwHv#idT$*nRP8V(gu3WMUwKaqqqR|1I zFWd>Nr@LXf3s_HggL{Enikbf4VqvC47vV|Z9>R0LeT5f;2MY%kgpnew2agxt2A(3k zA3RI=IC!q`8So0S4>19+5oV=$T(~y)N#O$UbHbb!-KFQ&VVTJo5)CHZVc|mX%fc<e zuM0D^&Iq>!Ule8vT^8;EzAoG!{FyLQ=xgE0Y=6EJ;a+I`BFrTEOL#SyZ*z?0X0Se) z68t<^Pkp0!(=$Ew4Za(!r@q1cz<TN%JPfR-zQH5FP3R_PNyb3X^WETkz{S)6v&420 zz7O0(cp12_@CNW;;l1FI!px@e!l%GfginKK310*U=ZkO+0;d}2@kijL!k>Uw3f~0l z`Ei)}5xh~<e*te5=0?(O!rVx@TR0lLUzm$HUJ5hLW`%G<G`Rlc4dF!aS>a^xC1Gwh zy&}w6nvaAlfo}>|0pAklhScwcIqLjXm>W`!l8ciYLU5utW9*B-K4IR#6D!;q%u6F^ z=58>LJ16sG+YI5!;HtuN!8L^+0M`+I1l&+~6_2)UCIYW1Xf3=Itmo6=!E<0epAOy* z?k#3^f_W4;191pEO!zo>l<*1g9CBH#&On402($V<01i@vRc@JR6oMZWZV6r|+y=Z^ zxETDjFdM5K!fdQw5N1_8AlwanRQOKtE5g0m{+|+I05skfW>tAtn6-lk3NoOq9XEuh zf%SG=sLuo67WId~KMJ$z{w}-)Y@uVKJKMo-&8Yu-A^1gOKR8a9pEt@0zYb0nJ_pVc z{s3H6_;YY0auUpfi-fCy+X!>0(NVZMxVzrh3k$grdW%K@cz|$y@G#**@EGA1;CqDG z0!|lZ@|L*C-ts<C?+boVm?^znI5-}H5`oFPUYH%m7U2cpXM`7mpBG*P-Yd*xKPbEk zd`x&f_*LO2!EXsa3qG&+^&<Ang7-w@0QjmfTdq%pFN5_yU6^OG>r0d|PzZqe=EXgI z&<bCo46Xq7i+T!JU!n|kW{18+8C<~jKUECXg@(RF85;G$)kM7^xR!7eu)c8tW}1Q< zi+T~bxo|6RTj4g~PQt7;cM7wn^dSe~P!9+LMWa7>xbSfBSmANtNy6;cX9!OP&lP5t zEf8J=)|V(Jhd&6fr#hHjv%W+bTn`-7w<tqs20>q<3}y`UCCXriT3@0J?hZaC4zUou zDm)bYw(tn>d%_%7UK1V*{#2L|_$tgngE9D4G-iN*7M=zEQ<yQ+hdCk;bHSd-aBS`a z2ZT99ix+00D=+*wI9-?pu(I&e;2L^gFC1lQ%omMq;QGQZfD45Wfm;f{4lWjEm)b@6 zEVzg8hv2@#Ux5b;-vaA>!0`7r%AYY_G`<B-5&i=_OW0%L)2A@I(M7`SMwbe6Nu}O6 z3`Z-2SBrWLu--RZ9-SK8<ms^7|A}I!PeBS&$b@iMG^&7K6|M$;OPC$TdEtg&y}1~6 zS#GY1I{N}nEYVFC>Mw=+ga0Eu1Z;U=2K5uU8#LVi2!>zS3qx_jQQ&gI=;(}8;aG5% za6Gu0Fx!ATgb@y-v2Yb|b73~U9W^8U+1%bK8V$gGgj<4#2^WLM3Nx0Iggb+IGz(+X z6TDEkA9#uINU#!SYpXXJ!~8_>6D5|XLEynsbZ9YH?>YuA2lFEy)fHH8GzPB&pBD8E z;0wZ=z*mKz0e>p|JXqg}47)7UKZ|;BAB5jUcoEF`eD23h1aq#PoCZ!7&H$$gXM?ka znWUT<run*HeGf9YF}R7Sv#hibX6m-n`+8xB$;+=qw9J76Px>VH0&{+d+y^{JcmQ~W z@JR3&VJ7KZatc-&fENl611}LC0e(byG~55xBCu83AUqxXj4+HCJB8<i_X#tb^r5ow z>_PBxQC|vvO_)95Y2nAf7loNkm&rj`W<FgP4d&Bl!n?pcoRzU*o_!}A0{<e+Ec;9N zAlODFr}-mby<r)A3amFQgHMC?hGj4ttDxSo4B-+4y<-{tE?8fj4E_|%)5+-QEpUPG z_h7EhrTS0croud_uaz(xs1Cv$w(AR(VV*<s-eL8i!EyKiF~m7$erchjh2Sy5&A|5v zbEcU~d}*dNI4Il}e4lVv@Poqr!OMjQf;oLoyIhLCp69wy7zbgCXiNn^BRm8AyzngW zUg3G*gTlO#;+QaRp?FnzE%+_rb>Q>DxRJtmPxu9n|F4R`F+5L$Wq@7*e<}PL_#5HV z;Gcxgg8vY{0**jaNxL_|JkpkY6C5r4CAh5c&){TmkcMmvby_sIR5e?e%LA$l^U&+s z!d!(~Pq+@aP`Ej`xo}(XUF5Xz5bbW^B$Smw!m04z7$HJsXz=7(TF3#<5Uv59C(KUh ze&PDyhlC5kD}>vC*9ddK^0;sh@RP!KgP+qJ48NoA5{-e-2nlmkb69vd_+{Z)U@jzJ zKpy~~5q=1KQFs~nvhW)4bzwH!p9%AY<m-})lQ}Z^PBhpa@M9f4*ap^HqQN`BdP_8z zZG+ws4Q3mlcSM6<0_z>o;G<x@BO3fNSnr4izX8@eqQSv45cHO42v@+h{b7$k1h*uo zhv)V5#mQiVD|~S>m|d{GI2jxV))yy(naBF#WH7UJxVTdb%%hyS10Lnpn5QpJh7bec ze$glcen_}1c!e-Kq&31A<QR_&vqO4Pm>tq{!ujA`!gatQVRlZ3g&VQ`e_4cP(0E;# zh3GBeV(>LGhDibNr@{=}SHcP4Z-p7SpM}xe8h;9>f*lya&>h6t@Q{NLszC^dMlLvB zxFNW_aAR<~a3Q#|FuPHHh^M3N!1=;=g6j*jv=<8Z2e%X+0uJ&#Tv}!cznhFSWZn!C zW_FAfW{mZP$}qzi&lGjWc%Cq0e7`W77ULmd6otQcII~RXbJnww{>+cZ#ZYtblftdQ z&k45&^E)F0*9m-_3|HvTYr=Wp)55jE7laGI?+dg2xF*aL{ZwC^3|Hv!SEA7t{H-tt zBR>mw1OF-96YM}?U?4_-OLjO<0tZBWHaK4ResFo=rQmeoWhj3}Wf9mo)DYeV=Hd-{ zz#&?F;RE18;iKS|!pFh-a%Gr50q!E|uY>jF%1}QI=2|AYc>&Ci*Fg%`Am|$dz_-Bj z#L$o6MZ&*;`PG!>e+RD=woHtmg#F;>$W_8wqc2MaGi&r^$zW!UzAG7wtO*(~iv{M* z>%z>NGs4W8i^9yB%fieWy~7y}F>5{(b!H7$888qdz~2c^2LB>F2mF_2r2j$)Hd-KB zP++g{Q{WikUEl=az2FMM9CB3>J`AoRd<2{;d=kv_m+3y6-X_9l!EN-uUTCoC)jOQQ zUx53Hp>M%Mgnt0*UCl7_Gg$9x2LB13EN1wwxQJX81r+Klgd@Rgg)v+-HVW%idRs-n z!`LPq2i`5ry3S=KbQJy>hlJU1ogt&Yre_z0>DgsrdUjnHmB-)(1T-HD{x$~rPl2BO zA{zAUFX2?M4U;sJ0rm<r5HZ5l!3n}O!D+%AA7l%&C9N*p0-PsY%=W)I1w@6dURz<d zXq|-7F&cLYGZ1}*v%mv|Q7Me!!bl{8Cz;bt25yotN;?)ihSk~V%_Rq6r~!n9qQR1{ zul#^|8}K8d-VwZ7xC?lLaCh(%!acyx3ik%@6dnNHCp-vzNLaW3$3++hjn{-nfZrA# z4SrX69QcaxB=CR8HNtuSgD~^{H(};ISAfwB#|<uF)I1|9%t8I4Sw=LN><Pk5_NwIE zum?4T>1Z8cI@(Z}g{zq`{5M()mj!na=D?(za0<8=&()y^?47u{hRnR2Kt^e54xTE^ z?3gXw0er7;XYgX-uHc7-`+`>q4+TFaJPN!?cpLmTo)X~&@OI(-;61`@KwcDn8+=6g z1Mo@V&%tjBe+fP(d>j0Z@VDR(gxR!z3=T4uY)n2E4Sv7*k1*TwAB1@j=x@U1!Ppn4 zQ;6?%F5y&glyGfu8R0tMB;k7C6yc`4n=ey@Vrb+DcL(PQ^Ha+m!h^vLgt^nW1354J zNw%9Xt648$R<r)XY!8MCvppECne`vSMA0Y)PZRD4o+Er0c!6*q@B_jl!OMiFf*%#0 z4qhj`0K8dvG5BfWhrm06A}ojSg77Nv0pZo)qr#7YUlHB}J|(;j{I>9J@Vml?z#j^q z0DmO>D)<L-E#!YHgx^HqsFdqDsF4YF3Fm;Lgi)1^GQvoCBS|<PoFdGm&J^aTI!CxQ zI8V4e_>Qt{|KV9D2#rLeJGe;rZg3mn{@{+nW5L~pne4rV?*$JKUIHE_{4jWe@JjGh zVP&8_oGrq7Xv`Dd2wq7>w0z*TrFf%oEY!CO<6&$QW+Ss(m<`&#(1b^v&!=OpSlV7^ zN1SyqfsbkG7$4(R%sxC))qs7@sn!!OtM~Ugc@JBakh7!p^DAmb2x6jo9U{yo?Z>00 z8i9xP#3^-Pzq5n2|1ITt5r*<r&ljP)Ks|$pb^C()m8wfrn*&hoq1NzWsL%1RetuWg zKM1S0-&YUdi5uSDI|$`#msQn65NE0BhahgeqTYaLow%aP9fop1jW`VDcdw}f6pK~l zO9=ADkJS8^U~1!+>g|`DQ*fL_n<Mb4P_5y^p*}z2%&`uZRq;oi>DIP(s{T=Dmfaf} z^_&`V)LF@LuGSkpHXd~b5YJslo!NFL6#AQbqsMKiS{KGD>liH6U4sv~;WHQtkHK_J z)%ln+8_7C7{MdwtoiX2pp-ql}K6fG3S?aU}N9}sG3sx-qsj_u+d8qMm=R&ua=lhv8 z(Pd5Zs55Ukt7dYQq-D9d`&5owupBOaZMNJtS3X&8*T*hZ@l9uL2ES8VZbxH0BDTSr zUHJ}Vc7zMfl3g{E__<e2c+=S~Arr1SBebr=3A9^Kx3xO|rZX*>pSWH5Tn37_2!2k& z)o^1VdC%G^`jj)<$II8;MV#sK2UW9E&Vk6TCr>%k%=YTlQ_c$J9`(s7XM?0R@Weae z4HyoDuPL6m5iZ7gA5rz*a;C+_K*NYmfoH+!-QYRVUpdv-x1908yAh=6(H{Jr7Ck5e zbtC!}7hVUV-vm#Nz6cwWqAz+d{}%lUyqFk08-FK6XG49w5itWseSI?!xH68Yo(*9o z`a_t#WkmC<`TIsR&l9W_%_;Sa=v}ahh`)eHMvX56v#_(=If|B^R*|Qj$u-ZwQq<F} zpyJ`4-ayoWkHKEfphg`c8eT4#i8^u*(BZv9bvx~BU>$L(<)@t$(uW{0M)YjN&NSQ( zHw?z{PkGbtFu9ze>}hrOv@@w(d$2#s<aAj1c-*Py_iN5C+gL@Mac1EHlB#E%wNZ8Y zLP{P0&;2b-eww~nb`!$xZ)38<{5`=|kDqaNHJ?)7opDyd;>-$Xoymd9h^l|O$?a)a z!4NT8wLa_2Fw@nTv(9|8yV}f$U%dlG>u0z6<E*o}^^QXoopau6&Q-6TbGA3LRN1$k z4b0Q3^V`l!ZTV?4x;J~`hTdj~O>}=QVkq<`BAUoAaC0xe*F+B?xA1ZuUi8=~{B7;! z;lI)2nO4Py=UMgA+s@pS51|uCnhZ4`5@|S|5zkVooCAg<$|>J@XHH|T1jQ15el(2c z+`19H3K)pyrCX_npSPM}3I7FZ?*<#u`UHt+u4=HN7plqU5oJrQJ@2fP$=xH~_D%8E z=jECKZ-*{)$~zx_y&dny-#G6~_0f4}<-``q7jGB3>gmHEdAqHlWlN=Ba8@d(9qOSS zG9qr%cF#W0j(Ekb`dvV3zUWl<U2yhj-VUC)qj`&AAo>A>EynOX4TrJjo~ONfxsu2G zFkh(+Zw6giMz*|p<mF_CH&>-ybSB){2(k69JO(A7_cBAWii{=pk7@T-e@*vT9=&Ta zQCbaeS-P>7?C>5TKSuZ5vEggK$R3p0r5Bw|qnNGUEyYlBc(c@%i_Tmu`So3L=0+W7 z0JqVn4DUhJ`jWF!wO^>Tlecp<_x^|e?K0qXYvkW|ct$Lz_U=D{o^vjxE;-ZN@Qc1T zv=NSU@_xmj?<aTm{zls`&INbzjxfOoSUS3So6!70at|+0XZIfB)O#QAJ<58=*&u2Y zv>j&FdZ<OeqT0UWEX0-b55D6pied9*RyDb>VgYQY80zXf&fJ&^h#r>ove<HdKh0Jt z?>cv4#q!yAoprEE*Y%!rFsi}m_t1cyR}bJ}{p?iFyyvVE#cx06cNPL#_2bCU)%To} zOzVnUb-(O<9Gen;xUB70yW;GgdY&fxa3VtA_%&$kB*VO$UY<Y^s0#NsU2#^4(e5p# zd#@vqbo25R=Va4tr8<A;ENlJh3Jw1dwcUEpsn%b0CdS^Tt82{y^x&rvi<ASA>eZ{x zR$=vRTAiPqsh)bxc{i>@nsd#WTwR}I>pcrw^(Hb+D!qxss>ctJX2wROOnu&&Rpw1% zgAVGIYtE60pTk^Ky2*O`P&|48-M}^a+M`-uceaiD1)li#m|s$dp*I?aY_;{eGu?bx zy?z}P>=AYAx^qm_MuazdDi@wK`qmQ~{*m+dDA(7JEMwEZUCaFc@br?re{p0<Xwx^& z^Io;n8E>nOPsNuBUH!wk*!~w5)r4B^L{(UT-K3);Txo^D9VqrC3zT{6LCFGTUP56a zjre<*jP&J?>wQe534cr#6Zyd3W-?zG@#9(X-1*1fi*TQdV9SH`$rIoz;FDqXp#B)~ zrWoSrmq$|20!P34L<%rRzaNM?JNl1>>w!NP=1WJ(jX6!gB{$|Y1^*^ynuAS5lJ2(x zyCV343ZX58DAC~1ncXMVIdV=C?g~y3=1WSZ@KA7$@I-K)@GNl2jX4X!jYNGJxJY;{ zUr>2|5j}eX+)?-`aLJW9`@tnw=DY?TAZFeGm)w|h5j;lJ-vi$xd=;#Zxq$mOz_UgD zEATRKkc)|nAv{VAaCh)J;k&?_g$IG379IiKBRmSMkG6nazBe2d^+&)w?1gS_2A>js z27F2QIrwi}6JaMbJ{3Lz=8dDY{1*6I;WOZ$g)f2inqioE7p&I|gTDalHN#-WQm+{X ze+$-YhQU98xoI@kh4fEB15sHE$VYH(;XA;Mg<FDK3wHtQ<1gUQP;gICXM?ZT{X(4| zJoU0)Fh6qYWxwFrV7=@YyaYUp{TpMs6vBLAe(_u+ydJz%_!;m@VJ=!+E6hcU8-)*o zw+f#CZxiMR&)veO!25-R7a+VO!Uy0J!dJm>2=goFS>bQMmxO-@UlDeoihU&P0pAqn zN6uTq@!;=;lfc-Fix*VHJ{f|65=!QmP^WMT*eA?>pS6T$YJn4l3&0hH>w`0en}KtL zTZ8k2JAey>JMr+JRus_Ep*J!(b|teR>na=#?kOAt?k9|%!x$pW)@_t<8hC<mCU~lF zb?|KAn&5lML3qZN>weK_4%Tac(cH3HZlpT68(6Oa2Hy$RYk<L=1=}rV27?a?vr*zu zhjvGUUlV4vJT1H#9K0X`>*a^SsF&fjzOc+{sn_~~Pk{AWUofksUh4~HwKUK#&@)y` zz0?=X#z!yp1*fB|=%v2kYTycC^SF2jLWWr8+TdJaR;T*Hlfcb|`ANU6@NzIuLZink z!Tp7~Hejgmli<<9Pk|>2?*&iO3zT7bKLovw7tAWOKn$@8aUCx`V71Z9c)^#zdKoYH zL$F@P3;q<Wm+^wX1M6kHV6F$y%Xq;UI)s<;f*nB!dL1tW7x<`n775ntc%kkE>t(!P zt{>pL5(88Qte5eESyS{fUT`}2hM1`g*2{RIUK6aB@q)Ro;Cq+}(xJK#T&PxjFONe2 z`FcaH04^h(0!|W62d4;UfHQ?z!gGWRz<I)j-~!>+;MQcH{^k%g^c~I+SS7lNMs08} z;RfLT!koSzD%=h{TDU!UqHr(pG+}nrbA(w_76^|7KcE@)pZ)YQ(O3+ARCpP9t?&x) zc5)Q*47^7eiO1`6w0Z*gh%hIqUKVECaEXi&5$#?PrrnQHMWE%I!nFLAaCz1F`Q*B) zAjVxr^(k`sLgU-JZn!a_)%{LaN4rM{lmK;Z8IHj`bf>E>=4^g|vURG9YI&Ed1KxO7 z-R0_tsjE-$uov_|imL&Sz;JO7S6%yQE$^bd4zhKshx+r8B%Id?0WM|sbWOFsAE!3- zgi8z5*FE7<C)KEzE64msEkAFSQL}ov0+_aXsFy3-u2%;ud{ooU70RenRKB7HJc;*- z@4@!1W+-ASntm0hD)e?m;|08WZ&$Xp@c}hw6}%hW8^(vK*-(q(La%A)-&q!FtY~^8 z*}B$Jo$l?*vQv@Wf2d<Q?n;>2tI)?)<-ew$@(S|m>8Yn{1))d!AO(U~k$(4}(v|*M z{UBKv=r|7S<i;hOFT#VV{yF-Sry%0+&X>>-Mp*V=e7NoDRCK$zehBA%a*PS<Jkm*@ z_sJRyE3AA@#}c^BF@;((F+MVQg<eDy)7QZWPlU~}tCa|w5w2;(&*-FkI1s0U9;Oku zqdxkfNE<dCj@n;B$8#Qr9Qiwdu+bTY9QED?Muy;HoZWz%H?$eMA<^)-;DFtDH3D(7 zpDPZxU7wqiP$f7HaY=Nx;9$hVh3C#T{A^%&4&jfp9ZaL<TkN!*#r!-FVOrcy676sm z{01?=ai$UYm@P(NB&^Q~TtGU^4m1VN3ap0FnSrP9cSeB4etLk1(oGBS=&`8**5Dpf z0zB1ea-a|nO$sc8L-z!pz~701y09=Ia0<FOZ{%CpaP@r=HX=LINB4ny;F2d5f82+N zhKGH$`^Xfa0}~m_JeeFH^)Os@pJgn3o{&l%;Hnk;nT7-0gl7g?!Bs0T6C4rv6VY)5 zj)Lt#G`w~OxI4`is0!omKy^4C8Q{H9SaSefZ{RBI`i$7w5FDNfe0vBCM!1bYMQE6T z4`9Ix?1E<zfzH}#z9ZO1n^+!0;_$31M;lzaWdt6EJrkuQ6-s4z#8-LK<1jf~i(>>m zE|Z3hIOdhdXELuGasAY+<*|u==C&u+<g{pU+`Fo9pew0zQwB5HWVRoT>q`Tv+O@NB zHr(`NnQ!88A<n1f!E^!lyLjrDz2L&NxNG#U$Yd(sh~u?ro)+d8(774+DRtVI3!(FS z{8V*jpsPyjXQ|fRWPk58<MjmMU8YWLGd@JiJ+%~N#y6wKy-m({`ppF1i0$dC^#W%6 zZI>z><SJK@ua=%kCihImnep7|?wM|Kpo1AbYq6R($dzFwIn{<iuG(m7-X7%2w@h2P z2fHd+Rh+8&VAmVLZE$~XAi$1mVIaT`@pvH66Vl$fR$vdpFn7Kc;KbVp4_Sd^IQ{W5 zE5LsA2A(sZe;ZGpvGB-pE5I{(p1`vblJgXvN1^`~o(YgY#*-U}e!`P`GUsl#jK~Wd zV>*2e4?{y&Jzpax4N4A&?S5bJEov-Kj}1XgzI3W%c-Ciro1K}#)nKwB$G>LRitwTb zMOH(z+ZOztkN+v$eP`ZD(VyB~r3`glD$ldVFyo_ZBh)A0zqzgohL4$LZ51=j)iCcV zxNQbZ+NzHzWos{DO#0EAayNh(tM$i1t~^xD8Rj}%sT=)jk_(sE>R=9syJ^hAe-v^m zs=mWr6|GE5%^B`W8n7P5qFXT_JR~TIwK7Q;-0E+`W^Df-|64VOgXBPC9dPt{rOa2` z376dIx_o4nXc;-n)X&3Rxn^dl@(9-$hnxF%E#r!*){k+O`xghm=I!)O|2H!sX6NWy zp^IZ(vm^eEY0R5shq_F3ZFZ;)Ba$nJW>0msiVuE{L@1d(;YHph*EW9-b-t`rMtc4# zoXf<88LHO;I)(W;&nMgr%r_>QX$4Lc?gFkT%vXVoFb9qP5UPsCP%z(yXn6#<p)g;| z`8Gs#R(O4aDR>UJo2cIl?j^h!++X-n@KE7R;L*Z6!4pf4PGxgFO*CEw&k;TcULec~ ziU)*01oM0*2Ivd$TH)`(8-;%cZxwbR1-A+FL-}suIKB()6M<jNUnirU1Yr4$Fh^Dw zg*g<vESv?tF3fEDOqj!iuZ20@{7$$K{EKii@L%BS^o#>h)*LctPrSkdz%jz(!DT~V zKkPamfuo0xt-x4nxQbcndK}}YT`MtQxssu*Rjw)cMmK#GG&ic(@vyGcROKFZRW-}4 zxPHBi>hUN>N<KB>QH-~mV4U7xt$Gw~;^XD@C%&`P-KDNm_j5!vpg-}YDySB!JO$NX zpz2n~HaW_u@l@`i=0O=B5uf3sn>t5B{qvE3VMBq{uK)VNXWvmbzh>%+<v(Sc{X=6` zyS!%bD&nP^B-r||9})+Jy=1I)AMyrctvyitXRO8YkAV{l3C3D8VZ?fcT#h+_Vb?)g za=RYk!(r>8lEcM05IyYLL_;{l{&grg9SV}`0sOJ}Hs+|#mjDc@mh<6ua5e@58dfZ8 zA(ZS|nfU9TjX&l_{9&y`V;Xr;wOs4U#CaB@*SfOsSh3bMD1J9An>Wx#>YIhkbw?ok zrYPTIu2k!`scJmtstludJ?840&D!c5G7m=Y1|`rFque_DarPQZ1?m{dr$bjBbM3WU zRiI=UtJSz%chbLUf&RZaD?2ab-sq}j{+j@>35*>xWK6#iV@FIf2=|PbF{Ga=-sHL? zbYqk2X|MUDdh1}>gy36DGxP=g{YXa7!(SOhxnxp#2h`aB@OO-i>cij3Qv5C%?lAS4 zv1IfUdI>(6_52G_F9W_6=C*pa*@S1Y@R*kQYE7nP4g<)vtlLy{S2UyBR4~o(wVCrk z0k!E%f1GL)^7ujz?Qo5A;1%eP-Kd~*Rr@`tpilVKhCQwh)@y!s3s2O}MlZOg^5TXU zpnIc?a_)udaMgV;UYn}p+;`O1YjJApUcAywL>N-kIVvsp=ql{nhqt9I@V~CEyZIC^ zLrm0SABfh8vTE!;Smu|hceV01D&H)tUV?JeDX(D^BJ5d+L$cbmqI`J=-a4DFNc*Xh zeKa0BGQu^xIP_mNJIPV+jym~jLYe5w=E%^qA(!P0egRiZJvKv{mi}3A=AW9)+JTzQ z{_CHb%@;4!?5<jmTV`0Dx9NvVHw6y+6eWj?GYq;q_kjbj!hF(iQR@DQ@%|t?33-8f zkr;k~T15=MK#is|k<+weCAFPZEixB>N?xGYNd5f+bssgtFHnP^Uh)D(GbJxj9991F z0+lfU(Xfktgn_67bjewVFGzk)mKuIe>^S|C)$NyDnSI!x;2moX)L4k{jzyD(hZD4a zzhki@bQW_)3r!NIZ6bN(M!<D|t%qkf*ma1APs(I@(fLSCIO0mEdjsk&dCy_z=Q__( zcvQ^9Awvz<`((doG}S*KM<XpcQ5>t((Ic)z++*<G5!Xg@g_?2Hl^yddOqdQm_<9zG zk}}oqqps@Kw}!fY)Rkv8Qe}?0veUGwhqbAX5UM0j!<rB4L1YBNm$XCmKIW<(^DP}) zVY0)FKxImvqShQkvvNe8f+JnDBXzVR1ECvsq>gsvUdV~}OdMpGcbM;ipP)XQ4v|kn zE;nEh^y`^?2mTat@>N5%IPNOMRKmjJB{2!VkZ@8JF?s2@E5&rF5Alf6eN=C4IUWut z8_NH(D+Bkm)PA|d?o1ste!_y?Q7>z|55DZ`gYe&kp>QI+rVUL;tqq6&H68x7ly|6_ zC$yzbcvuMCgcAr|8@2mHiRCY~<%4Ka!j`|(makCWp?(cpE_c$ElA}ZWA066psLaWD zVKmI!+V*zH<vSq_CLrOBlo@L9$r9)N7W4Zz7zjJ>x3)kokE#dfx4~T`#;KF8KFMFv zxg4#Fgw!*9=DH6Vhxb*{E3Sq(Y<BJ|t`;l>ufF2C!@N)Z^@=Ord^;5Xs%vS$H4BZj zWhDLUJ_}><J}S3^+Z!74uIn8;wEjbv=U?|Vp{K68GHV617-Z=v5?K1Aqu}VUq+{ud z6e;;axu1-b;IA_xS@MN)2^sTu{PA$^k}s4G!0nPFmrjz|G2q8nI+IJN`O8BfN_s2K zSd*Cxjf9bc`eX~L)9*H-&c+f8!?bzM>#;$g8LnLGEu0EwBSZB{U{+vqCior`{!^$7 zVY+DKfLZ&gUIWZFm7E8DP`D15)8kaH4_3mB!2GC0^+NC#;pSituBhG$yhpeV<Nu-v z9l#v_&`@Wv?yJE)!EcKC-QaV={lS-o2Z65(4+nEVM|Vbn`36oN3;s@c68IOeK0;|a zgug^%9@s|S)52n~?$5zXz|o@4+Q4aW4k}Oy!u>gz{Y?!~PXp%*XM*|hh~}$;*@u!b zbrm#PickcNVqvDlUBZlUU*Ue>!NLQ<BZUWp#|w`KPZ6F0o+UgVJYRSLc#&qL|3U~$ zMPn&=rSPL*{qBU2GR7N3eLa{nQXJ(l_90;wz{A2UXfF#h_WIQc=Bt7As}q=I=weU| zF~<7c2^!3M{q6+r3fAvV;2vQ8?gZ`)*6&W>0bu>^1Re=?M1%v!Y}KzzP@f6buS?*$ z-~=%foDZRb2#kFtVaB+M@J4X1@Mds<@Dtz$!rQ=2g<k-38jC5k58O`pAXp#Ih5p+C z9vs0hlp^T!xxh$mV>~T@(SYl7-N;PpS)v{To-fRi=_28H@KWJq@JiuS@LJ)@;ElpH z*#2x4p*A$O2{UgveL{~Lf?p=1<zcAx`CMT9GtP@T1N4C~1M!(~Iq)~act13L6HWnh z7BQArQ)fVkrU1?cCka;pR}yBysV-a-tUsf}Jf}M9i8?<DH4$zEZXsL*ZX;X_?n6d$ zB6o}+M+_9$bnB}lz)aFfqFxrvDLtBDlFk**051@(3RYzKexq-T5Z)r{%vOC{1k{<W z&xh56I$!m55zt^V9ux}<#4%we>8rvF#9P9t;Pb-FR}OI)h#FwdER&g)p9t3le=f|y z)b9@Df61343#}X(cEX><!Spy@)ah}mF!Qgfux{yuGoa2zwRDHs*IKw5xQj3Y*GD)H z{u@I@VE&C3=C_QA!t7wC2{!}J5pE5hFU*0<Dl)#OGheyNkIcyEFWX>7X1k~-g7<)f zG*l77i=x3~JS@zR>Qk)HXCu|Zr&xh8k_(?=1x5u4pJD|@5ea|U2FHQ*mu)aT{+4cn z*-F|d47>maZsKZW5m+c<gjux`gjo*s=WJMDVXP$Tbf}6jJ0AUI8)kCA1)`n@)|Wg$ zopUHnMV+bJN^|dU|J_A2+CZbHa6526;SS&-!kxhSgeo}N2RuR4`+}zm_Xp1ml}&ah zc+3}6^-On1EPS4ghjp#CI-Tk6fSUv=WI=Vm8iR**Ghe-w1=VgUDjTZP)ZKhMt+w+K zr~crhu4-Qyk0ok7ABWV}mEBXZtbRxp*#G%1wXX{7`;=YPorCvh+)q#m7Q0t<XWQ$t zuyR4ogNoH7d^5qJs_p<*3gc#iMD<BkceK43RXBV-fiDMI!&QYGSo{{Mqt(1-5pnA7 z9Cx&JZIBw9<IalekAhK%mW&0nioTv;qdH6r#luhv^=#VjIqv_S-O8_*S4+=sS!eyK zS2g#J;8xhyXJs<SO8+btPEX0~)=m>+LCeL_)<5sSPf*cxb747Vx43oy@4$2eQ(6o8 zaM)Ztgm>W2!w-&kVBt<kw&MW^&hoRhIS1G7U>0i{AEw0tp6gpvZK>|QzavM1-kiqx z8=kwj9e!{W2LM*<C_n8#<mWikvB8WwOk+<*aqWV$QPfpDT)m<=H|8D@#gBoJ!_>UY zgobMD9Jfy$tKojiH43VhQIW&_djI>(d+0ih{p->Fiu6%s)Xwqc<5f|f`+N0K-|{J; zP%Zb1&R`CFEgA4LTpZ}7A}S4qQCN&-!fdvf#x%p8rh_os(Qd+QM|%l32lp3l3uYeB zF00JQFo*tA&)vqtH5>IBq7=_ni}A27c+~q1-BZj{s&gZVw|#1JBX?CCI;^KtuQfuE zbgOR~p@cn-HpAkyP8n6RF_br{rj4Pz$5}G1GZ(7%mk{0R`ol>HYFlHs4|V26n)(jP zHTAU4&$PQ*MK*C~n;9w(5Bmn1&FP%VF<(>jnz;Y|1b%jYY@#Etpdh^aqJM4mXKr%* zQ@%pC6)cCqn4E#+3|r}+H5t<1^RsI(#zP6_;=_MR@K7q6h%EK&Q8fQF{`@^ZTN6&A zFthNXFzb)T4%Z5p&=Wc{;8sM?baMz;dVY2w{m}EX)|)^({CWHaQP1vR*0!p4*s+8z zm{u|#Zih3!3RELkLog!uF;<aLOz6lz7^KKq`0I$g0l)0XN?>Q?8(>#3@=XZt$e$rZ zviZi*R$ssgZzLyZanXbmZaC|{4Gn8C+;{1TVUHU|EYIj3Q1NmNqi5=F+BJMEVGi#E z8jXA$e~d`|5*j%Xu33>D{EdjLj=zq`E6}u!7Eyg+${c2z@8jv`=XD6=XiT4y=fPZH z1^kHNA9IBH2{dEgha2WdopG@-J=EzUcSY`GGtB4B2x!G=hn}Z9M%lBp_XFL5>w5pU zxo!ds#cM-9XhYD@o+M~bex-IA)DpEnzp;FnU6a^d!7XDLbQ60}?XR$oQ4U&aRC9Ob zhU4L-c@27K7C`IxC8i?IK>sM5Kq*f$Fn8!!F*G{N>u$kN>P?3_)7+hEKC5mwcPGX0 z6~^prGE=+5V9W|tu7x`bw}dur;Vz4H2&zX5_d?U7u0ljl^g|2xRvZ$)uBAIGc$7YO zejDzG+dLP}IW=-(;8JAOYxo;h&DjHEku^#w@J_VITBQ^&z+PnSQVQ%JBlAlsq|r*l zQVKJ;r82T_DV3TuGO(1w%XD>UDTRGBF};++VtR95DFyaakqiG(sKK>tuD0`Fj*Bp= z=0h}cV`0iwTs3sGmHV>8#kU&E_~u{F#QeYi^&o_G?d`14L!I2Af8FS-^e*nS(3CFj zpy?emVD#v5gZhmhH*R$3KV9AD5`upso+S-GU#?3&Aq*#T%!uD~vaZTlX-D>i)lZVW zVfG<yN@jhykd6&Ja^>&Y0diSUr<LR|2lZ8ZX`+F#laVdV5gzL`9bz@9EnFU4Pnbj0 zCc+uu7Q!5^wiD)XmF+3rsR`~+=2#WK3HocQ#8Q7XMJyT82WUuGe>DX&0Ui}~#z4;k zK#_soPIaUTo!TReA#`{pKGZqZ)w2L#2J|e=z!AP_7?(-}@D*V?^pP+<yD7}!1?x5~ zW8AE-@+I??@>fykxR<R8)hhw@n?IQSwtmCMh@6q+3w~3+!7*m~4IfMo^cy~y9_TlG zFtei$9R)Kx>I<jw2Jh5Rg|Y5oF6%;hwQ#a~gB?H+YO1_UETC&R#a-7fgxnef9mq>4 zFM`}qouhn(@(C@cWkIes6*AvFmZ=GlL$jv36D?e5ylOfI27}cn)7?|8r?XYx85q~r zRNH5uue?!J{W${zgC=^6*>EO0@g=JLOn0`^i5PtCP%~z_)2;8~)P|YvEZfHGLik(H z6_~WSN4K(ynUk2H+_T(1`&4xXEiH#ZnFW`Is7ABk63_8>SgPW&<aFHh{ScJwb$InF z2rrNGsSjrTGd8ICT0*&qTKVCxwkubpeUjo`gcLJp<4?Mw`b7tlhYd!x`={HV3JKkQ zE+3Z7uI`_KYa%6w&A}H2t}DWiQE&<tI1_3+=0k9DY=M6KUh2CY?f5XQzUq2(ppw}| zrOk0a(r6=$SjJlXHO=4rQTS`Zn1TOh?*D#mFb10K)YT>B8~@wSmg@NN*fQ#gp!-t} zG#?4gp6BiuVSVpdvGl7c*6+6RpYv2TpHRo{Ppo9K(yv=F@5f5!%PP$u$hIy<s2%69 znkt|sK(w!+yq3|!Fnmn+2NKkzh5x)sa4hD`tA+c`>Z)5?%`EJ*Ik(U~Ds6BYs;0>u zUVO!LGp_QpDg*u=iSdw0jKprB!v2#boXtWCALhfdTcKK5ZBQxy9*OZ3Q;fuxsExRB z-2E!XkT5+)y#%THQo0l#Z}o=HGT!1jmErN0RTBnmXIBQIjWVBcC-j-lFt{D8ijnst zF&xg?J_Ojqwd&6NGdkSXCHU#A_Z<W;7s@-_i#SyGy@$GO_^w0K^tFIGR!i}spEy?o zzJ+*#YSJ_A${9SZ%vD4SUS4tIh^(`UmO1xi_+pX1PG5mK`iwg>m;g5tBU`*j%Um`b z*@h+!&piB%Y_|i5WsC2kC5tS60ZJ%m+}9D~@Z>i`$bFmGw)nOnP^NDt(DHqPM2PV5 zU_pnE2PfLTUC0@yZy=Jv<@*(8+`ju@E7BK%bT04lWg$>rAMfD7c+m^np1NPcC+j2J z$nmVZY>>Av8NMb^GJWk}(eiCWa3XxqG39*OP_ccr@Ym_%8hn>;I`iMh<)e|l)v)D3 zXnh4-<mBV&bcXK$5-;fE%iA2^R5&%8s>UoI+y0rp3-~+3mjw0czR!?$!D+rn;qFx5 zJVa)S?>S`tWZy&3nB?QNKKJ+zz`u#UdH6fQ#~pWAWLXAAeSP1DtC4dN4(tQwl%(f4 z%tRd`;vOZWb<~l0K!@inJd1kmMR0hpWz?HwkB3J*M+MI^6MP=7Sc^JOj*8{i$f)<p ze$Nc}74-p`Un4o7@)jf34*!IcjPi?q+KxgLP2XyS&hpKIs}Vjf=ydoxLftmJ+*#=G zultY|xDONgiUP!yls6)(p)$UQNb7CLBasqujE3K3(zFrB^5gfJEI*DomukGtoj8I8 z(jRLsg{|VaJMq_F*4%){wzy%i;xA{isP2qg3P1eGS~wc_3hktt^x$mVM8wsfWj+ky zLL6Tf{5d8!k-i(3irD(|Odhy?B`!i8+2&4aF^1u3VRHHZ&A63xr;WKB9{nEw4l>AJ zY%(<sGhxi6$%en9mMk;=XE@>Sq9unJZ>kF0-N^wavcISPIEb~Dx1&_+?e5Arc3=WE ze?d}WYcv<9qMf#Cs&(7l8P-9MI=<aq+r*uR+uixt)tIvbs;7La^A2}&>w9cy-Qm91 z+@_MBcjsn)2=}i=f6MF8JPQ%8=<k_uh9?C{5#~fsQ#B4oqnOIkKXP|KzUMym-1F{A zO%A|z^pA{9GY?PnjQ)k(To;Y#-(H1E%eWhGFFIbwpmkh#6jKq}#8p#KJKaf`^U2=n z&MNu@(T}cZo`C~B;&@babh`OAT<8<G6@iP+HcvojblEZY++##n(Wx{xjzh=jYTC~D zxIb*QY^S?s@H#>mou@sV6PJPnkIvUZFwRF;3$*dMai1`}b<OsuT?^u-F_87NurRJG z{cEU=EsBeyohDjX66dCCg<4n^#}np6SQ*E!(9zAP6Es%GJ;0<Y($1}m<4))3=33Yg z$Cu&gmRi^t_Y;HATE}H`+&+|(=y1_^B5nzN?Wm1yjpKQl(Ot}Hcsw094S62jRSVnV zlF^Vwch|zsxG(5h4>QQ>{6gFh%)tLc+<QkyRmA___ii@H?k$^y4Iw~)5CViAAe2x; zmENT{=^!1X!-54-EFkJw=*0p^Q80jrl+YCcQBaW%qJRP-MG=4R_v|Oi_j&$!{GRhW z=h*|fulY=$J2Q9sbTb_YH^mR8bG^->h}hQngN$AueZ$}Ocpm;0)6YB!Sx)>@)EQvD zj>o?E4fJS``3V%C$CsgEl#ck}_)d)Y7_B%K&%G}(W3}Q${CcE9<(LUNxlhLLXMiSY z#SigU@%Cb-XvL}c4oroRR-86G*8*zfhrUi`Ew%4M<kWLmS@WT<NVigq!Ax#h@i&2w zzL-Ufj8&2zE<r+r`!Zh3$X-+pY;pQ|BT0*x)69F}41M;Y46T_NdeBF?8TvdOWrkk< zk*`=lXXx|c4E=pTeGOS!kRBeQ%>5CGaSrAKlb|vU|5r%8*x0}LW~`kmd4n&d7Yl5x zrK4uWPoyHwTm*dw0i;#`NGRgts#BJSt03Ys>9k?}0YO|1vd5}OuBqc?wMH_;)gt?> zW3F1V!I$tzemE3Ymu6$F=VHKFWZpJd2{sGfL~i!RHaEFrI;j(iLu?D35t51_E5^1o zS%!^5r=!$^4Zg%A-m_+Q@R|JJ71lR@b?|8uMXp<_(nen$42+H1=xgBFXsM4k`YL<A z_NprzeVLwnv8u$!zN=<}3T8w3z*ViXeMxb>ktpUH9*)6r=prLZP0mK0<x|UP>Q0P0 zos9-Dc85o7^7X@&a)UPciWHoMlr>+Cn2C^AL;a@55vIeTjP(&}=_cP2&&n9pXtOWP zb2UPZ*o@5LQ+qf28p3aUJ*#?dMX82ce51{sDtn8srP)eFe&Q=-&Q=vZ@ioUG5tBdh zRWhroHJ|v3#WMSwXQEl-neB~IPph+(vV@qoqFF*HO;hn(eU&_)Mye)TeJQ2CNA@?1 z`hG%AFx!`7>LH^W8C7YixQ{s~9a`wR<Wa9~g=;KGW*r|3lG(n-$FADD)z_?6AEdsy z%g0xRB-i8g=KSgC0aU*GuMR8o%5&g6O!9;FB-MX7s^zD?nz)4axlfUluc;3|^<}0! zK+Z7Jy>#y@gsC#ivRTo~vfKb6%Rmyl+kE9cyIoa#o3EfbQ+3&fR(_OvZkw;92MPP( zHgx3csv)1j&9~LO&wQDBccNL_e*<f18^E2)c&Vp8^R+Q+s0!PCpXPg(DKOIq*Np-A zZ_dxi4?}OMh#kJNbg|+NU+>Uo3|D2H0k}RTgSpwP;$ar94a{JU7WI=<v!*et;ky++ z>NkVuxtf`t88H7H^sDs)Y{37I3czq-hM=i-JOk!3SYpj)9wx#Nsz-QK>`q@n2BzFj z-$hThU&Zh8DV)KxdY7+w+ma|P=HF4w--F?8#&$N+jcA5#7SyQ?0cYWlQJYgMDB_Ij zllYIQqVHdsr>;ZFy+1tjv~qKml7rOSsha2b(u-={WUX5h9#wvYF$=2)LY+}n&CkIn zd6GJk<Ev6ehvl>m%SGzyu$+lvSa=ks4oeNBuTdwYD(?2>kKq^CEEKH^r%|Vy>ayFH zT2i~RUb~X1UHDMDklB=}{!!E#*f%OIj>%rW+qcj(+o}e8eM2jZM$W=2-qn~hZ1f^? z>7R78k<QS6GCw!g6~SNHtA<JH)Lvgc&xR;<XD=dKMkVj_B{7BTgrC{n_hA|UGc>R7 z_kHVG7p+De@YT!1djZV6Isi{1lV|*FtDFPA8F{##%RCy%k=5#R@F!!Z>U7Z8)NG=b z9Q2in8;zvEm?x``+8DT~{EGViAa)GwRSyoLci{4Ut@ScoUm}lYRAVgHdHEF|k13jr z+O)mi%UG|VdI!}XYIRE_WzqhlM<Z3dY<#~Bb<3|<(zbZ3z6T5MrZO;i;pQoA;Rp;= z-wut8-3;=1ZyiG|{oL1}Iro8@P9!~P#yt5hLSwp-4Dx8^ovJ7BXH0SEOlJld9LeB5 zLz82WwC3ZH%<6AYZK?Dxd{Z&yu;vTj3bQqi-|<!RTy@lohkR8$YrHDwkgrA_?rAo+ z(zozHXRDej_DdAxA}Z@kUrJyw9E)wNEA`d~Bh<(*eaThy#*bC>Hf*J}pD+1?6-X@+ zOkq6NJ!IlwjN1LBuSl!DjLgQIlDQ_MmjT;OfXxJZ8N$%6F3@`IXGrt2$CaPu)M!5l zg)jDy$%N&~rTlc+Xg^9-I_#@ZWHe$Bd(Z5^jVIPTT4+f#v~ILt;#boT`{J8d#jB#$ zbZQaub1*vpB>XWtErkniQS%k*>HbQGZb-`bW}Bh8nnKR&=GQ%d4m<qn^kH9O6J9|a zDC?o{B#kfyjSfpui1OB>@CJpPV>a4X!F!7RQit9t1t~)xHsA3*N7X%o3gtqC>VCwR z=}(4M>`AkImRfkkm!9?*ZFXR^Kg_jgw98B3qr3hQbiNdwefx;7P-^r_j5T?TkgAs% z_%AzK{_l_Bs-n?}J=7010!6cr-|-DBqCQ(0>140U=Re~7*P)f{DXIQPN}JWPb6WZ5 zEDF7Vx0pMI`z;yC&YuTqk~?l&hKwx89~*zU<F-@D$WQ$JLPo;zm%$Q-{J>u)GF}>g z-y`wOJYnYfN;nLYW0>eNQ^Cmx{4SGG<M3CLl@P~2@#D21CMpg7-Y27i;O}!X$~u41 zEGI0(_@$D$!UDf~WDfq~*OQF*$lqiO{^#DbxSSfOQu+IWoD9HE-v^r#=Gm+PiiLRq zVr!z(;qNJOi7;O#mke_;R$ysi=E#m&D$E7>Ehr7v@n@}ACal2|bIr10ZbvQ`=3V6S zVdjaeW_p-;Sf*Jq%!QGHX5}z{j}$bkgxQM}G^>WWE}4rJ@SB9x44Ii>#abxL8ezUq zt{LX_NM^HEm<J%4&Dvo;PG+5nABSYkdSO<`LmV#W+gTvYL|P`?82r9)OU8e#C^|!9 zi*Qfy4&mP5y~6#$UkDEZ9}yk`=42w5hvA>`voPL-ab1|%;<hlef*$eqA^lUJ&}YdY zBcX;1pCtpvzwlWy0KE3_Su$Wcsz<!R%(GRI^ErOcACG*?<@&;Or-?A_wh%@l8@)nQ z&~^O!Kg5p<qx9(I!!$!<Pl%iz&myDvky)#fnc?*sH83-|UZVz11}_#frNDZL8ss5< z$n_dED41Wkpq&n7fw?l5+yuN$xEVM{xDEJ#Fkc_1Hfg>q_#5HJz}#0&`3Uei;i=$D zdbJ)jrbEH$J}z=%X8Bu~B_tB>gmM-HTevznPMG;IpKunqkZ=RAUh4+Cj6f-oHwRY` zZprdjMHGxpmhhusZbGKV-M}q{8H4u1lfYesr-1tjKLZ{vJRdwkcsck<;T_=T$RT*} z1r#rf#$oVl!bic}l*~XJ2Xk<gd>Z_&@FnmE!k59^OG`61!JCEefjP@bxyO{XZeWgT zhmMPe4aHeu&dpvGt`5E}Tm#I$6CJ7twuKvmxm}j>HehbxC3B5I3E{5bbm8vc8et9@ zeW9o)8iT+sghzupQcZ_Az|&KBDwsP|DSr|?Qut}GKDq_+7r|3S&SB<R!Z~1$0@Cgt z@N1EH|5WUUVzFo(0k0H34&EUA1DFR5(EM5Oe&MTNeJTs&?7M$2^4s7`!uP?~g}D~` zj&NbF*8NKq<-idr@bn-Z%pJsJ&R)g}XMq!hIb)e5+zgx|%o)ox;SS)k!X3eN$@mcQ z*9fdv>rv5MG*I%4*1{;6Mjvu)xIP~wTpaS@!ezl@g)4w331@((3-hzW69niEi|Y%* zby@%GV_Bfl2pWq;qZRla;kMxQ!mL;}3HJr>5}pPALii={G2sQ^)543vmxPysuWH8o zUjfBU(O3(<EBqn&f$+y*FIq2*!B(&(yd4}Xya&t;D>U;tI7#>jI7OJnI8FEmaOIFF z&O^cD*=YG!Fy~Ilk;pju#1(KnxQod1gW1-nnWEsq!W?}WBU}#56G>^N5_r0B7I>y` zs0kD=h=Pl;UJ>SIus4J`zRn2-I>bd+D}=cgZI$pS@Ot5KU>-9-^Hab)DT6!>%;P4= zEUuU*z-nzMIB@i(Xv_kCCHy@25;;%!)2vTf0YhZm6ge~LU11cK@I{C)!>?kD4|dT) zLj7g%G|F5qC~UF**Owf^5W->b*h?BhE6J!S%$7_&VSZj85iSO9DO>{FUYI4Ki!e(> zFX2ky{=)pyK2A=8XSJXhB^oFa#uLKzRNJ$Gd?A=HUZn^zVpzC?iCh4@SU4H{jxfWu zUYOz9B+SqLHerS_N0?zbAj}WzVc{$=W)1O%;8|lRPKpLg<Qd^E;NQr3!!56S5Aol^ zY_~+B6+|<9E4DBbnFsMwj@G1+PdEu&NH~RWNZ(NiLu?N4m;+j13@QsVmGxDGa1nln zuObA;fZNdwI1a3@A_Ox<^;Lvmrl`J(5L_5MNX(~!CzC^Hr!oJ`paRU;JS)un#<@Gn znSGQn+%gsj(}N|#%sv~)6ymq#A>J+=0eOxvJ`DImQ-SnhM*l&WF*q-b#4vsmW}e_M z7R{%Ce-};#|0!G^{I_sbFx#uVEtJ2+hd3$BA@q2W>{KxL_*Hp`GlglU1(`1ozjhC? zzD*Evn&EH<FYn`T#6vtrm}X{@`7ZFA%N|;;f+yCJX=uJMtAe%UA~Y^H1qySZhH@t9 z4&f;9Zeb*X!MW%>$>Ds%vzl}HoNxmCH-4ugC7cib6m}txLS~>G)s5i_Glz4+mU5;l zNBhZq1x18Qfq4uz<z>KSg!yW!3a5kXfkQOJx&zk(Y714s`gTCbtAX|HfZ!V7K4PX0 zm?ss}Zawe>;YYySAVN8MU&d3y?ZNuUR#YAh!Sg8xci<O#sVKTb<2~VC;5EX1z?+2! zf_Djz1MA!V;Lr=;6C!^d%*hmb@CNv*@Y~?q!VAIoH6#6(KoN!PPYcVyal)&?+%rk} zc5sUD0dSh|=iti1{1S5vo92&$^~HSPv*5NO{|Ve(_&#_*NEBRBF;tje-0{Mx;2FYP zV#_1G=>Z$X^Mu(DeoL4i)8)dw!7GJ_gVza91an4_?u7US-I}Wa?-ZU5-X}Z<d`S2$ z@G;>9V2;Amp{3w6!Yja+gx>>S6<!6tDf|KWuEY8tmbty~foOaT_9FXJz8P!@Zw1E+ ze+Etv-U&_;J`7F~J_=3~{u*3f_&YFX2k8C}+)r6U6qliqC43#+Sokiug|O*Ci4gXI zdkV*a`w1t3_1${#pa^)J$kV_xgv)?mActTm0}3S?T#39;cqn+e@Cfi)VXiO!Sa<?> zhwx<Z=fYevcwBf5_>?f0`u!xl9UQtYik(p07UqD+ePON#^x#Xx<l<@*u0$boX`sIQ z4txr%@4f?H1eX*u94IL-%z=^&;rrm4VGbGb5vW8&g9}2qpot!ErA<p=4iUB&<`Ubk z!dwca@4+hu2f?E#M^)%W(Hj2{>wEAZN9Ag~L^)b6{FJ{M!273yU%a<O17BNXu`nAB z?+Ekzv|5<om=A^dE#D+u4!lh`1DqqwFW~{<df>yt4dB1=jVPLePYSmJpAl{Y{*7Ex zT0z2Wfc!1YZ$u;nG^1NV!U>Sa3G?HbPq-+!AUH$|WuYif4Mc^O^}Tjr##rBL2WE`3 z#7r_+-)jds{$Wl%Y_}q~oiJnES-2Lsr!ZsRPq;Db{~@Ai1&xuy{9ud|=67L=aDVWV z!o$Ebg-3$*9e4Qj`M~;$J214vSKNWwL|aGmV7~4xnvwoYqV1x=SRN2g0e>ybSe_QH z4(6O39m)b<5pDv$A>15%N0<@&OSmIA0&O|k?FsgWM9~|H7~y{4pfJC9CCH`mTEJz6 znT(Z$*|)7O%s|u;ZV7HE+!@?VnC`a`4$*^-q8I}1E<6<6M|doFknjZXaN$W{E?{He zrh=ameg^!U@C)F1!gIlI3BL|r9LxG2mfwfs9nshhUM;*6{Gsq(@Fw9ez}tks0_O;S z3qBxx3Vc}j0{9!@tKgHuzrcUvoG7A9EXfrPfNu%Mg6|3^g7uYkWx|z=zOoJ+4M+8r zbznbOUs(sX!CdQ^2h0qZK}K=&f@_d@B^fPei3Tk<7N+H9!gv@x$f#i)aNmb`urTtN zF+!O2fxe~==2@gCi=36)3}IGop=U+Gvi_nlOM$-24wj36-xPT&c)2h$<0@g62(FuC z;A(=ih1pL0M7SaN5V?G~h#m`bNSDR$M1!4;Gr|n%6=Bv~zYCWH>nrQv5VDTpM^x!( zWpGfKxxKJ3i&-h*-r&l@tV?R-!TYD>fly?L#z?TfnhtX2c6~J+n7O@!m|<=oNKOwY z?=WGe+yvpG;3tKda{8t@n1@rw>msiN|Bc0>V3nz_l!Kux@CK2inlwHUZUx>U+!nl7 zxHnkeA_u#}!20Gm@JR3_F~bO47oG<G1FWwkdlCvS>O{uo1#m$46>whRx4;F37l4Zj zF9w$sUJ5QJyc}Fv_#JQ^VHS0LTO9oQkoA8%(bx!$?!w!^1B5SuhY9}<o*;Y&{G@OM zie>Jta7o}-Ma~UHxi`U;0WT7HdGLp1?q_Ck+N2fX*_Um?$ZtlDFpJOuVSX<T3$qA) zBg_(XQkePRoG?q!W#OXWUxb+_ZgKpDm#US5;%{N*gDCh&Ig6Gf%%a8763SV$5`<Z_ zN|7t$Qw**k+yPugxFc9!<_0q?5%okK8UV#3q8JQrDLfS1UU)dTi!d`(FX1P^{e@Xl z9v5at8zsz=GG6#8@KoWKz)!`q{zr)BK=GVt%mcqH{3iG{;bq{rg_)t22(JOZE4&H( zf$%5bkA!o;`jR*JbqKs&<VRTl>s#KSaU2@@mN)QO@KG^z0jzI%gZxLZzU2-46ZnFd zxdQ%K_!{`S@OAKQ;hW(5!gs+Q)OLA7aL7b%^ict}zyaX|aJ(=-JOzY{fQt&JfJ+Le zfy)VVM7FYU6>z3-eQ;gjM&M8*Q8a;~xiCj++X{1}wv%uda1UW_W$Y{b7<jPo0PqOm z$H7ksvjaL=n4`Hf!W=TjLh-C<aJR{e!tABa6J{s%P2muDk?@n?6~fPeR|(GouNP)V zHe2{5@TbCa!MpO}{WICQd1b$7ybk_S_)YLv!t=qG$W_AM@2kT6eBTuIgYOFS^L<~K zbx8~=jyx#aUT|Jv2mTucMG*iO6^;d$6vo3SC!7ebEX)e0ns8xoGjg@?h;JKVwhg-p zHwE_*W<4<s9HNDOP>dA~)&Y}*M}wyezX+Z!{2KT*VSWqV7G4fsA^bjgoiK~&7UAvS z9N}H8{||{`H#ANN?*pF_J_x=b%(DBl@CopB;WOad!WY5!g<1Tf^MzC8HaJfB0XUy# zq<<vdYf;f)@k<kCyRU*Ui&+)nlHi)c{HW9u&Hz6m%(={#!nMI2gd2jp2|ohv!|`9f zf_6|05@vB4F3h>f(ZbWg&yX|2nP|2!Gu>QaW;!LzJhVWVEvRL}?999?9AXn{3l%lO zU&8IeLCE(A<6(R*%rD+iVP?P+!l~d>!ezl1gz>F1eilYSGp-Bs19mGP>wkEh1w}Nn zb{>4<d|+3Yfd~qtBpLaI@i2-AGZ4jv`PnTaoD8lgTnt=GxCFSda4FXREk#is8tsJ} zgS!Z`OVvxbIk>-Y2k=PYF5t<+{JhQ(W@&m>csTe);W6NO<Pc&!0g5+8V={P=@N_U2 zDl%1Og5MXO1>Q<VzZwr?r!Zr`PdFKTNSN>Ym~a{Jcfx3`8=*6zs076&;cDQk!nMIS zg_$aMg`0vO2)71%kueyc&R|RUF>tIf8>I=tjD1p=L;9qr6w!DZ8fn7Mg3Aj(2j*&G zdN3Qzm9OM^;4I<!;AX<_fjbDV1a}o)4elwt7Cb6H>wiSi2gP`5fLT{h6=tS;N*Iwf zo)czLzbsq?{F*RJ6W5N?oeJP3!Yl>v3ReYxAY2Rn8y|_HK6tY*lk_v;?%>_ROwxnG z1HfMj4+5Vfqg=5%zbwoQ_=_-`bhm_=8UFx>XkjE2oJ}B)14ao?0z1ObfH{vtGqb>n z!q0;X3%>wP6@Cd^T6iuvU3dYws_-J#|FuN10ve5l`Tp7nuLpM&-T>|{yan7xcq@32 z@HX&p;T-T-;RE1F!e4=>YexG20L4tvI1he7_%iqv;TvEs%4O_tffowj0WTN+1H4k$ zhpKv=a2)t!;bibuVRlY-hD1>lihaVILH|mayW_qS?g&03+y{I~cp&(y@Hp^IVYZ0w z3eN#Q5N2b?k7|>V39*F}6vZNN0pS(kWa0O~C4|?2%L;D?R}$U@t}eU>Tt}E|Um6O3 z4sIsQ;rTWNS^pyx9G~wf8XTYRA<RWF{e&-phX`K=j}*QJ9w+=8c#5#$LD3cFqL}A} zE%0l?4tLpew=@G01C6D^JP+VK;R4__!iB&agj2v<gsX$M3v=859^r=I&xM<Uj|%hP zz!T&UJm!j;Q=-uhd{MY7_^NPs@J(T!E_he?G4KQ7!C-GvI5M0&2nde_Ckpexgu=ql zgF~sJcoB-y!aPzpUHC0<RpEERwS;-rM}1+QDA+`JH@KDXK5z%&gW#^hhrqqV9MY2t z14QFHXbcrT10F5RNref*KZ2(Ta~bi|!aPghdEqGV9AWOrd|j9)3N8`mMSkxk;r;X7 z^T2^MqLB*TAk4{zEy9(-+l9F*bB}Nx@aMu=;G@C~z$b(ogHH+bg1-yGEx1DSS5ff5 zo!i1(2z_6;2iSuz4g)#>><SM8#|w`I7Z4r~P8R0DJ0*m<pt`Iu{jCJn_5YJlR2Pjo z;QGR^fm;Z3sb@#w`QRSHYruVlH-Lu-Zw8MP-VGin{3UpbF!tlsF{X>+J7~-!*9$j9 z-xSV+YITt?Kfx=6`Kf(BdvKD~qBxeDe_YQx<@ap*T)p1hYK21?E;hGt^U)WoY6}Zj zZ-1d?;)#7>U$?MYo5`wpOFa6iC-_KIyZJ~}d0XL;rTX*HPi@4*v-oQj)fyJl)uXK; zougLZ;ko{ex=m?W)u;`m)zxcwc-9?Pm)gLyt;bc>ws`J4u4eLi?6~@d&ojqWiFSD2 zJ+8*#iG%icw}b5rmA5@?A3mW5w1+fFZG;li$PSQRKBYQ#fV7rc0VO>AozgRBRO3e> z?XF&X6w>MHA|9UQ=T+5?kY=c7IznowukrBgyQE5Vg0!=Gq7$T@)ownfsJxw_x%y`{ zpffZLwGm2evWe^h>GfY!$1Vuyx?j~hd>+28Zu9xx4b`|SOgB`ob+z_-*4<S-yIH?@ z&fHb4x<lMgE$9wMa5q$UYrJP)c{QL1W7|!Aj3*8fj_hfbG1sVyJ*{GJ;?bT~$;dc# zDi5j|ka$im)MuV=?P=kLsD;Rm`q--rRF*(9p?dgaEvJ_i3y%u*vP$AA*hYL*SHtjd z?`}qRbJ5dBu6Rx@8JLjd-HQ*5y0Oe#Eb8z&)2L*txAs}7xfez0lQ44cFIcWm!gv){ zP0qLHo`f+J{O_>~9CyG$3f1`VL~``t-;*$=!YWR}Xhxwo`t9)JaSBaeBdGr8Nf;cF zz=;YRS-}Yf1Hva^bp8M3B#hi+*WOW{&#flm(=cj(VRec?_N?f}^6dJ#Jz~o|d>F=Z zeHg~U@L?D~$YB_X;lnU^$W%dn7)E0FFpOG9t$&Wy<6#()RVr1=NY|G}bk2VBsO61` z;!3+0qtvpqR&`%qFcNpLI)B!xX!cNf&sjyyW~$mbD+T*DyPmUBar1Wws=}=-q-q^x z6s(N0*(|Jx)O1EL$qi3$_1QVAL(iK&G-aD|MFcLn!k?(-G>;P^_EV$9q;UH4s=GK` zY?X}fN}ww$AtNvW`k}xYL}pr`2Lw|CJaK1AU|JM<d4a$2cTylhjXH1T%j5-jPXr=h zZES!WtHuQK<L~GI&lejNC<a}eu)sqsqkDb^m*Tv>E?hJlcuDOzZ{_#=6s=C4w-U{w z>i6^3aL*rp)&GJutQ@Z|wgL;_k{uWdw;jVB4F_@K)N@b;_QF{sund3AK<#Mt_XQ+R z9hGv?>QW#8n{Ax7YY}!U0|uP-Y}6Unb-#M;qSd(KA8^L$!gQ!^on(@AdmmiGDh<EF zT+8BZ+D`8ikY`z4m2=5TN6lCJl2zQSs`_5C%2!$oM*@%2qSxZdOo5@~D2peL1cs4) zR&}IOU^v+_{2kS<OV*Rcrz1e`nJ1e<E6>=mLk;r>zB$9<8Z`411M0PM)Q}&o_K425 zAFZ_F-@vG2{>Doetu{3EJ7Z?#d2IAR!@R@3ir1>6?8{am^L<t7GHRGA>e0*AOJ@7* z3zw}RMpo6`pR7!?cy^_qt-hw2qh7ya9mOqZgReq5MlHK)^$&c7V4HhA469MFkxICR zi@kExtZUYAbAR@oYq%K8<3?xK`qf(R!7-M<+^}BFufx(Sl7UI!UFl};NCqZhjC%Vf z?#}v7oxN$5H7}^ZZ&qeeZP<>Y;kxjukhb7N(E=}xFEmCC`pv3kp37eG8)9yrQul6I znQ_|IZSBP)Hf^Z}zgu(6Uh3HI2vGr*c-wjeM*{Y~Z6)BqhVi#itv;^azHL?X{1vSZ z-L?vweblwv)>?cY7TmEK;>h=NcPwno_NhX5t(KlEzU-lQt);P^r)~9ev{U5&`#?wa zzq(4PrDaFO{nuS%ZolDUdX4Tss#pKvV@FS%SFd1_no`hSu4bm=`tsPef#~cNNp{W7 zp(Ds5x!cK7k@0f3kUdLw`2NsaA_v0!ERx)e3p37cGIDo;eN9dX%YWe8XTt)&biPXT ziuvnLMvsX<p2LIPUT7@hw}T2aLipo~xZGV`EKb~;1ow<{!a*=QE4h1?ei5d-w}gv< z{}8SUHV^@tZwibO?gZAI6>1EEB9CYc0rP$c%Gtl?;v+JLSSpYaSeBS74{=Rl6e^>h zFpPyyGY23}23PabE)%l1a3RKjh$xDJ*|DIZvS2PgB3A@++X0!ed4-Hu!?*K>FyDwi zog6|Y<Z_W00k0HJ1+Nn>4gMG$qC@FWY!wX-T5;hL<u$<UaFFYQ*~uU`0v{D_0%l)= z`yM)guLySm-w^Htz9Y=k{Yw}FSRsQIJuOd!hF^FJI7WCHxPb5saB<<8U@l^!-M7FM zg;#*93BL=jExa1c{sYakj%1%94;L$a3`J|vK$FMlD7+QSegZ9g3+^lYJ$SJ2Dews4 zt6;s`3+8_XPZs%2@C@NU!OsdC$e=Ik?PRdPl@jwrBM<mZVQwK<F3brl_6-=ILg0<U zMZlj3r-OG0a{y$oa7*wP!u`Qt35Ph+@vSI^fKLmL2456@0(?by23Q|wjzByGz9aJI zz<&wr))<Ni1Iqa!zwoQz7-0p@tFNbqp~X-X6pdxzqQdWhOA2oQmlNI$t}MJ8oGH8y ztdBp3n}@)SM9xZ%M@KP0Ux6PLKE=g~y+m;q8iR$egGUJ81wSFo0~99<vmyxzbK&AE zWRyczd~XP|C@vH(0p{f^G{fSzk{p7f92DzBqXL+xuhLLQ@K#~AnRW^f2k#Re1wJG^ z4$LDrX?HUCJ7JcfGr~`Uc_IMKyaEpCZDUX@hT^7ZtOWD?EE-x1ejv=AfEP6(<t!bR z@J?{7@DZ>+E*)l$fs;gj2CTQ1L4E;THY^Vr*Pzh*%%E`#+<+SK;o7aKaAC+>3l|6L z+rnWc4cu4c<-vo6Sy_z`egyo4a4Yb1;kMw}dOH~$>I}tP(dY?Q!jFNu7oGv?3)W|+ zgPFY9BA*M^$E8F5I(V1JnR0r|8RQ$mUx=Kkc!r#Skrw2?@SZa$o&{eOjpxBPh2I48 zv?^M78~i|c5!j0_4&^Jryc3kX1)Nv-AXslXgZvm+Z#e`10Oppn5G`DWqP$qR4d!-m z%F)&f-w+Ot26O)z<t|unIRlpj>*LbFrNMp0Ol9yeVNTuYW6@!zJD81rx`XXVA>$cQ zu)>)w%nE0&FsJL3F!vxW5N3CAnJ_Ds_k}svyjGYau^WXs*Zhg_a_|n#NdNbt;E{d| z5i1tGFAcmC{FTT#Qp!WnXy#Y2-lGP-1->Zq+hCqLO*8kvH-!HL-w|d#@t3d*j?ml5 zU?CO?y+;k4AFTJNfeVB69yKtVXUS;q(}UXJ(!!0w>B1ZZtt$K|xRx*nHR}rx1ncc; za3?ep3cX(qiZNh)LpXRGSl<v1<_KqRu{;H=ZwRMl@KBM@29Fk=1D+tvfzRAXE&x9x z^2OlUdOH~$S_;Kn(O?Tj3G@Dx1;U?$**|0KkAvSAX5)0NFdHHpg)f6Y5oV)gr|>QC zKH+;DtUe@)zoBtVm<^8ago}aC2y+Fs-rt5mln37sc?MYTX@k55_<_jT;NZat40JoN zCCo8Ly}vC44R%12MB`;}iZI6t(}b6R%L`|NGlb8Ad7(8u;KAEj!fc^77Ust57QzL< z?SzxSq0XWx3`I}jWbhzi?#Lb^oCcmOToyb-xC;1L;fCNBg&zUW6XuO0ZwikBFA8(W z;GtbBM1wo5R|(Gr>s@h(+3VnJk@Iu<sqlMXy(<o8xOw`Z$hU)!2=4)ZEzB<^kE`Hz zE`Fwe;c)^~@H>4=G?Kx82&aI#`jlo;fl<OGz>aVlm`!t<VM{tuxC*$ia5ZqMaBZ;O zAP4i!;J-dJBX_@8JsQd%o-uty7~c=0r7#29UYLRFB3ugGLpTFGl8i19;$e(?h^Gj% zL-HgzL_=s58M8zKUt!|~VQ3kP$pyoo<9CH)AYUU)^BaZPHQOv)3e1x}xOa>JIx1Wj zd_uS}{5MXCq6IWA2)6<MEZiP^UAQBdmmky7Uf}z}{lOk9EJvpTV<ll857xWoV17DS z@0J6<04}V}ApKv3qLf(Rr#4-fpW3Rz3&FL7`CYFsyb0Vy_$XNKqJszQFZ2-k&)|W= zk@yx27mfpu4T&Niipj$H!83#lf}a&G3g+oijD0ciJmC`HH-*!{i-g%1SRu^M@hV|1 zURy65;^1qxDEOWJRJZ|nmoNum_X~Fhe<{rV!q>ta+5KLapYOB691`R?ehl;!@HJtM z{r<-7ywqT);+|-*Q}MU(OmHN!D$UFS+rsQ%#0j&5kx!W4{zAg5!Nr6(f=dZ+0#^{; z!S;U@QE)1?mM}XE^@YCyHx=f9L~G%z;Euu^gy<^FHi6#CS0p@6z(c6GsS%$9W1=wf zZFpN>EHoes@9P7{@r3QN*%N2lp%@G^-FwY$?YY`RHGAD|Wwuanz7AzhPxUjEwN$2p z@>pN>yn=GI`j*PW!&K=vpq!&7zG36~UbUZ(hARJ?_IPuhn)@bHY1wDrv|l#i;HbBu zOjSGHhGqwqIUf$(U#Om+4+pZ;xAW~X<}4Mtz%GUfo>B|!l97e$W9U|$eKmhj4O(Ew z;uyQfCg#nj=8!*7OK9XG3i2R5)o_N=IqC+bEn6Zn)TpV6xU^#-#AQ{zg*NX*9?VBW zH5ZS_baX0;s~v|uL3O{^L!;c2^5&1IS~YXtoI7de(CjX~Ej!ZYC*K@{FWw<Tjp%PB zh2p_D*qIktc>ds@c}<b7|4ugW^<wT|1{%*85C5K~eUaNJ^hFou!yB1~762w2crJ*( zVuMqUQQkRlCK@&uqumzeWli8?liyR6PDFGfVskzQGQyXq)}jYd>_m9_&_wi8ME1WU zd>lf;x!vVy#OECb@BF_(WX-@IxP2La?K+U+VpR?TI8E@!n~_6Z!&4J6_GaFrnHu<m zi&g9Anu)AcKMHI(5$fduRubkGRu8aBg?>Rqa9!#W8skRxsHQ!%sd+FO)qEKpF+8nd zD5?dECT311BV?W~kVN<V651YqV14zU2ihwTeV?x}bGkl3+4o2e#D?RgktR$?ui<Hq zF#5VNPWBKpADXeg9vO&_^BS~$J&A_XSUo<_N(;RL_xx4XK$2$+(Ce@MDzt-~C@_K_ zA?3_qVTLBS8-j@7Z(wiGhk_Fs4B~H8Fcp492Uo$QFUZZ|{@@X?W!U`i##&oUsI<q{ zR-)ms|7?9W1L$?!TJX%;NAG=cL;DXmtb=6B`HJ$x%V^$Njj&i>k;50jTHlca&Nr&n zAge&ABBK*TED_YF;DaZajfg}9uYtY6Nc@cqUWOzp$Yx`7Fcl_!!98%)ALMMerO#Ei zgQXEJ9DU8Uf?Yit8hJRT?R7@I1r8>{1tWL>X3QYFnV#U!NX&@fG8b}hkPZGw!}Ei> zHOQ(^aUk3{<KFxQcAO<J?B3$bH=Lz#FwBV#+oA5QWe}%3`BjI(R<RIYk9(V^1Z6lK zpyA$TDphy59>cxe2!Criyj;n>O>0@s32mMUR^J&)r|*#)>I8HD<ST5Pz|loF!K8&I z31k0NG)?G*(7E}vPP2SthmAIxyNPBF%(X~hE7C2f6>Sneq$0_z0lOU%ex&z>w4!6e z%hV~Xjdf1oxQm-&J_T9#gmtRk5G#Lx9}c&yHZU@wyBajasu-HVFjUmuPD}Wk&Shvt zDB*D`s%X>G6S^{V)wM@YCk&w?Q!8dByhulDX=Aez#?Ve(t#~1UD>2+Gt(cR*(M?gj zn!q76w?1`nP;tU(T56!3o1ehBG`FEvEKJ}U0k^SMEKbNv7n<lpZI>pnqvW>GiscFQ z@qXRb+Soe@`RH0ZlcVkLC4}f&d#zZVP@lnmR4djcyv1O5Hk+~#Y)BZ!)aqvPgpW-L zJSWKQjWaGWo|EthJ?djJ?`%(S>2^Q!Md;)taD>bqU_JuHzJv!pb>?v^u}uIfcZ`nn zv4p8qjMa)02^^VoC+M_2nJ|nxleFT8go6y%6s<Uw(2F`Dt-z_o6;zX<R(VWnj~{B4 z!p!87p;n`T?=t8!S0Lc_)5sq_cM-$w)MhFy$$`Xh_&Il%k$EQZE@<0q<F;^5GaH5r z!P$ojfo3TLXP3bm3qi|anCf{=jT&a<3+X(6{-Hd7o~9(vpAYBxeDw537SD!GG~;xI zW|}zHn1ol!O$`s%lDLOx!R5Iu><Gz0#&!+Zi4FY4H>Yc;zyqQYH_`~G=;2m;G1fc* zOQ(&MP!jJV5NC4sipLt$Av+^d)fsLj^oW37ObvSCahkx@n3_5%oQ3c)rWV=f@NA@* z+BD<DjUV36h^a#kI9K3MOkHxUUNj$*Mdq=_=b@8W*Q?eKw}Rzk;H;UgQybd(S>K!4 z{0x+ZvVfj8%$@=4jQ<7yR5yp?{jE?*BdkiXFT-c^3ay^S|K#(k=LoCpBRsvvOflhy z-lJpAe+$jMV!M%ckkari{4b{cNipeBGXAG(k5WwfR1fOnFRLRXtQ1fENcB6sGRLX3 zkydkatQtGgYVYxS)&7x~ubZhZkF?5}FRFx5Rvk(^j<PzKQ`M?bR&kHxRYylzB|LYc z)E}d)O2tMXfz3($NU`olWY}>wr!Yh!*rHmGwmOEYz<;wP?^p=SeYJpP+f(|)n17{B zVX<6sIBNa<6r|;uFDi87%WP}rz=sMm;eMcl=Jd1h)}F`MZG>5?Cqqzi8-#J&bedG+ z(OQ8zm7l=qNa`3X7~P5v8zyg*Ycj7}^Fa2iW2{9{(HG&S$C&q@uPwq1<m2J<Df3UZ ze)9g;>BVf%bnC7+yW2CCTQ;<qF-P$D<5E5SYQZm%*}BE=6S5O#t{=-iZjvJ;xyMZo zC$mF|ALk@;kDlb%0gj&3zZK;8Ft38Yn3)UdUhev^!eHk#TbOQrD$MWnE@AX%^$B8} z)+-ABQsl+JUkjH2e=l4bd{&sb{zu{R;A`wd&>{Bye-jPPqHzq6^6KEfg|oo97bevQ zbJ&k&nt<~Ov-4X>_)%~%VYW2O33mZk7VZxJjcTIk2X012>52un5zY(N6OfQICAy28 zUHm@6$>2f4jQw!o3@|_7bh8?Gk}zAL)4?HX)P~||(P#`-WW0N5g^!g4^VR5MCBb|( z`dCRYU+r2kp9KC$I1RjqjC{ja&LO~D&YgcmWJ1OX(O_&&3DcpUgbRbO3nznb3-kTm z7v?L&N*C=x7BEOgh%rhNK2;J-cTz>33fA+FF-ZS1Q0NIr7-Dki2}p1wFi%mSL(RZ! zd-41%zMAgBDPZ;#D6a_S*dUqiOe7<zn2LI;Q1}^<Bk_#cxf*nIu4v=|D`5<d8B2wk zLhlQsyJ@Ty=KI$3iSU5QuICfMOrafOCLOHj6Cr1&*7J$rP%S9f_GU<%fG>~{0wx^? zCCT*Qx-g5-ZQ%-F6J?raDuR8&bTc4a9~>{-5X?bLnrA*s)^mtZw1T39XtV)yfRcvV zfh!4j09O}gajGNC;?z*M8@QQpKX4o2fnXk}OgBe@2a=I<dEi#~+GHqDbsJ+ugRg^w zn=}MF;kiOEUxz+Q63k3GPs}8P-xMwd)>kOQ3}1ns9z+pfKG4&HVEUz}2irhF&-DBt zn4ayULty+1&kq9Vv7R3U^VNJOW|*tb2p0!m$S#*{#aOS8$>&vBJFFJCME1oUScmwA z`T-BmnG98aC)OX%Qd4(A+ChE6$LFfhE<6UQVSIE}pYpL<xjELao?F$`gB;kHpjz&R zbdFlE+ZvDMaC!H@xeKk-fIV2&c&4@bcn>a#`YAjBaBC0NC1M_KFBUakKnQ26ihHrB zaYUM4)Hrl6Rx!>%Mh!1&e3i=0P=+tC-3q1Wa7T4$uT>(_kF<PRUl!)<gOg2Ep?z4~ zI0t!fJL1f0E1mb(Mz%rji%~~XB8x?S-W9X9+RBMQ>_3a`!Z&?Y58w3lhF;&e7`Dv` zsN2iSO<$Z^|98lNB^v_=9EZb@LwJoMDtoAW(a-VWjpQ&Jh8)-d!()8dLLI37=laHH zsPFT(;KTIv3a@W$|9^FTWBD<I2M+JwFS+la$3`3f;fk<Pm3$?0*E)W$K5QQdW}nX! zdnCehS6}*tclZBX=D1KVbKD(X=6L-7edkwRz046e<MPh0!wc<yQeH1}tXQR5db*mC z9i5h4Zjrsg4DoEprAUy6e;$_1fA0F?qG}8Yah~Jfm%=X}UdkT42)q=w-Z2i;ib7xX z6{fE@GKVT}H2d6o9Oz3Jit;`Kr(yA|R=mPeA5D>m)oDaT3*tnyY-JeeBBjw2C~Zxt zZxF3}y}xONm-8_`PF-QB=V$2nJ>-lJfUv;{HgDz;pl=Vn!%$BFgiM=>tVJ~ZrPb*r zc2erIFd5n4cSxK?jAm5T4$yWvr-g1FBvI}aRb;7M+-1WPgF$c5p(d*BQadrUh59YV zK!QxQ9s03Yw8_~=w;w`pxYyx#$mQ(aG?(A%scuj36!!%fo$Ri~-$^cKw<fx5HcW8Y zW*hG^CC0fYq5Fhe9Fno_I=C~&eGh*}yN|+!Q7(^P9f@V7IqJ$%JEal_dVHUagGH}@ z6b$(GEd_@MW_$<9mY-ia-(dxI{MVvY-DP&g&=>F){bA^sE<YR|_i=E9%b8NI`yx2f zEdckT+%@26w<cY6xtzi8)<?iC*M_d`u7|`i93G{K1))V?*6oDQ8ZK8Xm@e;1^0+hM zXoNc*spWOOblNEDJPV6nYkqaw$kc(E2Yb9Yi(44-{H9`;+XbpH=`F`((tCsa>|3r@ zB*hOLk434PGlG26Rvz;*47UhIdsMIGc4As*hO(f^cfLK?mL`(T9C&&-c$DsxFn@yL zSg?XxwA{{Lh5bsasyP8poC$73c(AOIsd^#Ed0?!f^ufU8Alu?rQ}YGr+|S!rU0ZG! z%xq7O+L=os^O|`%vuizSa_lL}%v+XTbux9@n|ZI%sV-XOntA_J^;Xyg&7kUmN8tct zI@Wv@k9afhNV+o7<Qcq)xG-y~dVPhR>WPa|TUXeX&28%X3OmF6N)>+x(xOqS`8)Rh zrbC#bc9rh%S?71Vs+5Te(6DPafZT_5Lq@#aln284f8Yyj&Y&57USnprB%A&*s>i!_ zKKBs>-EPlVMfvZk84!gGI@E(AD~>k;*}dqQ<L7vp-J2Y1_}GApb*e<dMI8*MsxEeh zrxk2Fwdl2v^R8)5oBlMz#UM^Q9aR6@<PP+}>+eAB$RI`eIbP^=9!y2F_Sxx5_kG%D zryDuZ@ZH0sq5JqAx|#qR?r`QV!_W4sJCf}6mx87{hDLDpGJ@icKLU3A6Ume4bF9CX zS51G<uIKT1)UNmJMtoZD+eujaUGjaqrun1l`@UU*(%J9Zwas_b{`c)UnVaB@*{}|r z3HNMM9!DI_EJiUbD8|#9aThgeKZ6HgCN_cENZqVnS!wq)&#N0N?c|!1kVf7w>Oi9_ zdiIITXNe>f3)Xe1&0r^{4l9~T)SnAT)R8QHKD)&#d$u=v1VkRA?|<#ZW}_GTRm6Yo zyQ+4hqsyp~iTMNBwKv!$yz2g2c`K+EJM$FCb~oFo7e}JB<@RTnk&zz!aV9AD%3QAU z%<bn+hMc`Pq?N%hHJPn5e(}j{oN>7dnT;?doD6<jxCD3&IZFDoo5Bk15J%Ucp&iN* zrb7pW>ChozI;8um%pG9eR|PXb*JuWec6zw03PuYv+*Jj$Rrt5=&qBdYawK9&3v43V z!l~dm;d0<4;dHR>tHOL`a4C^zg7vyt$XNkb5qTDvbtc_!4CY8Sdy>8;P_z>TL)}>z zeJG=+F#9q6gc%^ch8C6?pxl0I1<s|#tNx$l4XW-RL_68BU)h_yoDw^ZS+B7w{|QWY zohhn@oWOL~EVcOrCcz9<@mpw?RWrVY3KMWt#j2*?;W0(M`5k7&#;ElTBZBJ0cXq7j zWJUG!cXo+L9>p_3<^A3+=J~jwZlSjM9<yBg)MMXcUW?8AWIZLen9}8HJ*CNzz7gJp za~)!}?t9zo=QpA_;!tc}y$c1+O{&yMOpoDnjYs6rDj4VuTbOe)w{=uWZQoHaF*2i4 zrOZldR4^vZd@K8xlXi?9T92yYBRE$b&gK3*13>?@k2rFU_EBwQ%YWNPA0k!J%;Cxw zw2!y}1MQ>b6#Am?!#T8%(%~}NM~#sqb^E9eDgs#Pi$|1~r9B$e1CF8P@RhWTx}cy- z%ZP)a5#jq#e`f%~jU-Ox|I<j~<T0ANQ_;Qkb!Ls{t^6yT^#|dgH{(Mc8&5G9@@9Sm zg~b7EZ`3SKoZBtgC$?=Hxx%!+Ll8ZNuLneEM6q41-H5D3H2hUmk)Q0O;+&n2Y(U!< zi@G<u>IAy95n{uB2B{NeM@6dMKiR1v&gUdXH`+><cvf$8QyMk=zu-@F^SStoDYdFF z6y1WQ9PO$r2wSYzmr)#Hx0@p}hJ6lyO}iKz_Sjr^6JfJVc<raak@hwwqrD0oZI^~| zpUrE){5I#2Lzc~*BDVbiPGHXH037#KXVH)K`l~FW7k9K5<6$af_d*P&*_FUkZ5uqr z?g0yvZGJ5#+4mutXmgF#1e?u>@irTz<LqR-^C#?;aA&Mt3U<fXMe%pEjTIIHjZyaB zu#6ozSqxOqPZ7XauhoUqW;WM~{9@Rdu=yRnx-eJCW~(&Sj(`qgTL^Znkz9`sJ99lS zXLF=`dZf*!rfCm^WQSqbi%>uPY?pH1rEzH%R#ru>;Cs%`uXUK|?D)S|4X)Uw+fGC@ zy!I$&cl#5#X4qW*XWEs(9-Biw5jJaIug!&4k%q;s3SN6YFT${2hBj`WMex{YI}A~t zDQeplyFh?%+ICF7X>agXb?J&-+>_{0?p3tPIG%t;4>QsB;A3<r+3W~c4+l?Br-V5f zieteVs^wKXf7RCz5WA|$<(X%K$uynYDmzEd8<}rG=W_4`8f$9KgzSFaO3`ZAN~b`L zr}5J5cIJEt(JcEFp|u}1SHe7+Wn1Y~Cw<kaW9H@J3%iR}p;?v?sjgqO3z+$oea$Xd zM8SqV)+~Vs+GU)svL~8tph`r$tYNfjbPaR-J=NfAXpnuP7V^<reRa)FHHWLa*X#qK zcbR5R6;2N66692sQrHF>PVKKD_f-YPJ58tIz58<z8b_B0!@rK)lJCs)zm51ftr;Cp zT(80X45zJ*nx8ikIPJ+%{wK*@Xx``N$}p$fTsAlS{(|(Y2MvW=ZcZ;f(dn-XAD!N0 zwA?sC73)^v5<(qPx2i7dhGzt9yR{fPUn7Jf&24jsX1>KAx1ElSpX-p_4&e}S>8IO~ zp@{PLQ`>*F^L3;@Za2D&cG?ZZs$t-9HqiYgk)VO$%uu*+5`P0D$zDJ2A`Oh85ucyO zjt9o~WqkZU;cs9P{fYJWQ01=MrOY2xr|Wh`MfOgc#5C^(!~Rk*71NR#(C{CDZ(&aK zpGF>w(dn7)|5I(fZdZ8p9KsaSmVvGAXGVx=N6z&3M?_<EBx?8<AaXICDX-~&8o`U{ zJ{TU<^0ToX)05qVEdLkqH|8-0tf9Y)%DQ1EHXa0#VF%%;X<vg;kKysax7g|oV}TEV zW+OUku7kRuzQ?Z78*n&@lip!1qtHdQ@CLH+Ms?$cUC2`+LdD)h<~*Rv+_dYM&#ECe z?J^$R9;|MnNtz$m`rfn?%!TS3DA8X1>!w{4AKxOs!AiEO@ta+$Kz_QNU>?9bI*b%6 z#Q-$N|MZ1w>TmdB)>JEgL#LvVR~`J#PASajnypO6*KA*z5r&E}Hai&QhAR7(U9IRZ z2)?;oJITrX3RB>=xx(a&<gj9eU8?UbyPPN5t6sT<RzUgeZMW<JCUy)LzYW_uKz+1r zPV%N}+x@idmT)M2mzsLpegUzt?x2t!SN-nT#m(~S`8#%zg1q+IZ0}*BIS5k&hHHLt zG#V>xR5^FhHVLWVU1X7ss`g#Gk~vL{ylWRr{t|&QU-mEw%=YP=I5+2NH!k9p7}f8o zkM7!y6S)>Fy47JAsxc3FAuyeJzGk#f#oe<L3kD(2Q;SjT7>7*#9YU`E7&UjPhWG4l zp0p^n<R0#m?yG*eXBY7Vy(;DpJ8#lZq`6f@*EQ`h+L$;AE+iI*w??foDhnpMbF$Jd z>!H)rXo4@usQDa%5MPhNc@(aIe@4yva4b)4#^VDDsT&SN9j+Vmy|#-|emxWU#*CT+ z)%ri|cyo02o<HopPBfbV9%J=??J97~-Eb8+RM4k}pLOzPkM=pP{lD)yDD)iM?A<|U zNL2Qm0?ycmq0K0#xt)e+#38q%u!oGd!{1M2qzr#6`Th`g{^F1jxf5kv9F#jz#`Pp7 zo51*OXGsf$`6n`)!}xXQo9C&o{PFvjJA-zcjI`rVcN*X@dm_5i0Opj?VFa4J5;pwV zyCElob0@n}z+C4>d1>%X;i}-f!u7xpawox>K;h*Jg#{K!OPHhcvBGV@xszS(z=cKL z0h}t_5v)56aEGJwy3+ve1J;}EzyrbThS9Gvj6YW}P%#DEQurBgd*PSBU4-X=dkMb* z?k~I@JVN*~c%txa@YBNgz_W$_2EPst(PIyigp1tCHds$~fy;ySWEZ#=c&(Vp0&|## z<{t%fV20cayhHdg@LpjKFLTU`W(I=U>LL&3Mv8AmF&rA_h1rwUlVC737R&|&EldLc zF3gpfe+oYd{#%#}F7qJ6vVX>WllTx97UuLqs%E5rJ}63y2K#61CggS=x!#GK40%1_ zvS2odDQ738qcHOd8&#BZHiio+$d7@!;*UHK%vy*11o#;}2?oWhP;e1FH5P;46kY>f zCVT|U0YRGi0n9@-$Y;P?gfD`(3I7Pz^IIrU{2ixU_y=M7Z=4kctMOZ8lyxTE9}h8y zpD1V2MF}(I9ATzh9$|L76NQt(T#Qe<OgX(54$PFpoE8?+LcyeKAcmN9&4hb`9~JHg z=8QVcj|S_BEHJC+Q6gUm*8AKbUk!dn<X?ba5dId-9wgm4$@=FFQ82l<N}n26!ApgI z0dFLu*2Ba2<RRW8%#=GU%t}e$b_Vn1!RJI?1AJAuKKM6s2!`51aZfbZ<@;N>7dR5R zo*wrB`-S_1_5L(`miSAdTv+c_1EVk)nUo`BY2doT=!+YTglmCA%|+1=inhW{z@3Cy z8}<=y2_7cQnr^%>12<K;KUiOb29Jk;Ul#co@N2@X=s4Plz=ik*431$kq|bp@3A03e zEW7~BMT9i76|DEFf%z`=UN!Iq@RwrdCosE9G|yV^dto2yhO@$~=zi22>0l@p3bqny zAqA}Wt${0oJ#1}&tAX`ZY2e0SE-<3JH@JZCP;gOU?hGp_j1d~6oG`bXRu+DVwOFPo z*xPF;JRjUjn6pKlg;#_72=4~#y=n-=LGT2T9|N;9!oVE|zbMQvB70Pn-v@I`n%+qL z0E*?JVIt?O5)OdbDWwH|1$UD1U1tv8CtM7CNVqguUx@}Y>0l0H&^(9L^ma2aKf(G+ zG;m$`AHEU|3YLQVVu6{9r*Y77Z!j0_kw=2#g`Wm<l7#XX!CY5Megj-VnDs#o;nm<Q z;g7+MH6!<Jf}*Wxa9p69@NO_ikm=~>;1R+{!JILpoYnAC!pwkNcu4sbFb9mtzk`<w zn@H*Rg!6&daF&XOI847mxGb0>+LZGXe2^RnS3Vp9A)}5mjtk@M7@SX_9RG~7!mO%q zk<sL0wg1OMOabM*q{oO71?zlAm@P1VENF-hB?`07FDA@-p2vmIObR$%xHwqv?t;7& zxS`0)gPRF6f3(rJe!&nk2#4(G5NoA@WQ2w>8z#&^j1f)%PZZ{dhpR|wo`HBqI2Alw zm>$m+re8|9Dr=twqR52CGGPYdec?LbwZd88kA&-kxhk5=N4((Ag&F9h!ibM?LYOIf zN|+_+0+}1B8H1liqY(HP;bbtI-CVjs5A@D0;RKQ6l^V&yaLOnx%vN%SaDFhyI_VBm zrHL?$Yp9(lDnZd*m>-D&!qveeg&E^X!i~XC3pWG5B-{b~hHzK#BH=#Z6~g_&tHK;I z20^i2H2A^D79I-zRCqXepYSN~QQ=A8lfqNMmxO16uM4jM-w|f<)*G&n5}$z`3)L5s z<scLsD<EG0>s?mh8{m{|cc}AGz&+L)9TJbOwXomi$T(j?b$ODLhV><JlbzP;jD>Y4 z{U$ptaAM4Q2s|e`D9;pU9L}YhIK^pgwo&`}n4|Jf#bbjS%tv*#nUCelKMgjHbyHoZ z!A7b&0wv584LReve<lP~y!wfc&MI@dQ^qW*ZXCsalL^zESj-GOH{B^2c{u}3NA*~d zU{LLY*fT3jkLX{gk++mN14fQ!;Y*@N^s{C_nxxuNTDl(cS9p`l9EumKB@pANv;BM+ z>IMxh$NXQGUR;v?q$5il^dNqIZ^h~rtLlTC-phXRNoPc{&|PGE^Ac*7bAfPc7OALz z9^~wQ$MJo5D;UTB5{CXA$LH`12IV;{igEnMQ3YZg|5s#ljN|iqG>+rrC14ys4Q}ai ze9nEs%1D$EJ&qsJ1Nnxh7J?z;_*{A|<M_O8NXGGBL{XJ-{P0E>=0z-a*pFah9KSan zzUJ^OcO3sq2>uzzZ%&0C$M=myR54Cp1a-9^X4D_=I3-e7!|})lf51g&7L7(#?E-z5 z3&ISSE#fHGQVrjAidW}yb}VsNK<j@XE>TTs((n($->BTd`MQXER11#UV{o1Wxt^wK z$-7QMs4U`RxNO;&F5AQ&_iskleVYMy(Zt4L0=BKA+~H{8M7tf4Dn6Iv^nP~+Y*`%U zuQCCq-5#vET;4|+a%&>xr@1+BYAT4!Cpy5$WcLvMPI8}xe4@);oS_LWhmgm+yuN&# z%i;AWT-I7+UEaGi#+?KIM!UT9XO!CjPGbz7)2BW?2Jf4VaK!qzT!*Xv6)@x9N;Lf3 zHRP8u^lC8f-!~uP@X`wZL9*rF3cvh*8CB2ms%`HfInLAY4|8E42D#xWIEFF%jF!kw zE>D}n-VVGh(`D`Aad*JS2$$RHyzVAgjC5z=D-z}QLCB-sFJZ>#zO7TL020A+*{`(S z!AK@7yFk&vc>JhobefBw4Hw(wLU5bsetFzP=2@3xa$ffX_z-D0qanfwJ{LH;{o$SA zo`h2z!CwGT9-c3dWZGVnQ!GKIh8=Cvun}Yy!Kgm7h&RZuqwQ*iUW#D{G-m{n4;{nK zV?F|hS_B_Ns#EVfi3Rt=4~+UVcWw_Bh0_@Irw@mNQ&rqbCx3%i5EQ$j$rk*{;079~ zY97bqOfUv^{u%Xe#sD=k2g32o!EX?we@6Xx2K1<ZCKuTJJL=C93^3|H9uJKAb8P9~ zQGc!l`FGUcQQKEKr7%MH^Gc^+EbkS=Fh3_<IL!aL%Dc)*#f(6WRZfOELXE(~bJ4F> zta6HBGvWSKP9yVW6|>rTy2Nl;!Dv5^OJF%P{u%9eA#rLi#b4jrfZDv;snO{+!kRmB zzX74i9l0++c{k=Czn_D9|8wA;PCNd7%mBT~7`T57c^w1y{g`3D^r>baI4Q+HfGl@# zJ}+4Y=i4A^xr6gwHTMH2Uku%HyU{iV=PyR6Y}l{J&QV}YaYVuA=iPpR@oZW-{vYu- zcL4qyWbMEd=7@NIC1tH~3Ykx;v^7qJ;$I;;XJT$Xk5}a9U_;C;nlk*O;Zm3r{f*QV z7<HM+Vs5jd%kaOgHmz}rb=eHtF}GR5>ifA7HRc|<p`WiT=FfO!^v1z0a4#l752Q8; zz6IN&Xc|0*kjLcHI?dv_Nh&7M{1EnA1V^ikwN8l!6KSBZmURw(jcCWDm_^`d_uxGw zR7^?pU6>vkKWxkxBc_y|KpGzWm0p+Cc18x*M5+aAo%GQ2v|Ca8G%Z*e2^*846`|m} z)TyG4PY?12%b4osT7>xNU@wL{Q!8c$*&2zdrH#!BZl;~OTJb_KiLPa7#hhU3zlv9b zJUT3<K6S7!Dmaj-*FZZrKgg}_F%7k1VQ>hOy|Gp-4)$dbn&`MJ4VL9gXrUF$gD#V< zwKn!n@D`1=GbbW3-V4sd-<bAVu{wB@{yeG`>w?_78`Iegv7X!zjH9`3W*4}+DflxZ z(c9!5nOlP;QL1D5n9K#+gV}VUpIHjVa)O5$(gEgq=<Ex=M+XL(KInWNY)!=|9r44# zPK@{%tvD8}hRhx_Rx3^fIUZ0cW`a)clR<7ij+vwtKLmH+?Zr&dic>+ZaEl3P1-43= zYRY=2v*(v6_04*xnCG^u{#@@A={AK4GP531!dDMI`eGI_GJbaDW0o-M82$^4*D^9U zOZ9@bk7qWuh&j#d7|!EoAIjsJna7{_FgK5%r=!f{>pygg1#})iAI{^yy6PNcX*u-p zkp8k{z-$G$Y>$AKCh82NUTo}Nd^7$Ps@z9TN-vg%SW8FE3O-FmoOu=c-04KCK3+%~ zA6K0+y=W>flTI7D?ue^F_V^dTOk7PJFaJC6Gp-id=fB~oH6J+%?rglmxVkhO>mRL- zeB>0V%;EXi7W#b`d<tn6+tOs|HIjNDLCgu!W@n^fAw8WnA(}dcSE^zgoD!bnu4=x) zNy34IgYc+S4^c83cp0UX>97Kx31?D{!HU^X%L}t|FdK)tXoUKBgHs<3)_WVAiX}N& zWESQT)5c}|H|Ku?v!$AbrF4|7^inIb+irA@nVucds${lP4%_1%&31}c<f}D3KE^eL zuU5FoV8it4J<5e!Q5vb)Nc!HZR>5{a3kQdVX${n+Y^QP@PfRc;d+F3Zl!w$eROwAl zQh`*2z&zq*p)cMR@{-VhIS=%oP`x)fUzu}N#%3o4+r2t%cIKE()#c63@}jL6tQVu` zRs~?Hj{eJ0j7@#2zg8b?K>{{a2evrrc>EcDl>NkMiNjGRed28Od={aqZ*>Y+JjP&^ zj4q099(RqUPNzC8ns0J3)!OOO(R7+~EU8~-Kf4tH$yh*h=RIZ?EQVj=c~AKDmf^b? z=P_shqchIKEM2&TYQD{>==nB6P21)a3{9hx2@!O;@El}IGhYP1Wkvdr9&MP35p3qw zI0ZKfuV8+;7@=LSai5Y=s20r25sZJ4vBO4^!@2=<Aj9VGili(h+Wemnng27QH=902 zjXM8Wh|rB_Bf0P>Rq-<?KhmlBXHMN@UZ!YHpzB=fQRg&Y_e4gA$1K!Y8?9D;hLkR& z_I~CR@_gW`OP}FeKU-Pbor>lY*|oMiA9>A3v#;kki_9uVQ8Ss>qY+m<W^K-I*pZTE zEQR64e+^ka&E_nMA}FPD_BfR?^ad?Gt1ogENV5%7Km;t6|3gq#mEP+VO=a;n+cRaw zU;{?s(T4=fY&Bx9Q{MBys}}8b@)iofrNHzY7;E$~6S^~FAGZ8RM|EVcldr_rkjJ($ zZz7zJ`~`!tZFSjx<YSc2*bbVT9EwnZeNOSxZz7JdpPC&~&~D(%Hkw|?3-#wSAE$)h zhD7EzqiF%vW1o}cIp9^3_c@J12?$1fi!(IDwGl@15qK5;@SNzM|5z<ft4-dZznz&H zvBh9sXNIO(u;ouROH!h}(e3r-d-398x9Lw*ZEEQ-HRJxl*iNnfvE9V;r>*MkcY=ja zBc;c|<>}NTByyM~aRmMtO-ifL`<=9WF47?8l*v5%*}qP_q}K0uN}~gOa=%lx=(|Y8 z*wgxRS}zq2Fw%)^GbeJS(`epBRX*UPTiJ+qV%b2`b(R`-z{$*fhsoD*4{d~_^)v)A zJIoXRNSg2p``GsM{MtXlrmfWJ15VXCUHEpoP%jfn6?UR|LA*YHivA?Drc@_P(*}^n zd~H7VkGWQzvfCeYn&*xF2!+mL{QAG20nWw@aB@L!U+n)^$*W>ZtM8iy0@)@0av~zL z%X{1>qyFo>aP~T%d*<~J$AWXGfNLX8xl_6q$jAfy4MvjY&dPpF<^U6ZT+^I;PU;;N z7LEzxw+xZXJq|S*?r`=FT`R+Vh!evc(n~grhz4G?!C7-!C<`tlTpe6d_@CvNFw+3? zCX^#X@pIHlnC`I0N;%Tr=qg+a+*??WbMY)K8lt0IAV6*i9xdDg%r{MWTktgD0bo6| z3i%7*=SBV!_*LQ8!3%}o0KX^vHh7KjA^2}>5XCX@7UA!}+l5bp^_D_-b{ed=6oM~; z^_D{L&)^ec{#Wox;ore}0u`?^4Xh_n!R5f5Kn-!+I2{TT@0HA?W_OKT1MCXd1?%mF zkT(Kz@d(W{2XpfQxd*to@NjS$VUE;Q6rKsLCX7@G{d3moyU^gqS~|22+*J58Fx!%p z?*{7`SMWYC+dY&s<@D?;_&j(l<$1!HPS3c4Id(l=<ORSpH6#6*ab6IOBH&kqi-O+} zMkQb@6fO;3E}RKoDa?GMXK3MBEAS4=QBo4Ydxe=9^%g|PnHj&*Q@~J^hvHi?#Mg0J zSkIma)3YnW^}#oUnKADOcLlR~Opm*RBTz)iy}*9qkHM~RXe$)SRN%Aipf1qc5y3%l zS&=7zIqF0+g~1$GB6AQ#Z$|`I05=qQC9s~wg}e$_&*Fk>g7qvem<!x6VudMSDC$8m zTr4*Oj}>kW=E8iM=?9)J`~-NWFh|Ao^e)VBQM;br1y2L(*<CP)y7cTW_-XKRvHKjC zfN)U@J$Mxw>x379^`1q@SAe&Q{9Ul#vIsdFn0m`1coX=LnArx_TNWYT57t{2!JmV< z)17`D1?%bH5EK`nxG5T(rn@W5g)0w){{rh{Okv)Sa;uLq1;>D6Bg2leN=*>v`V>7) z3^S?V6p^Qc(}XL5LtMJU5M@A-A<T{0HH5j^ou7T0sReE<To>Fzn5&`M2{!_F7UuA2 zPhnQg{e;;n9}(t|@fZ}7L}LVay6`CQY++WxuM2Za(|lnrXjv*e7yN-RH*#kSF9mZq z4<o=Tm|Z<G*Nh*~Q@~Js3dLd3V72>=@GdZSh0y}5-E+cUg1PC5a#q2=2p<FA68=BL z-FJKxRUbC|nN2or+1*LPk`Mx<(|f4WJ4o-+yP$L_qT<q2P(=DzKvA%ZiY=ljVgpeW zZ@uj(q9`i1TWpB<T-Vuabe{M9$N!%FDEmESddbe2GrwWqmNW9lu!Ub4tj~TfDe{Rp z5|xxV3G;~wR^mCEPcqTJ!8PO*9NQ&wCAhAf2{)E`YG!wC4%-uME3;QRTL+mx9_B6P zI1^Km7@~r?@JN}b(ed&kc&fY@o+0xDHcws-oBPlh=XJ1&nF_Ci`5TMV+6Z4OZ%M-O zzfOspP_RYjLy%kL+h8`{ao~I4d*u7!2W6giACuV`<|+Ak_&J%UV8(LccwU2f>5#=2 zzkPtjQ577AKbOCUzn0IyKgc}2{vumAJkQDjn7vFnfgqeF^C3TT4;%R**xbX0BXFL% z1&l;C5(OHd3S1`V!u92RxT#zdZY3AN?d4Lqr(6r>bu(wEE<8kT43CuKEsz+m1kck` z<q@!nlZt`I!i$tY9cF)Ij+Ce7l``A%*(%5U_3%1*KfFbL4c;n$2IIzf;{0C~hl#l} zj)8gBdQg>W!sf;}@_7b(O8G6}=VYFo_*5Au%>FE|$@Ag=$UMKiC$k^QartH*|0k8$ zj)L#xdtr0;93y=IHh0hA2Vp)v%8BiUBl62|W%($aCw~SP$n3aUCU=DE(>(uoMxuoZ z`oJCK0kFAajyi*3+%Y#3UJVbEH^A&o$r;)NPn2(lO*mBKvlj>7$-z2L!t>=9;P_=q ze2c_VnS1)xvV}FmUj7_79o`^k!tDLaeBSN2Rpw(YJLN+7L76-2<1%|+>`gds^+Do! z6%2w8%6#bdb(y^~*f_<B@oA6`<c07tnLFYaGM_L$C3C;}pZqZVn_K~(GqF@L(r1xK z#>E;Za1hRr`K*c~bH_4w-cjc>IA8fc!bS2gaBZ3UOjG$UxUHOq8R#xY*m<Fk5{+PU zM;;Ss1&>fZn@8DkoioSY6z1+cJOQ4m{7LX7@>F=S%nlUntIc8Af#NE8A$%Qd&i}kc zxn2eADdEbS;B7MF;O>wgfbW$bgZX$5C-4N!_6?fbcdz^s{JhLf${zcy^AWp%ysHFz zL>!lYgip%9!tCeH0oe29w9FgGe2oqBxruNu)0mqjMJ|LZ$&FZ7ZUvjTsyzRnhlIK1 zj}ft_M2RZ#;=P{Cz(q~v0dOmso2$LN5bi2p3ip<8fd|O<!NcT-;nC~@$R&6biHR~p z(@vAQ3Qh1;)ZzWu`O1G8=ABdy%aFBfWTe@Q#Fk_FBbc}M=p=mKD5vB5Rykf7*r`Mg zzVDNJ;F}M@aNxf9enRe#@4fOMd_OOb#`kOTSbYCSo{8^|<V*4Wg}f5qr%WtWOkgz< z|5L#Y`2J148{g;TNAR7DD_zbIpK{BPIYLLq2rb^?Wu5Qge3|1ek~!|$a@7#Fe?ujj z;k#VsP5n0VDtvd8*WtUn{0zSP$S>o2kbDr|Bji`{Jyw1b-;-tDL7heO{9lNslS@_5 z6<#j)fY->qU{^jLzD@26-zm?5@0XXtyX7@-g?t0d8Rr_h6^_54#1150k)MFyke`JA zD<6bElwXIB%WuLb<+tJQ<ac1+*y6<AhtJ3#!nj$&{J3=#NJ%8DWB9Hlf6j0D3w-Cw zU*Wrkd<NeoauS*w>&lhj#&QI1A?Lzv<s!HXW5{vt>LSrw1wG(_axZwe+z)0a3DzG9 zPm)K$)8(=7Y?<$&TOhMV^m6$Mc$vH`j>I)eY=YS<g%j8c^X4yoD}1xO6W%WGg4ssR zI*-D;<)>h7Hs(JIKP&HtUy)yfkHF^q|1J{ms^A3tv3wdfn*k#_3xA`0whMkQXTSlJ zWufhF1TIq3<Vi4BJ@co+yje%HUkm$F&=>I$fC42L(xXh~^?eh0Da=@P9AFFFUA_k% zAm0y<ly}49Wj^1+UPK)Bd3c`8M@ud>#`fp4CA@RON?*e(<)7iTavCndxOrH|fp3<p z!rNtDa^EHM;kpN8K2!dPTpxZ?ZUjHe?az_&TKq-16?{nU4j++u+5C<?9R5gV>*jHp z&*Ghw$HCvp6Jc&nPHP%`Mvh;E1UrthU?!X*FN7<}m&0skV;#17=E~Q@HRPQz@0PR9 z-Edv`VYspUBHTje;~{M${QZvsjv&!l1;4{R<+E@<IfBcsA+iIHl-VdbUakU9mHFt$ z40#AVPo4o^D$h>B_P<hzc_>&Z^UC*HnGJ~RWVQ!xk=Y)&RlXg*LuT9HJ@Vb~gEHF* zACn(|pQ7Vf`iGEsP6dy_FUxFde@%W8{*TNn-1lTYPy4aVE8NfJL-5x!uXcZsUx$B@ z{{zR*D)BZF0o)Ga=6DxQlX*oPkw1qk%ctNxnRlNG<p05C^3QO6nODs%WL^<>OgL^@ zBD<>~2L%J<0(hj{93C&T!SQ05jg0eTUc4@mdGWeRo&ax@SHm~UH^O%^4jz}7{k$Gf z!48;RCYXO0{Ji`Sd{}-5ep_an-UsrR@G+U~dtb;uz^7zB`oT^e9RJU8B>q(544jPn zBrIUNUqoiRU#`r@Kx)X@aBZ1a%}wPda4WeT+(l;7U2mCBdklr+oY)W~Myp^9e4)G& zo-1DqUn<`OuaMakcdg8uikoEyaNR0D3g0ci2k(|YW*p2tO7IDceew_ROY-mVtMXa+ zO_`U|@5*)HqjG)tGr1i8N@gqA4>DW9{xHV&=Vf*vGqKtS!Rhi)*pWxTRb;k~<;$bt zB6%!aN1g~bmM6n4WVWESm8Zeo*#(@NfX!(G<hd}PZDs!D@MxJ$XcJ|&l+BRYQnpCG z9bP8ygs+o#!CT}v;oIdnTf6R8;tTk3nJr)Y<e%Y}Wwv&`DYFgWJvjz{EVDh}bD3=b zU(3bt4{|B|OQz2MwU9Wg0>%jn;1&v(zCN5TH-w`y-y9T^`R1T%ayz(C?g-bCd4s-z z%*Kaia!&^RXsra}z;}?@Y}QR40G}_9g9pmf;o&kL4;dq04o{M=hNsJ`;Mp=;!4}Xw z|L;WNauu+JVwucVs%zv-Tm@e*SBCj4GS^TJe3Q&Zr`zOw_)fVde81cf-YqwU;}uG@ zM&cQ{EzBpFIRQ2}ydw92-;mib^<TL!{GrT7s!!$N@R#xh@VD}4_@{*9<^?{#tAG!? zGq?{YJR44x*+3DN+31ul-vU>a*#K2j-VT?_JK%cqBXAR$jZrPLb^iYZiFPXZ3hp9* z1NWBMa5O;v6CNhBA!33YhNsEw5->~VQyTMSwhvt{H)Pw)awS^BtL3)vI=KVv%AMhD za#whV%=hlxE3-Z6A$bh^xO_4Ew7eAF51aG<1|$xs;3oL6ycK>+-U)vov+d_o`2qM# z`4IfA%;uP%<S_iZTpj*PF5vZluySI1^O^XNTncB(wc#AO0bE_?D{qSBW^f(3IowF@ z2sf9zz~{-`;ZDZb{ymZCp@Q?_zA{@q2Fq-}xj-HakCWM!GeuqkUo5jZX0E&fUL@ZE zFOk{OvLdd;E+kgV55YIcZ1vbIKLy_+?}KlbUxM$J55c?S|G<yR@4|cJ58!=r{1YTz zQsQg)Rrxghrp%x_@5%vO!ylFTnw!t$H25o-ue|wQ4#PjoY^M1`&W6#CB=P${hD0jv zQuDa40f*%RI9q0S<f?K#xTehJn^L(GTu<%|H<9`Jo0jq@xSc$K?LS?VxC{lo<SXI+ zGQ-&nmDwCKO1>4IAa92+lpla+%8$X9$a~?%@_sl@^Zfr65?86<6nvfhJ-lB25q9NY z;capfF2i@oLHJ&oU3wpq!|>y>13xX-f#ds?V6(^pxhH&B9ss{3vy<NY@?`iEnXMlu z<hk%SGJE&_DBlGCD&G$OnQ+{?7m1`QiEaM|oG$+dj>>GDh{<d`swSU=3*`)4(bkgr z@MHtID%?zN0k@XfrqH2^&i`GJ=%#|c@cHrxc%aNih2iow@EG}8c#?brJY8ll?%6Wi z2o}iC!<Wm4c>TXji7(-6<R9Sc<s4k1ZItuio8+4CZE`Vur_9Uk`(<7+@0LfyPs*3W zFTm#fzZ!`{Dp(62kvGHd$lKwM<on^{@}ux6`APT}`6c+Q%!}9n`rq*Iej84cKjHO% zL<wHGR+hhm^JHGF7Rcw|dNN~)G?!E0wz30vmh<7Bav|JLE{2B~WBb=eVx$Th!{g=V z@Kl*Srf0}}6lRgki`C`wP<WNhi`BLA6nK+76TVr#6y6?JVi^*5$t&Rp<kj#a@^$c& z^7Zhu@;dlMc?*0<-U=U)cf#+;cf%ja@%xZCuEZ|*q|9#b-^q`_r{%}tGcvD|*}aL| z^<_9!{u~a=Kfu}YPjFTF7r17w&i}t7QL2Koa6S1ixQU#E>$R405N;=@!d>KaxR+cB z9w0~IVKT3zN6R%GZ2w706r$iFxdfggw}ltVUEwR_9`Fj8m({CfURJM@N5ZZ=9==7M z0Y6CdU23@0w;o}FR{Y0}m2)e8KNy~ri$IEFKE>;Eo^yBcE8qQ-Uj=U8<M`U^ZsXSj z?zjB9$8Gl+zH%$B|13N_fJZn_oIrBB+x(00qNKBbS?)t$g!|gL?w?<T5yCvr?e}H4 zE`n3p7o=vpYrYISfz$c!tzRO3@K*~l*X}D{hKmtR^4l-NwSpV2L6d@ccC`M<uoFCl zWJh=4xGI(1p(n#pyWE{}GF;2faIeQ#coPC7ti&(+c37_SOiaji?okv3*WHdkMDDUd z)r*6<c*=3Dd7^Z5t{1MnX(B9Sljh~+<>ryn`4xL|of`u2Z!seK9{ht9WOc;<-Y4({ z^mk~;E0Mq>rEf8h?>+kezD=zOS`+c8=%c1ukUgsKbSdK{;OWv^`IQ`8z_R3222?Ol zm+nV8B|Ui^v+cCw?vZLvmHJCqH}T>$cDYKtEe%hO-oaXF$(u~&06WvBr@2}A4&#Bf z=GQcLe7=+GWTM12A$2>WYN(#OD&MJ%9`3vIoep*l_ea)QfoWjnqnyzxLaW@W)tyFz zyKu-=oSThMRxt<1|6z71wbw9zH}dgG|B}P+=w%X#b!Km6AJUK+@eYodeUdQZTdF(l z$C?q}&k?Xe%8VGl<u&4mn9s=m_#ntLMtlH&cP);?-g+V0^+JzxY6q@G#vxP-y<n21 zNdCg)UbkfpXH7%==(mFPT+~nWd{0T{u(>WOCl|8vBS==^SgqWjZTH6-PIVg%aW$P* zX{qdi9I$Hr>+aIG*K!6FPMbY*N}~%WEMRo_$&DsYS=eaGC39LeZPCK}c0cW#c3#Dl z+D<&sY37ufGiNWHV$E1Iea^UP^JmYx#F{g0@wiD7=FDF(Z_2+7F7Ia6bFOq}Wjd*D zV0rF(cUgUBSfv@WXI)re{+T|j;-mVGQ#D@BHH5}2eumR%RpDnojmv(1{-AN4$<KJM zb#4)SUZwGioSzP;!_LzDbo2Rq8LQ1=CrZ}gHk(L$(Rz6+1__JPm?4+JaT+th{HtV~ zh!dfKk&lL&L}*|bzv2?1f#Do@o9b7CcgXnbU|v|wadP|*dC_`nBf(vV1$E)4<%aOf zayfihW`E@O<eu<xxi|ckJP`g~9s>U)vomZ8)?5~s3TJ(*l9zz9WPDjXq*;mkJ8$XG zJjmFKlEzOEtFFv7!5)>&$90X>LT3MBc9vv*F>J!c!Cd;D$Tx4F;Zm9o>nPw-4$%Ou z;1M#H_+nbyey-1pWPDjmWX|*onKQjw=1kupW2WQQW+gb+d{~?l;9TD>bFO(ChxwfA zU2=W+QMoa^N9IiLliR{C$n9Z1teS-#mOJ1_##sNjrDz>jL3P-4enh1L_&ep-hEL1& z;4^Yl*ut*Ok+uNYDU#+)RFc`FKTGCJ@OBXEbb@P`Ue`zrK*EFqg9pJ4RcR<(E>DKr z$QQvK<r#2yc`n>Xo(~U_7sDfD{&gBFXD&lxvJzLp(<*-M<@8U%AJT3Eoc@UVuo+*0 zlX>nJ1Dt+#iQ9Z2a%Z?#@oTjEUwj2#tnQW#au(u`%C<qs9pHY8ufVB#Zu`MbU3;ea z+j_-d$H8M)*AI4T1@rM2d8qs5<M?C$8nfrRN143>dqCnZd;So|2|kS^PRToxE4$r> zI8pr27&^qM6?m(%d*u+PEZnsT78F~d4(7R*`O{wD9!7=W!`PlH`7Vs$x@KtnO+<Wd zn;rEBi^vVOXws^@+?}v9xpu`(+0jbT_y;&T@yqA$PvBbc??33vu{+}rdVQR{{)rL6 zzi{|lJR0W=#E5u=UunS|%uGuy=2voXFxD*oiYKS&ulO%G!v2022Akzlk~d&FsaNql z5V(O;N$NxLUPDrHH?k9U3H_1(mK72apNE?1OhX0yz5ke1(vsI=>}mW1g-8)Uqa>a8 zY?I5M1Tmf%DkZo62+UZI`9Z|znpkEN7#Tr#*@9w+=Aj^9rG1MLA(BK_l$&t`+mcrL z5ciehXnx6Lj49ZKLuVY|8cA)zF76?Az_CIXBPS*Flbc==EsZb5_z>`!cf8ZLqByk| zYg*~Q<DXRX-T?%B{vJc5_Tl*&F(rCpH8K)J7tDHy9aF8)4$N9S#BM-WhN@xdmW0@h zcSYzgjQsLY6AW-!=ojQH4zcs}rJ+wT)S?hOK*tw`=An2&h&MCmhuE>}l2AWPZeA!E z1I!Iwgi=I;IESpXu`gg^X;<JMM1pu4L#JQHfA*4C4Vai02?DK!hy<~V)y>;a(_f`C z()(b-=|}jxp;G#LtmD=%jW&#r#>B1A`<R9uO2fZ_5c|d^g?J}CIdlme4Bf+hArymC zL&G`ZP#Gr}x(Umk5n^AtQ0NN`Tgl2;h%qDJ1D{F>F*vdnV)tn~#Mb^m=r@csDa5A$ zl0zF&C1_R4;N36;e3-}~)^ce=J1`CeHR$J_F2z<V!0;yGLj)CLTxvvoSkAeQaRVaa z12<rD>?e*OY!dlZE?k7|V_Y8N{(^uHO;Nc|j4|FqF`Io!ABgSY)becZJ`cy(B?uuP zn0PKWlEW0(nB+L?NQ_T1B3x}V4EuI$8tc`ww;}OfjAt~2g_wrKM=|~iL0E|AkvJA> z$=Ojb=-9VhMcwQ{nCi(GJ4_)g#2O5GHs>z)*Rp7x`ag29hT6OzmSX4d4PA%>VYZc> z!;OVF5KM*fsA|ydQ!AR+hV6Wz2_`qw&RNF!m|{{{b`E>BBP2BL8zLlh&PyEkV)K5G zT&&iQ-0iiZCHBkiOSKRU;LeIOOvTw>&5j26C%|Th*J@nt$l!{u##IaRo@ce~_y=Yk zoFBOA^J=lUe`45ke-GQ=44aQFfig2FJ6XbJ(CXiC{Iiqn66_e&3gU^BnOYmnFG{$) zRt-ivvfCut?6{qnr#4Au<JTC8jbbkd+FSlESr9bCzrjHk1n<D$)wmU4j;kggv#=K# z7u4kV?0BL8adQXaD#9etQ1&T{dZq9f=LeI)@AnUpS!C8puM{(V<QC)k-(D#^0`0*i zjN**c2CkkVR^hAe%(~I4_015&%@BneV)*|x#PAfZ8VphTtoumaXenM+@Lt{M=}a@= zVY8oC!#XZ{(>+=bF92BOrqqx2%6f;hxEmwH`4HOLc%D0<espB5F4!sT-^{P!d{b}@ z<|;AUznO8dV-3c2yneJr^GsGQXLo$_x5eJd&_N|;!sTY$*@KGAmM=G(kH4?Vx4V5C zL|dDOIqkW=K__Bd7}UMBLA07Z(|rn+T5jV^ZVB+`%%x^#*l8;<Gh58~8TX~gthX&@ z3hdxf^pjh+VYEhFvzy(X*jLKUj&nyM(O??KwKKpyFR;F2%TeyUhS8S`&1_dT%lIRf zC^6b9Hdk&Z{EyLI&?s7?(CiPnCO$O(I266h{Vvy@$lU}i8tLBHC|Z`aiTl<yW^5af z-7*$*k2H#|=uyr+_<L@Dt~Fj}+gsW3rk$C*DR>L@+nLFHkLCgEG?Qj3-*X}bSSRg9 zx;HnDj?b;&$Oa_gU#pWD(<>Mg){mRjB-%6gJ?_P~n9?q$v;@}{ES=XR+9j7^%j^>Y zZsZD6$|fL|9&QrtfgmxlrqRn0gL{3`Xso%JxBcd*u?LlK=dkxD@g!vrwwm#Vn0<_m zMph3qqWeIO=)<Pb@%>&l>xIi|UT$J<Wv>F1VwjX<t_F6Cx0><ZliilBO(xi%y>)A* zSFNo%CK)EK=nZ#uGlb#z-96DP+OuVAuHrI20Ady6e|ziczlSL^!wllCYmVhIb1YxN z^ko&3%cD`d-Upnqy(S+6Tf@v4>fq8jF>`y(7+&K}xzD||c{INkZw%W<gIr-D>^b(< zNB^#T)Kq4_$)XF~Pn$=p<0$*9d9>Sk?KqJ_b0XmH{}0SWx`By_6q>`D5A+u8<Jv4V z2Y)eIq>K8y@fOiBfwXk@;}+4{S!RW8FxC0sy48A<o7*y4Co74AU6I0{SLowqwZv*4 z+%np}K0|NV_nP`#zx~aGc|WDd3~_JD8sxAwnnOI(GTI2gKfi4mt(q9&bW_X@ODxW9 z6)ivmSnF2N?%@JVFLkcH3fr&qqwbnk(ZWC^)qSW{wBBIGIE=O%R|QQM%Ta9pvAQuP zkke<5$;HY*KMb4%vP}ERwO(d6k1?y;A1KcpbBmX2b-%!E&^lVRcWvzPm8;r3o3g#! zyr3$ZyN=a!Hn!+O;9KSs+5Gd9Jsba6-9Etpu|elpWNLSx?XGJbtsEbQsbyVIlH=uf z`y6A5^<xvaDt5y<%N)%K_Wmc6J(ryGnK|z7%x-*cuFAYQ|76U<(U3EA**_WcF|OEv ztzJg<9c?*>F6XfOQVg9tg}+~Sv)ufU?e-+*Cikk>n8D4OUCMvBSXQsrsTJeeM6ZdZ zK8JlEV6}2PwT|Tdi`ExJH6QIZ>X%mCJ=P|YR(sZz`O~NVi-wj8dtmg@$iIEeoi9$x zsd#l<^xdF4wx^x4u~tE?ityBEm86R9)1${H2D$~@we9n(#4o`r^qN@ipt0ld!v~<f zc;?$_oRIk0P4mov&oLT@IX`^j)_Yi<56#+a_riz$&}<%V`0(jX?;(1gSM40rB!M5G z*s1K?M5UTEF01&NLG$_?pM5mjSMZs|qo2n<K8$y1^HLh0|IjrO{+Z?}9iMYND;5Cw z@TR$4nDD_2Y*f1_k*I|ww~G^I$OyY6VfHV!x!v($k8Hav;q$TC?OF-5ud-b`;Q?5S zUgMN$+`v-vb0PDw5d4_N4VpXEl`Oy<V%&+R>tQx9nWyVvu7Gu_Qvh#~>%uq7<*;e2 zz(R05rm+IXj+<z#fH@x1SOIh8@rPubkN9&fy~+{6Tr;NS0<HreRepW=Gr2KrLY1Qq zE_)MC+QV%5Hc#5aUEn`dzYlC<U*Y(9@?%3NJ%Y<`S}3sku(_-nEP%Q6rhx+Hu25I` z-29DYZsrzp0o+OEmO5YN%$Y_BjHfqj8YSSNuxXSCWBrds!Zb>tU_5-02A&Adktf3o z<>~M;c`m$4<{59Td<DEoUIyPNuYm8Rbu{fYO)@x~xb)AnKt3qrtZ%XND)YJh*k6_A zzWJWa{lGjRk3*5;F%QVYSf0cK@-U~zQ#u2;@?hb`E<**d-TUts_R@JOz~PyAKpvI2 zLzxHUVIJ0es*(e9Gqt0U$zi+r+)L(o`pX;-`>V1($8&*s5FX-)X0QM!3RapYv(lw9 z{&HAX$~;x9l(|-}mAO|l0uaZ;oqCJRoqDTW0^cE*@%Xz(2_C)=%3P(4kjD|#hfVx* zxDmWx`OV-1avS)t+!kgyIu6?beqZhke<JsSzo6L>rVkSAHOm18!RDcOcnJKP@+ZUW z9LqX$-~di4^a40WV-=RbeD4n31TK_Y!nNd1a09t39Op$a2k3!BYngM$3v1?c=1lN( zn8z-kHDx|$l)Y)`q402dILu!V%pVC)lBdGc<@vCA5S|@ju0p~*2#*0)!&j-&_3#by zZSYO<PI!lWH*6k$$FRF#_PFJQpMdwsY!u+{Ip*($Uy}F1ubKzpQSdwxZ>rz`%utXV z;1GONJ`8^*AA!G;Prz(dV*M}SpXIOMKjc#|FGyJDG@L5`g8k3puQC?=2D5uF{RdoC zJ_py7Z5y|Y<z%>?oC-IQGhoK9<9NbwJ2?t>kuzb&292{)WhDBmpa^CcVCFZ1N68Fs zF+pw)GbASKw1Q{Kye)Hy%-b@2$0h6ZgxMlMGwAG9GH!<IL3k8QKmp?yvC<@%k=p5t z;T`f^_+EJ-Yy!2T&ZRIzZ?ZmvVK7W3&0CiH<)!ce`8wD<6d%L-zY&R#S%ANlIKmPS z!o%sXc@Q4vsnk3O5A#%N9)yQ^f@0TT4$Bjim6|Y5MA<aXR2*lH&vj}1RpY6;aa;+G zlwEpRfK#-^m%!4TKxdgF?JJkS-h=IRVDG{9hVXdRX$4P~JHqB!cAPFb;U&z6<DBpc zB{<>LGADe4%n5InIpJI6TJY_1WB37?6Mj_YZvsAZ%!%;~$VZE_@OPZ!JYpV%M}kYh zHV_ungFlkFH0%z{{HE|pxh?!Zxf^^|=1GZ{*sMPk&X7mIj?6#zRpfa*|Fh392e<+S zMe<6xwtOwj{==-Z0cN8CeKXuf-VS$^?}59^55s-r$KgTpQ!u*&XT>q1XOS=uu*3Ud zKFG`oya+F*xvuar5#Qw%$`2ra3ynYO4!l*y{%GAHV>hzykuloDv+1Z`2FD*$0sqQ9 zC6~j`$z0Vh%iZBaazFSeT?4@9GoRU&nE9MJw${@4xn~Y3_V(b6rr_{`<7N-9lt`FE zh`)qc2}h2VD|4=E$o%zEBA3D@`a9~^fg3Bo5!^!NUqW^(<~W<fY$2h~gZrh&6N&an z3{gQ>c%<AL9xwNY%`@m2m^<1G<qv`9$-`kj1kDMIg0Gav!mH)+@FsZ*rf=P<#9Ww7 z^BnjR_(7RJEFY7(lkStblfEKvhToQV!ym}phmOhoWA=^wHvB(0&WXK`#4jrN80M4G zSp|tRS5(GH&f-lS=JPyJO|A?V%G~K{$vE5-kC7MPcO=}N`Gtv}cU}K+Jn_6Z3V0$i z&x^xZF#8yDfEdiDtZB?^;&E{p|0Nz52e>Dj$Hn0~uz6e@=DEZ?E)Mft!v4t|5BGzs zjj{f@Bdk#Y_k#^`C-_ErD158T?YdK*0h>q1F;Z?m^XNFd2!29!mce`F)$nujCipG$ zAbb&o4{xkx$tPs|ez3lgxvF{ViFJ5%{3-K@U_WH$^N5Jb4PbULW_}O2nmiD$DaVH( z(Ughe#5uW@jHK0G=IZS#*M`~0nDy(y17uE&VS1V03?41FfZ3YNe4a~qyM^um<56&Q zghrw>67yBS^Evw@GruRiR6ZZRTILe4PcrN9klP?%4Bsfvg4tJ@buNQ<$}8ae<V`&P zKdgj{f+ysyFgq@D;9KG6<(=?B`EK}i`2qNS`8a$`{u2I1{sI13=Fd1@>14$*fpjD? zn1C6JjA1ir+}$w`$!C?|CmQP4Vm^!_tASh#ZYFaRw3fLEI>@czZZbCkAEf7aI>B-C z$Tt#WkT8#Y!xzI7RcRwUL%suEBtHn7$GK6TKex@(-0*X-d72x30X9!_!-rvZhUSFd zfp1GVZoP-ZohmpAvtu+XeFE>Lu}dez&-=_L@|mBCd_Iv+<NRguDSVnIs1M|tuz9i@ z`P`9zWIlkuOV+REL3kwi7wJzG@Z`g%>RG7@oG$Z_i^?_Nm|Or?lR1GxnMX=3xgOj= z=8348+ywid)mn*ixP#2?)J5h=X&8--&AA>e^NcxB<`Penv*B4XXL`QO{l+|ajq&g- zc{TE<aHLI<Sfffj8*Y%h!dv8i@Vzt^i<{#i8RsC2ZvtRG*W%MM*Wy08x;t=V<${WB z$D(d7-q+pycf|j`(Y=aaecb>49$geTGRy6ECfX03H@BTZ?xpUx{6f#pKcaZ4$ZU7* zA1GYv9z_y8LmQmM*9><FzgD`3@fG-Co?GKj)S2ea{1eHO^WA5W44j_tM$RF7t2^c# zDnI7#;@6GtpZE&wUFi1v3x%uPZGRzodXf7blWCjVp-0JYi#M-DAC!)pkD`~!Cbxl& zug2~Y+gW6fcYkK;3b$JTDaU;#fYcf{oP@7w?wBN}9$tsisZLt9yEO?tPNuoLlF(J8 zX>a_}OT4P&6tV+940X>Xp?72e?<mjAaoZ-N8%mpDIDkxl)6a)wIDzM0a~CE%Wq~up z+*|P-K6W?}^<)m#?JRaf2^<{neut7^?djMm?*1cqJ<7VfYzJLq+XbCEDXp89H*3~( z%c%Ukq^7M3Oy|-YHx{0#8M+-~uz8plS?;)~Q|&^=D)^_f$zr6?*`x`-0zqCap|c5U z<16)AekBKaUmcxIHYdI=Wu~3R3&3FVawJj~m}<%FNQcfMyy`=Li}CKKQK#4*;uc<+ zwxQj2R0)`$(YF0ZBy8FEAPfK7js8U^#ztx9yPvGdZ~w2G#D7e6{&0_v&EHV*NxCyI zDeznJ#<iz#8R@PcgH5*6-G5DPaj;eZXZ(%JekrzJatkBq1N3f^`{0`yW!TPhkqjQg z&L3lsA9OI<A8~Tru3v@!@7_KwTQn|j%yk_&605l5t8hj%ejZLO_H8&@HOKk?VJxHf z3GguayW`KC6s)B{D*sLg?o7fz8+)PnpUqMQ^M<v26~6+(H8|r1?!;zE%4>{j*g{V; zk(T;6CWI}-3uJ5|{QAe!X35Yh%sK{VjJ*`oYd3W>hD%A_g@4lm@8C#IZZHK7@G+oZ z692FUuE#6|gDuH<s1QsUOY+q+!PK?n@AxN}b|uM&vx4c&MK2-tjlhO4!dH3|2B%0) zX~wpN3_dTMQvLyIVUQdqTJsNJ`e2;eDyN<|$kcH^{5@P7@y3(SgzF4u_lexJZX8L* zNi0KJubH5gk%fQL&ff!~Uk`icr1e>YEbM2GVG*Nv%R0kLIE;v8Ic#x>JA9MVmCmUY zcj=jMl{lLZ7CX1$-%Fiin8+e$6UMU8nTd%kaHb=FzQYH_E^+?E8ky(twY+nkDDu&b zXE>^+k3E5LNAXhishrXesQaDe+>Ht!Sk9~1=uMre$SZLe4hD<McfMxKVHar(vp&w= zh|U2NEe$%iW16<Z_oMB%90rEKU9!M&j49(D_I^xnfcbMWp5kqp3_kIcv6r+m7#}WU z-x@GEgU=9W9DET@bQQ{YmCnex597`_!WC61V>U<d79Eaf&YLpT%J_hZNCscymT{Ek zOJufVnt}DG8){n0tmI1N3y^Zynr=C7qpt1n?^VDl#LOf)jQW-AFhX9?;a}bqhmZ56 zI`^SYn$r|Rr8{%5@-v)Nj5*{m(pbEb72soRm0Fp0|F=*zIbvQ8@34c7<?ssGc1~ak z1I}Mqh9qYa22OUaMSjo<oQJ7}n{yGf>SDd&#XpQQ=<p)Ka$d$iw(|iO!^uF!B<C&G zah^g>(BZ9*lxhxJ!Bd?Tn1?in!57n=0#wSd0w21&&W0P6u0|f-Dl!hkXN<%k(bL=s zt&D8UUc$K<ZCv}$aH9yfN%R*+Y$(roJ>6~pXSk@tI1C>Bg)`VWgS}9qztdgKHi-Vg ztK{x6o-*+!5w7>1u{PM=O7x0#c5nMLT-6@r?)fuZ*10OijCY9exET>!h*g4jh@8e4 zM#qvl=34d}D49`3?-1d1X2sZv6z>q>Fmqz{-NJL>CUM3P#4AKNy(?p5v8vE%h>3Wt zFH4%6+Dl_><iIOLc(-q5jK?QlA;QGfu@^ayZB4aRv7sEMgGsE3@iA4rLWGlB7i<1c zVpHr5u87Vo!7D^!Td}_J3K5QOYiuJ&*VQC$ja|o*?k2H4#x@kZLWGNQN9-de@R~6s zcE;Z4RQsE1cg5H^fmetyRM|Z-UK-;SB1}9GYtBtF)Fd8`@j-9CLWD=nW3dZaZ<Nhu zohM^YaCGDCwOEgPW7WAfC)(WP&&6^$hROChBwmdD#yOp8KZ(S_*oPd!H2WwLuf>)# zG1n~kkr*!x@d^>Hg|}mqxz*;I#CtK`f8i@cxVk@zrE-QYGl`=yUT@$PA}skh)|Hzr zZW4HfNa1EXG9qv!dGn}9v0Y_zJW?>KI;VGa6^uK5Gp2^uhj2kMcq=A)J11;qJj`X< zLG$$?+?we;r1AO??skct`BUG{Y>b_G^O=bD<<B@yvoE)_BSm4eFMr1M-#H`dPPHQ? zc2oB{JCYZUVkO~CAzbGfLH7|<j`JjgH-&I<GGe?7h&P4oM>*dVl8o>4`!R03DTH}? zQwYb5;hE8f4rDNjMdo>C5i%H*F0(D2mce$K%yz6(DRa@R$yR22I+AfAwnb(KdX|&% z3f4<zM<%i`O%9S9z)acio0+m}qPQx$d%bUSf5^*86qTZSo_R(gQLP$Joc4!iudBur zt^JX`26d|ag~9EkCf~}x)!iS6RIX&oA7yckI_{@|NI{ru!G4r0!K%5_jU+|NBBoN$ zfJWkWMjqbsG(9O&9`4I&-JHx>&g<dcmlUakhm_t<iqtMJB}+|7AxcYnV8z%=lM8XM z*h5O+NpbU&BX<VAPj+8Oj!dk_ZVYx0vs@UXxese^ZH`~!#b)9?%o4Dde(@}KKrnK( z-PwIN7^#KX_$wG`fEU;|NHM9QDUr>Ahmzb=DP|tCQzOd*Kc%^Ds!2YJq`k!Ll!m%v z-05kN>Uc}vHEEHlc02dGv`AT<ww#S)T)Vt<?SeCiy>$Y9?X-QCbAOC~FGpa5wVma* zOOMnI{F&lTPmk1S_BwWqM*qbgg*VG!SOykov<3gz-*UyUO|KPy>@>O`!`lC2-Z=NE z^hinewJ54<esm(Q-V_Hn1>GMp#(Iq8SbHco*fT_LU>wl__!Q_^4%BAA!_(<*n~X?{ z{Ex8O>@2f!*>k>>aS82gI~%hz&Rvrc$!{3vAROgJf}^~b;3y3^O1Aiz(FWXiG9vZI zZo~rH8%$Te*_cCn>!(;5Mc4&5m`%lYn&L;X@JMs1Iw4&)*RnU6(wRt=n$@t`l(J2v z^k&ZI7L&f!9UqEx>&+I6VusSNZwqiFM>!Hq;`RX7<v9-Y7pHxPDQ$<f+^`I3ZlFoH zXe^s**>{?%OWf~6k^Z^sP@@cQT(InVNgUrEq^-`UlH6gHBIU(DAjKy_ER5SK#ifa5 zcS?E?Uo60<Gk!Vms)QXQ$$hm_q-tsj_Cc%j5%-%)ks47xZCo_pvg1jdwOMX%IMNt9 zQm=5NsDM$%xa=ED+1p5!@?MI)F^R|0mtpt1aHQd=hqyxbn<@;_Rb0d>`;*v<gHHmN zzRcD0LK2VZ$xL6w9Ws%=8R^7wCDLCa-FONr&f;}_lZ9^ONTeiw2D!y2u^H{8<Tc1I z$MtrRSsO{_Se%7)@t@qA6X`pU=GqP>a~|GBs+4DB^sM8$`<m&MfSqd61=vGNzvVoq znRGLx%lYG)^U&NL5-{D!nk;aiiA0KqOh;*PD#zB;%*zg@U+26vP3985fplWtnwqgO zm``Hf66y1i<|-{W^L7<dU3<9AqLBfWcfhsJVoWa*Y(_kh>AKNK!@z4P?ty5eIG%zX zHL)HZNWL4>8pa*htcM58wALZb<$f@koAMA+iRFCA%-Kn%4|B(U*rZdiqa~Jmw@EXO zNqI-#a`RH6$#5>}d&&I$?oM|ic`dr4T4E;NGcz#->BLODXJ%qO%gx3}q@O{$YmU3e zi8L+x7&eQ@%-TO<Svj^=<1wLnm9fC*vfXfIq;dUT+!~*l(dFZqC}reZ`&e?YDt?+V z&3Dt;$4&Xw?)1z^&p`}fVCMz7+$b|Q-R-S+qJFVC%jE@mn!5?Z7V}yKHTjGGDWrMe zCx-h1DQ=m3GnOnjDJwFy=6Nx16z7sT3dUGqCCgNLz+IJvqh+(ZCo57^<q+$dC7&7O zj>aeiT_?FeW<_#RDxv+Vyt12_8Oe5^h(@Ar<LpRrVO``Vh8Sgr;8Xu)^QPcv924w? zG0br1XGc1gu}5H{+6q&R&(;^Sozh+r<bn7a(wNW(*^!22zrkh|vyxfG9J&>o1<WeW z&B2W1{XHWQw}0hG*+@Rqo|wYTW(vcRF1n;C{tO1Wqpe^PC!a*&Gf0&dA=}<+Du0YL z*U7dZ54Y-Q=qkg@v~D$J-Q71TN2)~m$a2|4%YMkr?+xzh%J>OY*UgPZiYC8=vLZbF zXxT5CiT#Llv5C&{q8UXCZbjZXK{;3JrATuEFPqdONR>Xxo%Dc7A4R&=ji^@2-b3~w zlbPe*8jEx*Y@UZP9pIQg3G#Q|1f)wDy377F$Yb{wH@Qk=XzmLbFst4xXw3JX6TJ!U zS>(>G5{Z?+g0mOijl}DV^BZDZ&N({?CyL6<u==oLR;7(RN#!z=S87(@rS4NzBIi|G zfW0`>i)B2sR3<9(Z<*EaQrF3e<lDn58stP$!WA7$BG=dzM@u7PvQr<%xi4Ui`nO#g z3pZzX{1-hR@!V-+_lNbtjDJzLFg15f#nCpA*->}jeZg?WQ@tZu>HoH=r{cB2kw+sH zOD9GS_6sv?v)4=UVRv_}teiOCbL3_57l&ule-P(Ee%|-x^G2svhtKtRKI!xKKL6zN z8K2K3j8h^${B7fnDAVm*JFB>~*q2qyXa4T-s<v?p$K>XOyZN&ExVvg&srb9bt2N2z zi+rBt^Fp85Fyal%pHiOJ`pjQaUjFSqGcFSH6HB$rSMZEG=Cx2x_*Gxl8}8$EvWne4 zV{<EofAi)4<@Oz$o70XzxV%YJ@!9l9*M_O@%jaE1uYPBD+l6*c)k(gri+rBt{<m&c zahyNdydhkl`NPf2XH+83{2k|+ckVp@*XQ?r{@&-Gd=BtWMW%T}4w@bk39}pUm!F+j zcUD!O3w$o|nL&WO`i<P`BXV-$-F#VneCEA5uj+8084JkE=TA$|bA9GdOfP?>&%8wU z@^46(_b?Lo+Ps20e3kC?nePPl>hQ;^*Gc#}pV=Pf<-h7Pf6RLMpZa`~!Hm2D#u4(& z-@Bdz{Ii8W`uwE(9QL`g&wP5ot6$USVxJjx+0^0kH}n!Pe^`41ck-F>g}nSeJ`eVJ zxX)vK=IuCd*o%Cg1;@RDCB6dQoAdJdJKpPqy~*cWeCGW)uMVRtd%n+S{{Hv!pZUiD z>m_$)MI>kDk$>{ctvIjlQD6S2KJ!As>kod~XWo6Y@%w?FRG)E=;P3n__tRmaoOo?t z7T<p84aOU6p4<4`-e+EepbNVB4D^}NkGy=|YxB%|YM$pMoY?gl=GrUZo5MXbq_XE# zKJx;{>+WuPj^nonKX>}_d9Tf@!zkCDD|~)7+~c1D##izx@tVo=dp<MNl9&ID&p)|+ z_e65yfBCYK@C(4J%IhnyOMVrftNUE&Gq1nA`sF_JHS}J72cNqqJk_j(-oAo?J`eSo z7j)i;rujU_=lMP}?2}hN?zVdhKLc-eXFe6lDZR^Aa-YwS`22*s4MQ|J=*wbgCvSud z?c|y9i9LVm{)s7=%Si7T1_pBS9K;2o=X9U5ea`W@hR;Pl^Rm<%Pb;50B%IhoyZ8$F z`aIC*5k8Ohnb*1A1Q>PL^J1SFf!NDu94F7K*cZi1+~7{=nwt~nb+VUrm(L8t<mK=7 z`AMJm`uw8L2Yu$1w>O>-edZN7@<*Dz>^olpV={RIobj2Dxp?_OpBZAw%XfS(aKq0; za3}YfNTqN~Uw#L-9rEK0mgEiA&u0cs^71e6nb-W@11~dup6@e56MJ=*`+T*}*C(9# ziLu^Su*1#lTPeq#{8C<SRfZ$>M)Zu&Z@9O=l$SH%17Ft1KA-gYl+Qo;{HxDwm+&SN z_PMe<7qep5beG^OUe{OB(C6kpxAvK>8{Sy^`#j9&kv>oMd796&6Lt^0oR=AABZ)WC z)jqHDd6Um<Nb#OYy4&XmeSXAewzqio5BmH@!inSdEnmS2pTF{%p@qE>@u5r4Y`5_q zjLPsi(`QB#_UbTFhUWtIIrS2CeFY7T-7gO0)o9nzm*3TAHV}Ekj`Vqg&r{qB4(6TL zj%`O?)lEL%;xl9WdUfvgd6#?iU|x>>q#J%EFDL%GuY>`5y&>NBnQc*C{wbdsl-JAu z)n~R<dHESWv(3uOubyyXb20d?SHP!NJva8b+-J5!dC#l$^tr#!gMDVJmsfwf&vW>2 zqF2CxyPg?v*K^!wHkWz%n|<Eu^LC%__W6FF*`j8~!{y)aCE$ZTzveUB;=BnT_xUTI z8B5ozbI#`gn##QVbf3d;+$&(qo#z6dYx!KyXU56(>bLfpEq-2pAD<Z-*UKONkISq{ z|0JvneV*m>Jh#D%Xi;U0p!aCvHlKI;e2>p;G4$#`>oWt`dik&Te8lIseP&xD>L>Qq zuYCnS`pl@c-bl~-%#OHTKA)}dT*c?=J{S62+voax=E5784V`uY_7{9Q_}ty+-aZfX znZar80t|=`8%XT}0H2F}p6ByI&s_c`UIJd`GlS6D1<1tb2A{Y1e6!CF`24WX6+ScY ztX+T+;=|V3={9fU;qy8R<p282V6$F6n{z#X@AEG{pYfSZzFvLD-Ss+7jSL&>WwGto zW-BT_4SjCzGegCCb=WrSxxdfDd>-lZ44?U&IfhN_Zi{>c3<K+pl<mZJabkwn`n=g^ zMt=3`uz}h0Lq0#@^HV;*##p!B0DNNI^SeHO=rbd{dUd|=nN8eYJ|nz(PQn$W=Tx8B z<ZbfN%4Ox7gxh;W<r<|e=#s<|xAD1?&)wW*BP!>FNBOcQy4NEsKGT;q*Jn1Cdt<%E zXNF_-@;CU*XW+g3?LOb_^Zh=v`5pBW8*{&};GoZZPTm_S+vhzq(yHgLeE!yFMq2gi z{O0ptJ}2dJV`|-H;Huek#An_L@bU|NuI+PupPTv2NUPqk-F@!uxi+@jKraCg^_k&S zy@AKOV-Dd=&pQxa)>5Bu@Oh)p+kM{Y^8-FV>@)9Tc+aN4;`5P&6I<(TU%`hyf8sN5 ze|RJM+2^x9^HFTC4!ae44*4AOxoXwP|5PgQ6_ohQ`z+pw+W6eb=Wagt@p*u;+ve@O z7NxvD<BjJEpI7*Njl22nyz_?g=8aeN37?<wdB4wxe16?$-t_Ut^Qn8{HEi!ceObJw z^NMqPuI6)*&t*RIo{`Oa^Z2y(xuefreLg?o#P;s*E12N(6rX4KJjdtDe7@4>t9)MV z^DRE#md8U?bA6Yu;J%8!uSepkalV1e#*Hj~7(vm-tto!^wq~2BNqlag(QeL905`X6 zG$8O(k476IKSOA=Rq?ZrMzab(-_f{$=chWR<Hf1ChvrLH_z7a7UK=!DLE<%%hIwxW zzjyfIV|rf0BwxtkwIn`CV<GwZl*ZA)PgCB>z^3Pi4@P;H^LzxzyM|0M?bNue;-@~F zMR0qMpUpIG&GEwyXWnn45p)4E@iDEl`lVoEQ0PxMpEdCQ_^_M5cdq%BE=>$OfQ?Sv zDqQ|cu-d)g6pMW}fnczjum&ymFJ>KX9TPnh=GHN>CSYy_6EG9zn!j81x$;a53gqJt zqzTH)@o>fP9cV#DzewJ=druA@22MnoKn{ydd`y_D=Qu|P*Mv=YOt=U(;W6P_Fncz# zP96A+TpzZu_b|UXXu@N{ZD11~6YdOW@%7uR)D;O6eFE+dn_j4JAJ{~nfcwKH`UE@> zHqj^GVX%ol0bc;O)r7~w9p&-xU>Ylr>+AyA?1}78$AVH6OpzPF7t2lIxpFJ`3b`%J zKwBKPJ$#Ma3BH-eF2{|yUFP9)myDgldVppJCR|vV(8C;nyYU`X;-0uqE`VQ>xd~pC zOW-$U?pg23wc(?3J@_-ZA^erx1de~NL^%?_$SvVBGPhY6i@_)%T$*edYujQ^Smt8| zST$uXWwDGV5UT}^b&fBqt;}INCmc5e_f!D~W;8_(z=6lnSXcP6ruclZ%zb;V%r&=2 z#u?9ABJ<c@As4`W1sli7&3!{MjzlJEA+cEnbzufIVm?<F`-9V5U3be|Tf1bgp-1J8 zaD~i0{1A;J6K5#vh|C3hN3P5>0lT@e5>IEx<r3J0r9ggt_;=>xgvt^9C38eU9M#O{ z5g(E{o=lnJF;OW{hvTWud^7`cJPqME6C6>w3b-@2k+~W>$~+(N{cWtz^Fbe(Yip3) z7#<<>s2MBs957ktzQqn;91qr9+?u0AI~1@tH4D1ISI9l#<?;}Cjm+bIi_Bx4?}6j6 zli=<0T=-EMOUN~3B2mCx027HK6YHOc(@UzvL+DkxHf$nMV1RnCi9`YShD{_2m@{M| zQNSZ$6Nv&I4Vy?5@C5i5jdM2qr@R18GQk*7X*Ck*I2UtH*TQ_Xfxa1z$q&HQ<Og9s z(ZM>q;o9;Oa6@?y++5xZx0RoTJInF?Nc2?VMVLWFIntNmA@V_(FP&rlA$Yue7@jI0 zflc%Y)Oiaw(I?<{U=w`;ejoN0_!x}n6FC2);0q+K(}=!;8K{=|Kfopu1$+*^L-~xi zVWLkUpYb;M_z3GW-iC=j0kfaiUggK&=Vd<na!{_#K;W+{!6z5qmg~bG$PM9RaufIq zncb65$t~fZ<Tmi{az~gw!Z>q`z2V^0$9O$F{HoA#Byeb2`6@utV*g22;@OQs-e~@5 z<_qX(9*X5MciuK~Dcn)!&dV3gu|9X+K5|2Nm|PCWM=Q|+3HICO0Bzw}a#wi1+ylN$ z=H9+k9trbBa~yUIyha`mZ;&U#H_FrCtqI4i8Av?D1kOBMEqrE*MoWtIw9FIHez^cX zAeX_1WiIhsGMD&$xdHr%+z37)H-*39>-RXZR!ID)g7)wqaxa)Yg<0o(I4BQ*b7`Jc z@TuW*i5x(FT^VO=tFeqPtA)&{XNhnX7*Qpdk6Lh~+$Va=SgY0;nyUn#Nj_gFb7Bk` znZ=z3pOrqZl{v3B$=rvw!*LE!1Bts-z*WkATFkElKP+>VzCh!z3%;yZWX|XtGH3L^ zGXEU2;}+`|z<l=0i^1|gIi2T!zSWKeAyi_oEE<1pEk2z<<CKmV%L#J@IC3FeMdqHL zFV}|4<i>DaxjEd9#-YT`!3P<#s$%_fV!c$rRn%YRPB&EMkBISdP1r=Az=*hW%~U>* zpiAUd@M5_Q9GCe=?kc$-e4SS?1&Q@4xDa;bi(vNl;#~7c*&)w@+1rcx3*d+3MKHU` zGk-Dsw9Nf%zq}G=FG$vjUya0JB{sl}j>>{f@F%hhpOCl1Kgf5&zsh&Rf65QTNg0Xp zJO-!BPr)XN1;)P*&gSd)II;aml(7=lIkycvmeDwCT219@a4VTRY!{i^n;rjIzb?#& z&S-A?VRCDDwA>4xD38VT6QL_Gz<3mx&=oMxRwi@>JQ+5jD`0LK6S@MP4qvSianqQ{ z7090rZ&3a`c$+*QHqk0jXCZta^W#WxdpxL0+#LI9EG`ZP>wwHPaahI*v)+<<6tL49 z>zBZv$hBY-xdQoI6DD#6+ze*FYu4w9F8-?$-I4f19tuZrJo45fHwU|B)2VQtjH(tp z#xb8KE_RHgc@Ahv<B;L7?PM+hgD5i}N43=};kb#V*Ixw~-Wn=%yRv&62WSdUkUPQ` z%3Wc0m1CVA@FJPpc!}Hx=5vLtGZ0=a4}-5~O8^T-AhDeV*t57acgdX72V_*U9+ivX zXXSeEOES*~M`WG@K9sw_CuFYa@8uypE`L{IB>a~=8s>wHoS|`WNS*=nF)!xx98g5p zOzbPQWuDO33y%2?TrTtE)<(wJ-RcONs596Ht?nu)g4rdG19OKOAlHW{(FKW#@s)ct zx9e;fe<ZC1GEV!}<uZ5JWioeI6QQC2Gl}UZLR28p1O+BU1<d2s)d1(g?E1!NG2EdZ zmbo)NA>%6%p#pUxFkcVE`dnfYl>+7xzpZ>MTOuk&VLb6y&V;2vrFtkZVJWa0II&+j z0L+Q~DRa*^Q7Mp*tVC1_n0vm7N&$1iCMpHY3G*F*91pfyBKib&AdbJ>M1ep8XHM%p zR)RUw&NBbJ_L8}(2gsbjD4CnjM4!O0Jc3O037CHsXQ)nn*h~xCl;gjO`7mGqW?iQQ zN3>o>ndQoL;B7KbCOc#vmb+x`?d%c9k+y-KkvqaK$mhea$P;07j>GvM16+i}Cn}f& zpO7zy**lJPu7tmrm%;&TXhs;}Su#!Ljuw%*CMwHV^A=xR$ojS50=WUt|7A*W$?D53 z;HEN<*LHGmxU1YB?kNw4N6}@8LvDi1nYd8qwx1^#z)R@S7=UwkjS4t-*UNR`jdBC{ zCYh`EHn|;qr`!SNn-Mt^UEzl+Zu%zDB`>gMx%+VtAvpFfcN?Z4tVX`OBn446wy$ts zM>23^g<B()5js}5v+#}gvptiFXL`rG;WX5GZlyam4Y>vGE+&7w$~}i<;IV7me(A{W z>TXL%_Q6%|cSr_~t#aFE;QQ1ncP+jVs^Mq`#x=ri5aJY9yH|!#y7gN3b$nys>Xndv z>N<B;B~$qsCO55dBVi=lx?{pfuDjlS5Xr#V>)mtA?&|i9V3c_4488(8*Sg<DkUPR{ z7e(^O4er_~lH=W@NFp*x0|yTw?{Swo(c<9bJ(l&HdoO4oa1T3pQoF?c8DD`<`nokT zqh*LH(k(MuE9hd&KIYENj1~uO{KnmalHmDcac%E*8dyEseLFMi1j;YoIP0@2?pZk4 z{bKwuF`+_AvXHzI$zvwj2g$%3+Z~&QF^rvo1J7N*sVZWTF#oxL`yleeGcLtU;q<Z? z8*H#^Z>gG}yc9q8-8YMZ#lhDiww2_re+$7x%7;2xX^AKzjhk%z`19PPW-SWbx&O(i zZNi9b!r(TqLW>ke<RbW=cohu4h=3C%{0anb;Md<_M3!Js1gYTVDMC}+l=#9zaDb*r z{oi3kR-0jy2lC4fOiqLm8S(!ljL62Ki?iK_=j88kw~cU`nRp^@d|BG=iuog*odHA> zX%a?Mn6&?2P?0-KP?1*>K}9}PP!aTdV^ERLlX0>(K}9Mjf{Hvh*1z5xHmH)^yfrq! zx?gMC`4!d2IbTLYcjAO<*TV`q7ILGro&5OG6s(*;>i&>_6Fd?yYt%_%S&%Uq0zU>} zFJ#DBCel**MsaM7V_d(<sr(USB8GgA`NH<N14E}I^Y?h_wfHA6hm&Y9lB|Qd2qyIb zO9F2rJD7Nl5dU;3Y{+2drVM7~bLsBuvz;nq7$5_&LD-0smWdfeXb`^cFTDa8DdlgW zDk`(xD5dqUV8$5CMsnIJHgSZ$<C!;P9)S)qt}tF8#3yVJIb>X76mF+EPOXw0ENN;N z4w11MBT7zh!Cfpg3`>F+t8jTjt=u(poYHU!Mv|M}?I?$y>^?ik$&FXT2-EvKi5%=~ zm!q<ioY8zNW;C>qe=$S#F~)d^zp$?iU5X{;k3KXVhVoG5^3W9gds(OvkFHP({=GD` z6q8sKT8FVN46%82LFgTfVSZ>ahPxz$Fc^465P$v54e^=xIdLn{26Z#WevGj?$)O82 zaMH_B`8&J?2V?xe3h{yNrlB6lD+w*cpjZ*tW8Ok@rlT%~S-+pdOhd`iU?>M0*~Xh} zc*zrD=xW9mnSc?6?%9TFX%$?=&{M7Pm5yIYZSd|w8m|<>fT4ZMz~uC7%u?v!GjJlf zNa$5MBb||jLr3n0E2T%>0Y`IkW~^q_qs(F`k=M)|RVv?tQHH+ectek%f*s=D+(2jz z<}oS6yJ^WG-ggUzI$+sSLgTS)siEgkCoOb{a~7I`6`m2=!37I3jv>N_ydQGc&vRn& zGbpk`NyxNA8CZvb(0uOLA>K1e4)Iy3pp|hOvXaAF87e!(XF2f-9}H$=7Jo!m78|eg z?Qk;QDT9kd{#p#D+N^A4a~}y;!V~`(K{neP!(o%iuZ-8>gd=t@mXv36M+|4#x1d6w zY&OD&WA^<>JdiyaV+rTk+(jSG=Cx(Gnn^sDy&dxwE-=$PlKpU!JL?iBw@VL>sEN&X z;E%HJ<%n9?jP!df`y@xy#pWjYJexna!`*B~yFHoBr@6wt?DZ%)8+$C|)@)xbul0Hk zJILmiO15JK7+-j(&B(VYcI-y1oA7YkY&km?Wz7prDs0Cly7}{+I`zx2kA$a~%q%;` zQ+9a1&10{!9m~h|2`{$iB85P8f%fj)`A$jT=Tz67?=-U)xUbH4$^#Fjy7mI6IB-|G zTeiUI8aNnqXDo15l<_Wba-?|_<2Ofrq=k<9_c0rhb_}nZwln0$7CLQ)KhLbeT!fVL zU$HqN7jTx-(s}zPGKx-5?}+h5#+V(_#FL1O<ESg8e}R<}8BaS_8k;_yX!9rWg^9X% zEp&=X8BaGl$V@z)!G5Dd%(_ay081AgcDI@6NcY=?cv6z%ijLyYxd=PtW-W4x^B7>< zxnwamS6X^9HmkFUO<<MM_olf07dcf%Kg)gpO70!?v70e~Yib@wkdpiY{!QZ}ercJ_ z4<I`c1)~KgZkf5xY)J>qE59;ZC1$E4E4HRna1wU+FLIifoy8g%kTvjGj4J&Erj|9B zQ?t@fBO~G5^fv=;{-sXCxVZuv{wu~(p3d!^W!7Y?^kjMz$J-`-A4(H$o8A*^HETRi z!5!003(X|1kgn->Vo9^6(B0Ba+vF@RLeF&5J~fB?W*;kK0<w~`C;p822(8E3v_d1c z<6k>;1VaZxYcZEep^nH&4jsdEf}!omNwG2*`#rgGOE%1eF2-8Io3pT3cIZDCUm!FS zP6{!CQgVpLS<uQmkl_|C#!FKdx*ZlfrI8O=dpT#$%G-t4>nwKq;$^_kEq3bH<QB9K za5?$j+X7SbAZtFy<a{@DnUiN<T~T(K6S5KBt?A`Xar*a|1$(+x|6+IS<xcC&3o%>v z&LoZl_mQnebKQF`cUsyp_t@pm(7@4Dx8)U1i^5kiulC-+H<&@*b8C1vsv^yya<Qxp zGu^dUV7BVHA6?<px7$^uFTo)b*qh|GztS6et{Hk6rk)sjt{IvE12FXFEAbO!m>Z5e zEfdp9H?@0X`4Y9$P3=37Zj|Xxi96RI%Ez~HXNjHZUcA&9npliR$($iJ9AGitT<Ubk zV&pD!`ULhQyHl4rMK!o>?W>cyaqYq9aqA+r48!34R;`-5cP(>D1A8*u!^@l+b|d%H zGG~Nc<aS%`bn438+fFub13Jz6TaRSpN;88aN)B?h*n`e{ma9^!!Hw2nJ=rNi?wq{L zwc3@thn72yhSx`atX?LrJiW)FKgFmz@Lqj-zaKHCj*T#1>2qykzN0FAo^gj8k?$;J zdwKi&v5fXWjyo}uPP5$sE1Z%lEislV<GB{rVFI~?)n%o7?FuI^e<)6_p_=C0_c9Cl z7csY#H9D_xpIhP74!oT1e!aqJl*`tQ$^%=VnK)62yS&xqhZMKTN~dAqgCuvtN~da| zBIsVR5-aLD_m-7TFNAeEvC?T;?HE=<)plGXt#HMj%Re`{3>t5B8SFN_%BfrbJdCW; z=EW@JAJAN`eycNCX(P=(lcoeO^Ql;Mm9sc2bw4iO1J<_xw-0a6sCe`yC!EQLw<}dN zxZf%I_YZIPf6O^NK7JpMW3CB&-lDN-`QeW*-W=g)5x%{SL+7xfypBV!a@XQH2cLVm z?XiXU`HJS=g-<2qc^!uszSHYCw3c>wiH^^1CfEXkPcANUy^cfUXzYjlY@)G;@bfrk zlwDppe^1LOw)ks|`E2VrAoD8SymbZnMexVW$3n7A<MRNf&qPNgzE(jO_y?KI0Kdos z;j{7xn1PNs>?oL_Dd;h<*VknVT%>%q;@6k2gImbAarrwcaR=O6-U$zp?}AM~7EItC z_#)-s2Qvl%C%g-e%MZZ}smA=>@J9JDc$>^)kf+NyEA2z#5f$u*pOIgH%^Ols=Oy?p z<-Y=dEFXqVpA*!113s<%58-q2Q8*1J7*6XmI7>c(>07x<e2D_nw*-~Gh3hE)H@K1f zC(KX`91(8~pC|LOrjyL~{`HWHVTN^L{Ze?a+!(&V80(*}Ss1T^_V85scG&bk!N5D= zOO<~YZ2Fua|6cf7<v$3UZYIco9Nwz@3fOclLH>*IZsi|<pN=bW7>SqUH{mzrk6_cE z1Op$3k178&{Iz@*{z3i={zDF6XHCIg&!ta?E6L^^)N;HU3i!v8l?vfvxei=cZVWe; z2f!`lF)#yAaoBNiXL$l_e$*hJp#=LWpD|X3$n2yzF32WARN~K#sVZO?#u@T__!4;` zY+hi3`s`A-RQZ>~SIg{PXS$G}4!hB9Q2wp(jq+~Tyx0VF9^>(Up9-Ep0pq!GhW5fw z$h@%HEAzL^^D@s12W7sY^>z6i%+Prp4;utb7ZNxd{#yBE@DFqx1s#wuZ!m!e!9kpQ zIq)#JlFT<JWy`Z*^U@O3Sqv8_e+^tB-wL;+af+;sqo$o)4>m6+L4HFx-b)2M9rl;o z!9(Sa@F=+pJVEXQ&yabRyhP?%(sT*I1ctz-O9;$njB8bgmuaRKNE){P6eLVH5LCJm z-lj_T!sdk}$iE+cQ2CF*Ps)2?)Aa*&4#BS}pXZOa<lo`<<+JcH`5gQOqd##KvCqjV z6)-mV|75<)g#ig!r!ss_&WDq+`k7w{hh%mw;ihALE4ZrM4z4Nll`W<6`EexbDZ%Ky zjIYXp`@=2e!Eify1l&U&3lEeh!wi+mVK0Q)>_9VwD}Ub8j8wZ&z5-qXn|H-?CRV9n zIlNJ3MB<y|hvA(v&u$OOJfrbqjT3kkeqKHTGqMx&`5tc5djmcOo8BAn3BH)-b5%Nt zg74&S;os!{!GFoW!u)m1k=i)S_<Bm3XSaO05?m}t;D$0=z*@=G;SR>w{w<K`rh;zp z`EpNqpxhfCF875^j}4^z!;_Ui5WZL*2D3*qXKn<%oW?IF-iBBucZAoPmyMu+htnn% z@Nl|W9t3ZfdFR&j<UoD?0NJg4{s4JWo&+=O4kyMR9WTn4!H48k@DVw_35j=<xEW>y zP!4<>d|c+?#~3`!e+p*fAk7~Ur{(8iHq0>pZJ0N`=y$*r`4nv4L4x#Oa85eU|48s} zd7&zW;o5Qym|>V$hkvHa<xX%LnMX=Tc@WI2Gu9skn;stU1bDRad2~#aXR?dfG$odz zfN^^`@Ctaod=<>NJ<MMPn=T&kdiVzAyYNl&cG&dfKza}Spz`;_du0CYe}QHfkwZwl zt^yt&rVRjT?)e`ppMUR7FAb!56qpx`z$w_d{--+J^M8@K=bN4x_=%2R;EA3YFmIy8 z@XhYXMR44_U<8R$Bnnkf8#XT(L7IOsOfL<Xe=ypqP8-<t(m=W++)w%Z8*zc$1D+)F zZ^3k#H`Hb)95+9i7pPzc3NDw~Y`IKc2wx|!g*VF^;9F$=?YLdO6~0^E0W;DNm-rs| zQTaZ254&iwfPYB#sbD|+g8Tx^h~4Z6oezH`*MX1Ayiv;dg{;#Y{!Zp!)ZgXvV0MCH zovt7w6VZJ!eY6QD5<J!!l$-^l;Ubx9rMA2jW-w>gSq+=_h`?Mc?Um0p(Nn$!9wgrm zkC1o5V`1}R%6pNRrh>=dOJpAFSIUQA1}Nf$d3;|h^Y~sTpM<x_{1eOw#H{~6*mS^v zPs6681@=n(PK{f8SP2R2xYj-yUx{89$PdE|P{cY>_)R$nepluWdsJ=!e=0YE855j6 zy!kofGY^X_zL+uz1<59nI8^v>2zzYjBEPy^3^OPZ^XtOAA479ujbxtN84H>D+z%Ly zp62%MCij6&rwinBbC2R(309hh#8i0^JX5|5zEoZcd-d1C*D8M(%y>f_4>#GZ@<I3> z`78J#`DgfXIsO|GPb={UykF+eBh%9YBTd2y=dkjF@LO^k{JtE5KaqJk_O+Z1n@$%P zPYgDlE?_ifv(p96|48H^VR~J_{Arbr?Zy0>u<3OHm%!P|FN4cy>=4+AtolATmGP6o zYA18Q=^<Bx`^il(ed_`x+M-~R%x!j&JQSWIPk<N7li(}lsqk`nI?Q)|aOP&fH_;A& z&uu<43{h4b1vphF-uVIJn!wu20<?yt!3;M<<I6fIb7@|eQN*4WrVh{TrlSQi3*ax5 zUjm<!Yr((B_24+W)Nld~kw}rbCs&f2!H&!|R7__jX0DEmqsnR|W87AA8PzNXBVzqL zxRcB?X^({C=4CN`RlqqKEH{LQ%jNJzG}?l=y%~Ur=7bl@__D5$E5plWG~8LMWUiq# zGH2qp2+#kh&5<%Lk>|%`?nKYZT-6Lt#5ytfKQc%9k<3;7h0OEB4{}qOfo?f0&kf1g zhIA{Q|07CthI8faFvAbAQg67vJOpkbkA&OF6JbUlVtrmw^^$pB=`UXd50$xNj)LPH zU=|WnRWKKxBlF~QnY;vM$RXCh8eS_u2yd48dvLqF557-+6=tX*4*NOG@Iv&D_%&}m zr^HY0+yl9_+yT$Wax3=M$vl<)e<(Ze@TiLR@9){{CcB&6Wy?tjB!naclF&m!lO943 z9qCd7(t8U=77%z)0YQ)fj0l1hMX3@%6i`4=L{yZnR7F4qtXO~F@9Z5P|9hWzuPZs9 zd-|C(XU;h@_uOMWHd4LP$lt-RsRxbxQ2&^q+BSw*q*gYDc)dW~qL{DhH}QAGt~F2M zV7>gfI^V<(9hJvb<)%7tK~wlT)Nvk6Ri+sNt)HnzG((_YVY?GYBV9Rj{8O<V&a4~+ z8m2ymWIeG;wQY_-KW<m6aD?+W&HYuZM@p&KTz`u7;2Y|pTz@6|`>oNPs6+lzK{YMc z@3Y2r*UBSnz_5XeJ!jJFgSw-CSN@LWOb!RIsWrtPf2qo7fdKC#z`?NkNYfU6pXcEF zkkNm#5#(|M8f<%0fPmP>XD!3eJcDQJ(koYj>T(PJe-%g6j2024ZJ9M|W~(d5T<J#j z;>IogUE-o!;GQ(<;9obldcL1O!AM@d&oDzB(C<L&fGb3yv+$7%2Zz00Bo9$<pzndA z!hZC#P*mWPP%A2MaZ;phE<{A^fRl-|Jqsa<E|Inu@ZVv50R@lHstVTDxP2nRyPELH z9uZbg@Gz&SX&n&S`Wya5IM_(Bmx+_X9kx{{g7X}5w%M}&fRBswineSvD8!fmUt9fa zKxZqwGMM%T{N{$O{FVLv=@rW$ZF_TmPI!(mU}T-4U@v#e#$L=Uu=mFZ^;Lg=YUmK8 zxX2c-F!ow>yOC`e6q`=qe`GtpL2|nj)I($*zW|`3zyTa<1Gq%h-VARKzesFR^<t5@ zm#;k*@3;78csYe(_1aj4-g^w=Edv+3mx~=Ey*a4EDDUfhkUPBGu-fURdWp;8w>fHa zO{n)%oR`JRon1m+zUj{JayL(El(C27DBxq>Kk<LMm+LYLyuI;%nzu62o$7rBxlZvO z22b{K3Urc}3Z)ahe7a8XQl)adm#clK{V)n)9sS-%s(zcZ7u$iC1{uGzcn2Zod5f2t zdbPZKTTAu+1|OUjKYpC!79%X;EaAFQ?=|?$w0j$%4zVc#%5})%t%38R_QOFW<lMwn zsm_UT@;Ubnz`+&mf#RfdKiT5q8ZPI7DL|VmMZGZ4Upmy8PN#Sc+%B%9bbd<q1h|ok z^E}z>T8Gj*FOjMJ@B_1;uC&8><7vsl;{5twIowhRYD2MI*;f(3`yuMc;yr;>4DSe_ z6}vC+iv7+(DVz6cc-XzvNsRRJwK2+Dj6e?WG#1B8m2sE12{MiLQjs1y675k9u6oSd z!wrIL(M6HS!OKwti#HeHsR7}JQ!uOn5p6R#JZYjXFnk2_<p^i8QAWFK7;Kd`b1g1Z zv_}gGF;Ibs_G->H+47?U#%}oMnOkh?${>GSPA2k*jyHHa95iE)Ty&Do;gs2zsa7(I zk=<#N;~>#hjAX<;YtBUJqBD&<@VRJ?R1F6E%f!Eg6NzqNP<Q60S;(B)=*<lNh^?l^ z4)({F8o;!>7@JXGn-QC<R??A|DY}=TuaglwO1(SSpMjkVzJ;G}4C*hsz*vA3sl)KR zip%$>8Xnas-=A&W9H}Pe`?IXKqSU5*e+BD4r}{A8pKJZbu7X4SPgw7`)rukh>J>Rb zaoK%;2y31?749EdN!Y50)vr0u)mz;j;;-RhmAZfCzBSqC7}AFNEA(26*zTWM<Qx}Q zuDBnNb9L)-|4xnVmgZEX=Z@8<(AvC#!ivzwd>UsAyJ<YRwlR}NPq4V-4E9HP=1jG2 zsJ~JUCmGy{+O4PQXVesft){QZO-<Zs#x8^&6~k>~+!?y&#+dt9q^dg3ICF@Ke$<~C z`V<$!ovAaLVZML_+}T<PnFbTBtwYZ=<9N>X40g|ROc#q?UkmfhSD0Nx9c;eIHHYpd zT3BFGd&=EZ3yaOU{}q;*@hp4}eXwnec>tH+-CQSEWOiV3xms9lPGhaN)WRB*!!PdE z`cz&rU!jnvh4p4j=GsvQ+h8uHPZy&b65V9-YuMdY3tLR?aPEFs3){?82E(>7ykB>j z;~B1xk&Qy`F|(N50Am^4_M7E+=>{2W1P9GHUgmtmhG2)y&sox;24}mEnRR%2!;EVX zPMG}QcaPU6e#+#Pc2Cs8Y4c5<_#`cyHS0jA<({Ui`=aS!fu?KWlDQcd&t0g6FU)+_ zLP!hPHm19}J<Q(|v(34~(WKj{;luq&eK;WFo|k|UIWHqWhx<jIifbOTTdSXAu4+81 zb!2WF^ANn9r;%`;`%9KE+`zB=tAT4~1HV4Jq=8>!qHN$vBm5OSx`AI~NpoDes?!L6 zYWic$?<Ad~OEFPi*s+idY`}!7^LhT{WpPETq7nX-6yCrdmp(6-Ihcaq;0GW#lVMcn zBz1X&zw{&LadO^=n5xyqp)+p-eHJdP_px{zk{zyI<VFnR4sh=nZ)398H365;+l1_M zF->n%GPjQD4Jm%DRdpNbPYcDPa*Qi%3kKEQ6Q4s(8dvy$N~8{uafPuGXQBZKW;%ga z8Mgem!LUSsl{RD(8{njktGsCwKPO%zCSgl}8%#RcWU5~=Ddf*Xq>Z*6qMFfkMM@|2 z_eg*BLAQ~q(J6{CQ&}lSmnc?BYI8>J8g&j4QmMXYbc>RdSOf74V?1SJG$R=g?gU+| zr)(@&g>o!y*faIERXsDxU)mU<HjeUV`)CKkSj}kd@s}}7-5%wyYLruPqy5i>K4bo6 zqgZ&pk$uC&i~8WBF_U!<A7*W!H^|gEl+`8T;~?`YOB<H;Bm+m6jd&e?4E-Tmj07Ei z73HqXDJ;K9nQg;JNYK@A5e~I@Q6<11kh2D>oH72@ct^f6#-EX_vu~u6<4j#R`>@Pe zxy)6n%2<CEHZ18s)_)zkGP&dYZH&Qc(K!EGUR|-9ZLHV|sGMHo{rm9&5Iey?F?>De z=@v>Yg(jQ_H|86x4@=e{wQ+*Kyni7t^pm<*DUY+t8l%p@xiMxMEymNjgJR#ArAxR# zCzT7i31=&eg<7^`>DKg&4m^&5+o<e`{&fElCS9bRYoNZHR#2lS`Wpl$@RD89&KwcU zIuoh(P4rhv=G|`eux>`-IK-8e#Uk|7GKa9TDi<4*{M8Jjx~ef5kIFRFYqGx)F14EM zFW*dCxo;N1hVUkuPu3vb5jk4^g7OVsz~&K5oJMW4F7N{9YB>RNiwf$O$^I9tZ@JX+ zDgJcpmI!rlioYRJ|8t6e7Bu5SQ~h;}L2CC@e`D)am->0C|1IlVk?M_U{zB_DtI8_y zr*`4ZZS2>LWEZ}D!;LH~e@2-PVdJeR>fZiLnGa%-Q}Dr`$sWmgTepG^l+QWT<^q2e z6ymc2{|ZB?G1L96%IhofwQgBS_@WPAiLh+RLIXHG-T$8Tj!nJr7`}h}>d0gM3gvVg z*=c7RsaT26RO7szRe>SUO?G83M2GBD{R;i@h%mj-pN^eK*A@C};tY#FEA)SE7%!+T zGyFAB4;N?n7ok8SL;e}Ya&;@@Z;p0YeWt%g@_e3MI|r{oSKMt`e3lw{4&GwpAvY<f zX3X^8=yMz=S*ptSDR^0AGejS90Gzi2mEvh>@D(KQam4hr(odQ8ISAxh%6HwA3K)#% zi>Rf;XE+aMif(-M=&BoZhxzL5S^l!vFY4SZe*^1TyNaFdPc;6cYR~r9h}ENR&G^pv zBV$}a+p@Huqo&Ws$r@_iY=155%hBr0Y=5TpqiE%N0^hOcZL0SZc)xnjszOirV-l!X z>TkrWmr)T(Fs(AND5|CN{m9~NPx!}_kNQy$PHj|UYdFgMFMC2{Zi^nNu$e@1v2DG7 zT0ko$saH!oUFt$xueaDJ_Fw&<)srG7*Xyr7ba>K=J%{|ob3?m$hw?P>qc(Mkp3*Q> zVTo?iW-?BTKkA{B=pfDIt%%!#zx`x1SN=F_TcT>zmUk2yAb(M8$rzvDk3E19!*N3V zbUz!b(L(*o5+g-a5HB%OG@r~dA^fWFF~E^8{1&1BB}R&NlQ{r|-<RZaVXlP=FR@W{ z04GdcrX+YB;XD<EGzgq!C1-%CDnhOTJ|oQ0J1VErJsW&YxE}Z$;fKKA3pWM-B%A~O zUAQHfldMdqHP4@0N>XSC_6YX@2Ze`$%LtDImlqxlt|&YfTt#>qI8%5YxUTRbFjY^P z*K^?J;1C6V!L<>ORbbA((!B`$u<(oEKEi9k)J0*K9pFcWkAkUkLicmviNY7ad|=W2 zI+*Gt<gfW=%ujO)x8U)#@L%91!W<0ezC#SdSMp6{G%$1)me++-!MlWcDfbCi1s@cy z4n8W(OG)*UKoshq*Y6YYXb3(l+!$P<)YbxgUEEuPOLW>gflGASIG#=26&9`sxJ0LI z1lWqZhVGAn9l}q6y(PM33m}-{!J(hB!t8#Ngm;3e;KGD<gR2Vf1=kYZ53VPC65Lq$ zb8xQkS#XIyT!`1ElX!dqrg983;C15nEt!{wohSJ&m_rVnwZ$#36=lfq3M<Ni(eGO3 zN*Hzt{CH;=Ua}>^ynB^4Wd)Cl5VQszI1S8493#{M?;_*g$1NW=>;z__N5!4}$q8X5 zdPcYs_=<2k_@*!~@g3n@_CJ49K#`dcRes6k!O_AMz<%KjaA{#SsAS<f;56a-;A+B6 zz*)l0!1aam!A-~^WHuB+3-K5ZZYMk*+*x=cxUcXO@KE7t;L*a1!4rjF1{Vl#1eX|g z+6G=scl3@va7c*|58(yjWbiuSJTRAVFalfkHenWemoN+c9vRmq3H+fjd&y6Q8-ckx zf?=A1zYKFoD>Hp19?am5a9{9!;ep^^h4aCG39}G3^b1UM6xb!q-q0sJ85}D-3rx#; z3_l;7X2<oXuna;q@mLP#OC{Z(2iF&V8Qes86S$=?Z%b}I%kaCwU4{36dkOCY^Ie%? z4uOXVA4dL`ks`bgo*>M7beixr@C@M_;JLzIgP#`u5&W$1FJP^ehs+`k%v*{(wLaDh zR|Hc*FT@g6hOk{cs)6?i*90FB=Ay=<!W^LeP`Ck@qbp2@TAo@%58N93rMPzk-w^H& zzAgL+^_1?3FcKcW2u}i+SbQn~M?{7*SPSM0BQskEHifr<`Eg74H^3Z(Bl9CGP55mv zM+fLm<tmPU1Zc|Y1cdtH!S9tO!hEK;6@CEjEX?P458=PSj|fv`WUw$5r-lnhgU1SU zkZ`gvAMcNqSa#xI_bl;<1OG>u8dVF0lfX-bD}YxEQ>ApXa8>Y5;Vkf8;o9H>!u7x$ z#b-@~20-A7Dhi{(9}ABGpA{Yl{!+LQ{FU%5u-5KF+y!8*-3R8^w$|<gbMfEb5`Gyt z0uKu2RRqS0Cd^ag8>T8+EQfW-ncx&*b|59joY-$y7x!l15@Sw$96u!Pe1mE#+!@?b zxF@*8m{T8c7jb`t{eMpp`op82@ECBu@FegE;i=$p!VAD!?GJ@s0xlHymEhUJ>_4;y zAi}HxFA{h54a>+hW%Ut+RpN0Pyhiv8c!Mxsr?v?5F}*|h3RtTNBAx5tx5fP%@L}Qa zz?|t|?ebPXCCpnr#PL0P<UqJ6%=?u?8+7jhzA4-btW^o&-WU9%xc3A9CQOwu&agA? z9B`!YO0Zk_c`!Bj5GJJ8GI5m)BfJU^Z50Z<6`U&W+rd?YcY|vQbD&o19wI!|z#5DD zad3_>U+W(x<0FJmygtHw;0<)(`qLu`!lUAm0v;_~5j;^i9Xvz0GMLLm8Mhkv8DYK$ zJSWTs`@C=tc&%_R@J8Vg$lvms2z;({4_zi&2!2a=7Fg>W!hJsY194{q{8*R`@Qm<M z@Fn3D;A_I1N96X|O#fvt2SY*>HbMAFJa&OGRigtP2LCO56wFsL&M&*c9PT0e!HL2U zEvdo@V69>Z$3(DJF$5=rImXSnsNGOl#}ERmw55172j>Y70(TJ}0`4iyFQI<I6T$hy z)4&{JVFt6okC9`-g`OphbGH0PGwMGU!XoitNuLwuwO=D#1-wO=*SlD_2Ka5^Oz;um zY%uo?WX2DHKNfBRJ|mn9zC=Am25JT2ns9sYH^QC3-wSsIb8!~KKMej|n7y0f3cJ4o zjuL(i94)*RoJhvm;)+^Qh57zzsVo9-kD9`9;JU(mt>#vRjLa`;t~)04PRSEa1#8Pu zaAyr^%TZv~khUBJ&H@jU@O8lxv?(ii@RhkxJb0_j7G4UTFU)Rrk#G^16BjH5Tk<O5 zSHNq8dBz)rcYwDD7lU^Q?`8kLM}+<G;4}vlJpeu|d<c9@n0Lela_R8b&lO>OlUTkM z_JZ#Vvqm{P!|-f$e+!oZ+Yu>1Q!@O(h^7E$!|@B(1(z1)>vK6_-W?T$TY@u$*=}kG zv)$AdX1n2-J=5pYuZi#ga7ZgL;$q`&2`e#z%Y&)JNK10OU-N}4gGUJSx{ed>37#U{ z8(b(n6g*RS5_lOIr_Q{d4|7O2sF%cpHL+Qkx8GLbbntFr7Gl3J-y7Z$t_eOSTpRq6 zFmJifgxi8I3g>~ZX;W4x5vz!+>sY!0;O~V;gMSj92mW1nKA5ZW7@mzZN_Zuhn=;a! z4KpZQ3@#(Q7hGQW5ZYf@0TL08gX_=(_uDXVL*cRD9N`IIZp6qilffN?r-C`_ME99s z&ijyA=mEk{g0(Ir+!ugH!9B!4e0WTdKr6snF%s^tf@h2SYv6^#yTIDg6vFHSuN8OR z9j^+X0BcKA2*VeagW~=z_^7bK_y3PYuo<|ugsJFwRk#xPrZ7J|z7yuh#*e~H!BnK+ z$+Q65Jz?gzgIk!3G5BfEFi(Ox%NZz(`hOZiqIhswH#d6MwF0gzybN4Z_ysVvei()` zi4BGM5t1X!mzO-@9pLW5yTFeK^MfRx{Vx-G7s6O!zP%I(p9DW4{5g1`@J;YC;cvm* zlacBC3|=eD50#C==~ldF2-g8~Pez6hab?C{5xRp92=@XX5$+HEKzIoFW8snDGs5G+ zmxQN)uL*P9?;Bw*Dbv=dkns%gPui3f1b#^TE`jEN4fLTb9mo2jggMsd5#A0C3KxUR z2)_j`FMJSOQTQEj72#vxOyT#rPOYv8AHqYMtU|`0f}4x`IWTv1WPyGJ(;z)LAp+M` zI1$`exH5Q<a5eBSVGhxa5$4M6No1Nb<mAP4@xYLnWu`Fgq0bX80&5LRgntSAthm1n zULpJmc(pL+G}jArL`*ATBJO$cHgUfU4(%49mJQvia5ng;aAWWZ;ih1%or#2U!CE^L zOj8zGI}_XithF=2FM+joCU`v<8b!M1Hi9F=9MTrS-QvLkC2k<e>g9w&S>XfVio%D$ zHH2xTL~Cs#JXdEn6!%EGXl=sX3D#PhU>fz-TASbmaQ9NU{>&^DLSKo@6`6yCxvFxQ z@L(`ElVtcI;7P(`z*?IV?gijk;!gY9bA{)FSCH}5fpS__3u{xh>qX!Tf>!NBAUt_3 zuZufhN)M6oPR)0>_k{U!@u4t2fGnR1qZ}6QBFXS6VD21AdyNc#R~WAX7H%9Fq6Z`V zAs&chu_7ehnXyAS3G5ZF12%>0fy)ZF04E7|16LB}`$1*l-rz=LB%Xx)EzL!!2#+?x zeBO5yt_kKIlZ;Rc%!zq2pYa2Q8-qs)=YppSKLVa5JOuo-@T1`8G~@b@fbhI{JP%$g zyav2c_$Bab!t231g)f4+_aqDSGx&gT0=nKK!c?~ZKsXuvv2YsrOi5MnyZn-P)B#@; z=F{vOVGgN%FHCiVAAH4a2L(>X+9y4WUP&dlfuXgU1%Z0TVKuxU(9ynW86H~d5S>rK z*?M-Fa!n6(urGKHmro6B3-@u;1NH1{mSap<ZKr$?GAz11m>%c|b8u}Q!(o|PiG#i9 z1$4*iUb}L^<%NioyBb3{s#zZ5bfSD2@^!U@@*2n}!ns1kN?pTPneE}+^l><!Pz8@8 zO`AH7gFS9D3z*yizBOmSx3wBR1HMISFAurO8Ny+Y>cvB<+8hc@wf^{tN|_nxV8GPe zOt`L5hh_$<Sbz1Y?`8&4plR%%6-cxHHX1|3Vcp?QvjRTrua9Zn;b~yIs}Ms5>Pm*g z<Nz^h@t<Fg+Rn%hT)VsK3a!@NWrVAUusEzl95<VZC8)}?1C@+Ps`G3F-}MZxx;8v# z%vWn?2QvO^Z?1Z^(zcpeb?Yo$@=KaApg87<z(H3e2ko9S)P;qCgw8F|6~N@#6&(I+ zb&d~JXaRS}cnZ{q^Uy~_efSYNI-<Tnd7(ahkCF|#jhwIm96_&uC}$jM=7iXo5Le@i zrtornB8sN)O1ef(!|7W23H^_DFuw$$9sC0hPR=etJNPyNxj1!c%YI!~kCkSbZS_Ba z;M|YQpdB0!Zym<okZ5sjM*{Z7EAVD`vwxIn+*S7$1u{Y$yM#9IbcX&MiA1(x>$bSQ zz`w|L2u*F^uW%(I^B#r=w1GR}#7o(tYV+;IcM1iv_^6c;@)aTa4BzKC_s4yYf(w0K z1bxiMfxzj$G048aHx<6qd<$`^Q+=t38k*u81@FnesYqy&Zz&R*=%Whi1Ruu^#``$P zH_l?^GV!Q>d^0a)bM&f#RD1*A^qs}`8~D7%w+~V+-{Z(6)i)0DQHxvQ<QT_MU&L9` zk8xt)Gt=&S4kvB+sH<x~1d~k>s@&p0hE@-Dh(7Kdr!tPj$9n%l7{@7AgWKhXA)tX# zv1-xcKzxXr%{YBzVfZ+mV)fmEON1{G+1PyPaIyQ!vOax1!BIXwI~=};kg?NO2p5+x z8otp!?zsRZ+G;pWXT6Jv9M}eTn```7B<HKfGx2F97$4`{tiG2KFv2&HBY-v^=K}4P z0QInJuA=#j(Hcoud{>bM)ovHTDOdxUCKxW8VIrK_5&o_ygMlq3ufEG|@ao&lcU9q% zKwOCJ#}zQB5T9rM1|L_9!Mzl=m<5bl)?jnmX7Wqf6|aSZW*Xxp=?qSp^LTod3{K0O zHd~;)t}4bl2xrY2Od!+X1NoxK0ZCUKgO&s?o7|Mg)!dlEXWDg>Lj<lCMo;8=)4WNq zHpV=}{Udg#%6v8u|1j;bxw;tZ;08_HMGWz<F$}>Yjo2ADGgl8oUo#`t&5*sc<S}9o zvS@vbX$a{xN{^X58dmVMpU;SWQmsYOiJVbzO){>dSf&xnnQ&Ku;e{hLc<-z8&jwPh zwe8E72C|^_mAy2OZFNPe5laIVjFW27(m*^+lfAMuur4$f3D}}*uVr$)Rio?3t@<O% z5Z!1#+@0rvW^@~_eRoBopwaq<v$!s?X|(4V7%on&Mt9_yTK)Zp=UbvX>$7&P#A!x% zB}ckyBeCdS4DUcH;65wx+{8LqTGohugn?Yz0$6l^mdEY7#0Ue(K8uqkQ+)2)ZCMJI z)Lln+7#3>~r{HeL(mD4d-E?;+YT3FP;-9;VJ{wm#ayMpRbIoJY-C2rAR~9SI-IGF; z&e`3Y={t1J?mpx=i<4_)b3G%Y*?Kr5;~AryrHd2fo^fQGD+6`mnaCgx*RS~RnHr1# zZdXV0bmr`HQ9s60$X0B+7Q)3dW4e0(xj^X<m1UB=jm9FZiw)n~m}v2jgEl5RDw~U| z>b*_3py&?Q3WWAHW0DED*}*w1f1-=ya^B|T^0=q;dVA^%*h;nHCImjdgIatIkQ@|D zlOQ;ZK?j)Q0<QTs1~VgzYquJ;JP=p*4F+pu80<0=hL4*-fn_SUMXg>QXlFd9ZY>X_ zmFHlXv7R115xLS?iW^w6ITVkonhGuL1C__adNoW1c7%!$*tpgh{s7B6_%n+BM7)Ys znB_I%B-BvFr%=LhxHS;dP=cGxhqG*zK4MTUeo0Z6LW_S<<bvU_Z#u$-3-t{%>;lnW z=|wa)L(80ls&rMovLcXZG*`!01d@#{>h_928;>qatii&RJF1$k48&ovQ16w2gjUB; z`9@EJl~pc}MeJ!X>6#y)rj6c4N5rVfwK^rtnHu35<1I!X9kXUb_14Njg?OD!Kb=iY z4imx{A``P@R)|u+uf#oD#i}w_1rq%_^*?m#w6&AnPz_iWC~q89GjXV_qyDX<X6rIp ztW4$sLe~D4)xFi4iK5p2#i@?33cLh$yHU>vcGqA#G6q_Cxu}b2NvBDlKL8a<A&ZNQ zIKs+0?}ESV6~(ttqZsK&eyNXubwZCtmq@pG4o`n**k^W%mwvxnoK@s*YJ#9{sH zx~%m(R@P`M$}WdG^Fko8(fd5@?{y)L!@VZw5Jk=!J9MnYxU2o{GY-F~jC=arOhn7} zsamT8HLRtr#e-J|N*RIcOlty599H&gct*{6G0-xl6C!(NvQub6&1dIxmGGHUCJRL` zgPt5yePh*~7XwMzG<D=i(H-q0459CcW-X8_gH5Lsp$x~l%8bQ7OOu_d>6$=HEZ2=V zwcg;%B}rSFZB`@K1QKFHi0>c3T0TQRf+gp$dSOkVO!n6(lcRk2A%I7(&aq5IhG@>+ za9}gI!avTsG))sD)vYyXuLZ@<wSjr1qBsX)wJcJh@6Gbb!^VytQsdEqlLrqQI3d4A z{*Wm(hD;n+uU4HpB}WAnz{27Y+XFt=|DrHBzLq0Rb(s)VMU9Iq<1OC#X5fLn*z-;x zt6AuI+-W8Heq8cYVvCH!C?z_6eD0U%_`OEP_dkEHv*DqQ@wWkSsgi|@X5q+}R?h-+ zw2O?<9LpYIe6v_M+68ya_d?+OI|Feb_<do1k#hQ-?ulTIc9B!S=Y^|+Ioid^!zAzz z!WF@sqNjTr_;2A1upK8x_bT9MZI=u}H3*!Gr$<e2Y2j=zr`+lO5SY{KWZssXW+yiT z^9_;Q9L%Y8a!W9KY4T8TGvNu~R>FmRZqm>R1I+_>6<!49kQ?0>gE{0z#wVPGLvG~d zV16BtcY!(NMt&R27hm$bV2-AdPk{d;d<wh}tnJc#3Sp^uTmr8Yz6^d*_$v5i;Tzyr zg}(-G75)~?p*6lkAU_L-*2pp7lfoF+wr~Xo-4l?%<-7>x;c;0w8T^%S1@IkVUf27= zysp0r^SVZ$VKPy+370UR!CVVU_c`ELVb(N<>jE6_pAR8LJXob#jSdl3fwdYPcr93~ z(Sg^4wHh6G16Zrkf%%5gR?^u9=DJO0%&&-nWZVL*l}G=@qqV*tJP<CdMhE6yP#}R~ z!6jkhz*>zCVNi8pH9BwwuvVi3R|7vUaXBKww|Hh;7tFCiG8^(9GH&BgK7_YL7!E!x zJQDoA@FXz5ycmHK3!e)=0lp}#z*mJggKr9N1%D^J2TXloro%@1o7VS(a1a8=!RYZW zFjDw9m|Zg6*?P4>JMc*`J9)aF1*ZsK1y>dR9?U^ZhWQ2DNcc}M2P^5GM19|mBJ@Nj z(L=a5m}a^eXfSxN@I>%%VNM{76`l>AEW8-ZB|(g<z_Wy@@$esE_PWoKLkPqPgd*|a z1OkUi8Tk$HCShteye`ZhQmfh_3}2)6iTg)jesM7FCt$6D2WD@nRq()6Sk@|dV7_yO zv<@DGYY?;!9{4M;R>1>P>q)ENfqw<xmkfRbYZW}W`*0g-6+CbNtX1&9CRnTBfy;t9 z!otF_7u70wUflncAaLxJ9_&(6gsHidF5C!QUAPH2Tet;S@3V-w>{6SGdmFG;$Afzw zm@iXIzazMdaA$B&t?vhqZV>cFi{KvMd<irdJVJOVc%1Mk@D$-m;6mXkV2<-LGrpB_ zoR`emjYY!jc9#ji#P60>BCH3m5#A5pAp9|Si!eXgcL?7AYt=kta2x!#xc>=0Ec`e4 zec@=_dK^Jufv8*jIXFZi8^T5LXb8S4+!}mSxEuI8;U3^0g?od46Q)kEB{H1BP;jL1 zFtA&AG&mrPF$dVC6oD2t6NRUNwS_$tj$;ay#eEyNrtl7M9pMkbdSga}{}!Ah?(A$h zmcWyI0M>^0z`ujF;XT@=u%bn4%X{$ffCoy1Qs760sqZ^l*aS}$js<Hge25zlo+<8$ zV1A!6W9kHRNiLa&H=h;eTlxyE?+1@65VZatxH@>f1gZ&sMK}w*O_<XvyM?I}tT$;y z+=s#Mh&xAujtS?3^&X7~QvlX`G=f7M9MYRKQUG6;2<)}AULV}&fbWU>Q{Z2Pp8@|R zOpBa0ybtm$w}4&3?6mZTjd0%qhK`>Ovl|Q*zp!1JJrJ~x9|Exlt15v`fNKe}6RIct zJ-D&(Z{Rk<e}g$*$U^X?mV>6`C~#k4&i@P&_VfN9CPEo_j1guhG)cH3c)D-~c&0Ev z#r`AA!Ka17jlo)%4;i-xKQHc`z%L1Nv_`A)vHzb8VJ|)KD$Tc-1H#$hBf@-se;`~R z{IPH=@EPGY;7h`J;A_Giz~2aW2h#>P^Wvv|=qC}V2=coyr%Cu7z(9N_h!W<r-y^&L z%smts<{5AqVSZEbE0pd_!4-x1W>rOaC75d=5hkP;mDClF)$nK}ybj!4cmueNFkdb@ z3U2{xT|Q*C6|8mnz}vwCCCpB+R^@~HZt!SvKLVbp_5I*+8UmNRveak5A>psVbA`VF zbEueM?tzyG^GjO^(;~(T!X}u;6Bs@gyjd6ndzP)j@qCGRLj+C+y(ydyJ|vt8eoweA z_(S3P;7^6AuF3WG%#13UUkdjJbL@xiL%_F%sR?lp9HPfu2)~HOLhzr$&wwMG;mAwC zPT^(XQo_r@9C&6re8Wi==3q~{@H#NfnlsEMaBbn&44C7nFTz&Uc~HPq<#t%z#UJ{E zA*az-wT};WG`6W1aIoHNufB^9a;B$I0$h{SLLTzfrG(&%7zug29HhnS!*ao?IJ8LA z(sMjiRW}lYRgA{UUp`m?`!>}sA562KtAmd`H4rY=yUp}$P*M4y&u+~@C!_ZrI!y5) zh&8o%2O_M){K>c@;A&I%*4cupVN%d%J-tYEND5YRj%$S%1Uy-)sgI|XE^oiw7X5}g zRK-!jeinDae_*60BB(AV1^;D9rbFMT()OC!_^IzU7?q5K;`+(K1_{wwLEM3~NfjGV zp+>=k5C=ptHFV#PtZnw;V<uT5jL0-}cbMmSlLxCk-G^sc9n|JOyWw!W1hYic9l<OS zzs4{*#IFK9OSB1hJ7Pb9-sj)D;XKJK!n@)0$G3TSH=Kdi?@<8R0_RWkS@x(WkdBpK z@pi{VAneNYWEmZ{_mQikDe3|H;QR(3C)D~Zk=btn5o0raBkNxQI&4S>8{KfK(>Xys z);O4+S_Lg6s<|C5?l{D<IqKwtJ$(1Gcp9;!o+awN#=(jquJ(*`v|w{`awyW#h9R-p z1pYhPZ3JQ>slW{(?+G|zB8e}7)=r4#tW^=-*aRm#0afBTuM=O4N-{i*XZ3uK^N#Sm z4i}rpivM=cC0vh4Pd`*m6t+4+qIEoct8#kwqQEW>zeS=ww{Sjg?p9O#X{LJ$qQygN zl_Ad;2sXpBGg_@}5{wPePDg>~C!F9k4<E`?J&lpe6i**qk;$Gn;6BOoEb^M@xr&lZ z@H~zG<2`GU5~ikZ;GClS9n)vv?sb4U9YWaeEFO-@ows=2MOkZks>3bSa}F_aM$`y# zk6VtgKAU?<=sQN*53iYa&voQ!cy8mI4q<B*oYQQWlcCO?d(-;}=AbbXpL-u)=bX0? z#l4?saZ+*EeP9;Q<{W_{xsUAthxgKPe?WFQIoR!%y>v2hp6*Xszn+kv_GR4XDR`Y! zqjFy&)4t3D<mq04(%3xXxdP0y9<3Vt)8GUQ52xs?o})-L!t*4m+~&!HyWQeuPll~< zb~8dT3WJ?vP~n`B+7G7yZQ|;!aB^@m!CUb-4eW)((3T+E5%$7iJF*3DI911H!O|nx zGO_c`Q26Bqn;^C)#+U+OOK>R@FKe*PZVOV?1kHiM!Qdt)lw>fAQ^6PT-&4tW6o=D6 z>eYCv=<RRL25FZMd*Kwp=VI`Fq&n3s7}t_o|JeD4Z;UsCG(hyv&Nnx389jLh>(gSy zj-E8x;_0X*s}aN3HtdE&KkSC{ZIr5>6D;dvMgMo_o2{i(&zxYo(Fr!Ug7H48XJeNe zzANJ~WPMz1$qA+!&0vWum~DOFR8h@?S=PJJs$p|<jIVmtz~;eRj1+HZ9-LEYAL;>{ z+%Q*tOMAoHyI8Cp;Nfj_2=0zA{HjxK@S%z{sqF2_l0`bd#;KNUa>FU0l1*;<sja!e z(q(VpbiD(ZD)zLALBqqIHcucrx`fNQ!3u2`z^POh-FrBXqlK61rcc<}3a3)CrOifM zh*CW_BD?VHPpRHa0Vax&cBwvO>~UjJ?OOyZWOCt(Z(=T5jKfJQaK5R0n{Yd+SL~b4 zw0+K#xMIFSwh7bO47R|6<*c{e>R^jtc0~)Kck*|pHo9{r+MvHHgISzEAgeIPIlHMc zErT^eyj}b~`1+9T<W=$aVhQUx9ppaD=^^I}X#HVs=$wF%{sC9u-qd-9$qi=sTxTL~ z0sjzk3uk9EAO9G>^R#x3W|(oa;GT#3I?#9^%H(+$r)2T;#XsmRI0_N9b)b1aoST0d zX7d6q!xfpOuC)wS2o1#v1UfL~C?|V|Kqs=p`60THKo^$K<y?qd0{T+AokcjKfUbY9 zvmY`FJj^gYXL<Y&bSDR#TTsG453=c`39>*>a;&o%N*CzG%8GL)@~-TCr7}EfI;~L< z`tY=~oq6~l=u58WoPc%{=*RLlbWT-UTLt5+pL*2sR>2f+E0ihNoMp8-H+$3rxP@55 z!B))6<%~t!2)1UMay#pyhJ$T%`*Oa=Fm1`E^G&+9BgZ)pBUUi43R+r%GY(Z2Y)}2@ zs!o1M1v|6@k8*Om++ar*=Z<q(0NlF|T<%(2EJlN9wW@V6C&afRi)R=98=gTZztwXc z4iTORRF=(i1kvmsE<TU+R7EvKdEBUIho>)GoSvSj6qknz2+^LSaB*WJ0YtEw*;H5d za2<?caZhDRX5(B$_Z-LNE93bSF7Luh8Ulq5TRgnhM=TzGft<2<x+C20`lTI8t{y7( zuQfa~QNEW9&n8^)HzPdHqq086;|}L~!Rz75gl{rDW8k>+2ns>1ber*?7nvUo-CH~- zfQE<5?5&=iD075oJ<inTd5PNlc258qM|!&9I!Af(QGSP~4Qkryxq-sEJV%k7%d-MW zL|ft)Ads=zz5}TmSKyS8z@)<t39MtVc0Y{k4Q5Rz)C)%<qkrcio?q|AD@Z39$8yLm zoDf~WI-ys>3H4Re+Xl;3()qmiFYoul-h5CP@7eieD3{nzz10@&>RHzNDSJichY`cF zNZ$C<h#$o~zp?X4Z)`yEl40-W8#|wk3B2jRbWPNm-`1%o(l#GVfU!`C{Tc7uFb`!8 z--UTNlmA|Gc}z3jwX1&Zg8r1RP}|0RJEt8IshMs3VBdn|Q)0>P$dqrLYDv3bN+(); zH_An_RuV@sPGY2v!w)H=d?d3jm)IAV%Xlo3O*zre{0hb6Ra_!Ggcu6Ha*6LpsffH_ z#WK2DdRSR42|D*4R_2~q2!*d;a(p?o6=Q&vW;DwsR!1OXy_I7V<r2H9$Mb^Oy>*2= zqbtPdl161);~9N1bw26Tb2E16bEX4l2#lg_NG(lYr?5{oxTfja+@Wi82;@qARdoAc zda@4orcPkqKf&JA!8kgMVBHYRuTP_A6i?#;gB7ZU?Stj<MethtV7X*|+!%eLcm*rs z;#8i-%IF)#6KxJT@i}$7eeg=%JFL9dqu^<2h(Dv~O`LtWpsz=<<~TnQF6iq~Y`h#? zOLMA-j=|(A+=k7#5Wz;nkNbz%l#5oP4@lExyAZ*$O~GH~Le;TjFag`hj_MdJ=htPs z62Y<=$hmfcTGcTaZ%ixR-7%PFSbvOCw$8yZt-fONv9?qsT|*~*!7NES*2bh~qVSbF zp%XCT^k!KcRjjP9P8l1UYcE{2+O3QCb`H)r`s*Uy*YTb}^9hIhQHSH_Yh})789&*0 zGVf64qCMkh8|&a_V8(EZ@r%AcVSe6HS)anMHl9KU$T)>HUG*vK?;8BV2w$5q`kkx? z&I0HE>chA;aq5GIOU{3i!N|=~rHK6CVMg8<(>)kbwjxhE#xOpCo@|0Hb&O63?XyO& zV3|tVDNj3vn{S>GZoX`H9rWF6sn}SJ=@o1q;<t)%Ig-uS3GcLByooOBTY?&^m33NI zBUzd4DC^3*7Rk!%N0~F0#`Q?1zk+fEF0OGy-;l3DW~F?krOWiyH`CWTbTpb#&i96= zIJ0-Kzt!lVmh=tAgsWwbzVix7qd0}CxNopZ=pyghlN`9z)1gMuW;}tzZRn&9d>er? z<KUfM9sgQ#7{bVos0w})e@0OvddhJ4Y~AKcBW!JbE_EXK8WFK%O(=ZH>grb4oc{VY zs~54uq6R(^45IZ-ek2$$(l!Q=;(!QT7t27M_`-h@AD|QW;*Q1zeZ60>b(QfrZDWpZ zG%QUjtE=dl3MHkPqnlg%aD?Rkx&<`rU(y1e(#<EXtZo5g`|IZObpPOJBb!RS#ye5$ z_xMY}pHX!BpJd;OBEN?A(Ev4}m8nsnssn=wbqiTFRqebTJL$qKuUJx;s`^2253$0R zxw`Jb%3<oQb~6=1<nVo&r+fXHbWTuP2I^8B8yKu>Shx9=F*q0(zKUP#3-ddIA?wP6 zgInwBw$w;FC+fOyVr4tB#JA$v?AMiK{9dV~QSaAvgGTMk50(z;yX~O9+sdO+9nyDN zqQ1-C(bbfwFW0*|M7c!Wn|)woyF{&bV2_<*HImax5>NS8F;c_DX!9lSh1ZRyh{35M zqi9D43a?AO&D6Kk;Bu(ZhvB~){*?=h_vHr%TDv^N)PFFHvj`r(AAgYhk>~YO_=anF zilI(xYd#y0f>E@(a!Kl+>)=PxrkfAY39HeM23IA}Zj~`jKXTdfIjd|GokuLRWL05U zu#OeSKEr}FO9yfL8tbyE;B_kkp)64WVBXW}rD4IQadY7rQ{}0DJYf_M+@XQ`Z5Td! z)_GO=;lYQ3aqQ>UUj8Rkr|*4g)bL=Un|83{qKlAfmw9UW@L*<KG=jov<zzJIICfES z`T^S2roJ2=tX7XoM6goHrn$Ey1U9KgRg~_`zVjp<*`HWCU&3kmr}BfL>sE)#9T98@ zt7WrB1ZzN*c>9Q8Qt48tvogtOpq9t+Jd9fcuyoyTS2srl(}ML7&tFhX4<=!Gc#lJ2 zbLWiGPq^_SJ@Z$3uoQ7iP+m)?g5p6Vg99?6PQ>Cx&a#Bt>&2-7AI95Kvn@6L-wG(n z&jp+Q4|*zB+B<5hyG!h@{~>I0RNT1Y$Cn4^l%Yi{Px07o!K<GCRlTLS^V`A2aYn7; ztDgsRR)kigW=qss-XllhobjWf9s?a5f0?NC5*3$LsQMDMmNjHtAO0?|8Q>|(UrV+s zcB=UGM|vd|rw)^GU-MTHX~VJ<rWNoz$QvjLfZy-rlrZ0l2B(IZt3wQ4QT%q3D~0(s zIW5e~c;BRl`2iU>7Jt>*^P>IpH<66i%HP{T<Zqx|@z)=vH*oFw`wI7r!6yQKD{<Y8 z8e!f|t{LXdsG$H`2!2|zLztR`bVnupvlk#Mk|R)bXV3BpnKjMxKU*SzzYs<xSg3o; zK&;iD$Vi3l_4j|VflEVoUWF)O-2LJG|KQGhKPc`Mz*LWBcvfC{aEJnHtfF|-17`^5 zfH}=c<qQ@gM>rYGDNnj*fIA3hf;s(3_iQkyJjpG<Lxfv{M+vv%`A-m`Gdwt*$q2o{ zR2L=>0?!d13Vup>7<jSpWbkrf&b<@~7lL0BW=(Gro)6|1nO19g8NxpC*aSW(ybF9( zcpq3RcA!89!575+0{DjTP4I2uyWso6KY%%>%9HsUY{6Ya#v)Ej6lW4C*dTa?IX6Oc z$#i#uIbTYS25SWlum?<KcDnn(HH2v_ytXjsQW^+zE~SZZd2kmpS|ane^b~;&vY)UA z%(+ko!X0KAA<PCfP8jb_mMOyg7?~-|Tb$FMjLU|$OqgwDg>Zc^KBF+LiKffOvYj4a zdK3#c1ivMm3w~F)C79pz4Bs03k#HXPGvN;43&P#NSA_GyH-$&={`*dZN${W!I1_yg z%=uFC<6!oXWHus)@RQ(D!VADL!q0%?g_nX;gqMTUg^R#7$lPw@WeA)XWd^&!xx#zF z9fc2pdkKF4);5t4{uG#N>KOM^ur`SVz6>5O?wnhgD$I8FxG>vLXub#m2+s(Y1wSXu z#`3%{UqZF61v01#-Y)L7!EXxZfsY9H27e^n7p%=4A#Q*0S9CW~p-CtmzZJ!<h2_3* zI^2I1X2<fEa2>EMG911c*d^Q?>=S1Dh!t)FP7r1vlOo&~oUXUqGcmOdp}KgmGsza_ zwSP!>Hn_3y9B^kco^q*RZPp0P$Hyb$&PRqeYXtXNU~Se2TpO&-8iDn88``cBghudq zOd_-EohAG*SerFMm_A@_)(G4Wtj!vM^T8`6{0Q)i!ZX1y3qJvVRhW%;J2=EMSOlS1 zJeGmq5?%#<S9lxvxbRN!N5X8Rp9#MWzAStg{I&3h;BSRL0{<X<nm5z~5zfIw+dD#m zE`w?Gn1#Crrd>?(H(<Z;U2tjPpTS)5z%YM;D+pWB&@zN0!8L>(;M$sTL$mv&T~tOc z18yeFmalg<gnK%;y|`BgcNON$vfkwoVOoPn(7mkg;=|^S!0bJzh&y}FLSaO)%npf= z1Yy2#3V4xl8d&Q{Aff8uRpQP@v_`ltSnEh240}&)?g-otyhFmUH{2uK8@yjQ^azBH zD4^4>2mVZ$jq!qTQ}7jGHcTpUGkh+XJCl=Jf`1TZm;6AO8UHQZ4QzLW!?VG{tP%Qu zM1B+k6>rJo!Te?;PXlYSM&Rk-isD`f);bb!e+sO1B*5%?`F78^&w{mCBk(FPCo<?> z1g33O@=NT{JBjczJbDOk0{0W%3LYZ713Xgr4KQaSn9v^ZG~ttAtrh|IGvFu1{cEt^ zQ4#KUz%SB01mQ;rTIT`$7g*~&fFsbLw8{gRtyil&fc;>t@&GOk)+!HRcH3Iz0h|QZ zDi2@|1Z$NCa4uM@Jb+t*LpP*!9U<Hm=9u*F!tAT<&hS~%G`Ch~K;%Mj8F8NhrrBiH z#4K=4a$>lBaGssauD79ZS8z_4LzeCkT8l?7FbBODp)a_b@KA7XVZPrD5H0|7MI*x( zf=3I_15XrQ2rdw2`{0;9!!H5<$BFAt;duz!lo5C}c$oxR3tlC>9=uj~BY2}Q+sA9d z+rc}9i@|$^_kj-zzXg6zSer3CDZ){BoEAO~J}=DY{S{$0uCIk}g1;619{hvwJ@9YB zKY+D~Bb*p}My^BS3I7fDf<qM8O~!}^RSM#TF)?OI5v~ZXDx3}0CXNu7Jz$QwHv{Jh zw*z+(?hK~R1M_0r;>-&fV-_Jxz6km77$N*9c%1NP@D$<sU~TRQkr#t!i#zpc77DKh zuMpk{#%znuj2al5gsA}hx@KJe(-3xv$2ssG;R|4HC?7~dPlf9GShy7Uj4-|>EtiDZ zpL2r;hOYqrMz|uFN+EQw3Fd-fGT#XzLwJ7=pu<mv;1;e7=6gNe`9cvV%<ef+_#tqr zaAR;~;ill4!Y#nuc!KHh&A6d3Z^azp5N|oXHzNWK1a}Y*-g4c9$AEha^OhSRyb?TA zcr|#G@T=en!moj+3G*F7Z{LW#_@ayL8`1wmI08ZM-w1vmtoLsOp93$K$k)L|!e4>4 z=_7<;SGq~u`5y4PFdOVHVLrb132P+;;TlwH=S&+5Q44`i2)6)#BHRXiR+w+MUkI}$ zUlkq**5;0I9b2Oi+T4+_fyNU6w}ZPjcLe4o(B_Up5V}Ip_Kv{p4Yj=^FfWa^cLW{; zt|$rRgK5Z{iSjaO(?{T8;6~y;63iI@h8YiTBg|g1qwrjCsFw(QMCJ>>3LYuE9jr|p zA)#GhZQ=-g6+A=2@KtP%Fguy2ge|C*CBp1uwCN+nb%41m7YY~Brm5FUAbyd&B3uf* zP1po$n@EVvuiE|MUIzS*FgvSb!hCf*DVzd6EnEeBUbq_gvYY)s66Gw=SK^Tkz9ZZK zd|#No+pofG6MqSFG~DJ1r_&4U65bBxwkAw}FF02CAUHwzXb3`z2*<$b!XJXG3x5jE z7XA|aknjy~Q{g+{mcl=RwGAa?`~ciV-2Vpm6ppr{8wQ71IxgtS7mqlw-e?l;Tr)pT z+^c}62-gG`3fBkE7Uo3PeBsvMMZ%rH+U63{d>E{4E`ed3A!J!2fd;`t8(o4&KA2i% zEZk`DF5$7@eZpMCbx@cq2#yNR1)mV+u<<9t9IiVn%r$#oXvXz_8^U$*_z`?d_!sb9 zVXhSTS=bhVMWe#yz*cX#pebO7aAmMpxDnVC<`Sr~!mYqbRBPs04unuinCqUZ3UjEe zmhcpCJ>i+)#=`T#xx$OU+U63{<WeVXa|yf@tZgoVIZ~!=E`dWFD$_=nAgl&!qf20} zhZ-x1z6|DQJ`1`LTqsPPF}<rL+}{Jw7k4g)S|oe|yiE8cc$M(S;5A&<!bE9kX`^^t z0>37F6TDNHLu-45xpd)x@Lli`VGg-{Ap8^fV_^=tQBjC_xxtr&V{EwoUyG0ok9)$Y z;9rHgkoPZPu8p$c1%L^)0Y?jS1T9vWqh^W1kAhQ$$AT*hPXN~>v;UtAff{m5l+#bz z7!!CpI7i$c2e%ep3f9J$5atbVcX8)PnYP6Q_hVpfiwS%ZtZgxYPl3lu_)o#1$s%xh zQ-SbR@B%VkU4WKng>eWQV}d)sWVJCSaB1**2~!TNZ85>UJXqUe0;hnrEv8E0G_@_J zO1S=bf`*MT!2`7%HpT?@fzL5fFkiE{Ed^P>W(hO1pUG*sW5C)L6Sx6b+hPJY0&81L z;HF@0iwVrfvFT&~4}p(eZHxS)bE={^CRCOjEjO&HNES;F(c^@Znyn+iV#<^(0v zSqAPPtiaubS23a9A{2oK2)_s(D*Q578)-s9d^ArG_t(MGg!yQmEqn|-U-%Swf$-<x z7s=`27uuJ>AqswYaMGP@g0~B^s*8oog5MHmwZAJ|9ei9k3;dCAL-1$9&A=CgTY;|# zcS8P_uSIwm9^VT02Hz7N1h%1sfsF7qb_r*~-6xz4rYal5)Bz_5^Nl%0m~YJK!Ymy1 zeqm<^w-|(M@n{X^tSl4i32r9LVK?eg(tQZHz3?b-SK%?>-ooR+1BLm@HB6Y7n;K(G zXEu0JNQAi%9uuAqo+Z2pJYSd%huY4Jyb=6@@N3{r!W@*?A$$P5NBA)KZQ=L8hlN9* zKzLt-Ghog(GlTQs&xJ38FADzxzADVY<eS1Ap!iOhuWk>7`RZoF{mV4@TILnzC|VrN zSkt2+1a8qpZVaZm0y1B@>XZ3NgkSEzxSg;S?%jnQ-~qzO-}0z18|+BoB=8J!70x^0 zg3J+t4df|db{dO?*(R0?w*_n6PDE}Grb-7B;w$`i;l5z%jMIGr_^9v<@G0S$;Pd1V z0zCoYx_B%Be<!>Y{HySDU~4d(DBA(`A(_D%FfCD&w}9h>i@}M)$G{bZKLA$|{tO(- z6oJ>it}s8l8VO$lHy6GPZYz8Z+*$Y*xTo+Pa6jSi!TG}X!6StE{y#3vA&VQr6!Bog zDHM(Y&lb)A&lk=FFA`?^SSH*Gyh@m_<ZFbxgEt8CGi{6TQ1A}U|FY^vLD(%G<H5(t zc%mer)E^0>Jz72!Mik2hVfKJmgzJL87G@jzR=6qn2jQ0B2f}(AqrXMy0uMX-UuMkS zFk1K#uwR(HVQJxE;Bvx~z!ikq&@zPCwrU731lJZ`0d4>eF|!vSG!qYYEUkn$gWC&l z2X__T4elYl2RwpYE&O;L_b;9z+#F#Fg*$;~3*#h1mW3j)yIm&C?)F9Df#40oL%~~w zCxLeevx|L8cs}@uFniArggIF8iSRb?S<Sfq`yqTG9!J5~h55L=EzCROo-kYfFT!m3 ze+skZ+hW2s@f|o?_*XD3kF$n;2geEj1x^f!z)$6h!W{RlBFy>UTEd*7t0!Cm+(ek8 z8!d%vg7bu_HQ7bD3Am?l4!ECis6B*y5xRm$2=lfXC)^i2MR**zP<R@6w(u<QeBpWE zXN1>)pA+U6agp#_;EmkIjMc&~->u@oFW)zWKLfuhd=Gp`m|wNWgzb0$d@9VZ+VjF5 z@E5{dcYlwJdo>Q#{>wj%>;I<+@$iU<4F{?Ob_%D1O9}Hi6eElq#}Y4G6PzrZ1x^#L z1Fk0A5S%5P3$9NNp+tNoY9b!&16l|_3~nbp9NbxW6u5`*1n?umkAnvb^L=8t@M7>- z;icfo!n`9wkBP7z!aU(E;Dy4kgO>=i4_HsG5q^h%Mc4)R*M)uHLu6D5za8EaW|$9z z8HPXT7ZvweYG#|zMq0elykobX*rR5=W=^r5-J^bf&Fo;kyGONr-RxjwtLI)fI~wEE z4IVnF+FNnRS95W&Zabhp--<9kRdE|!9cnTUbJP(Wtk(~#*zNFat%hueYeV%04+E5a z2M&wX!#t#`mvNwl%%684=mOPZC&c}y)$*Mv!r9N&S2!Z?+Pe^VnVQQ(lKPB?TvhQ6 z^LrSai`mT-uB)NDQTj~*^~G*PnWm~0)47$JQEXN=PO0&0u@rKDvFWpJX|GNeo0aU- zpTc01+Wr#U-Fr-*F;tb?W2V`sVK_Csys|G`t=m?sF?-BP){EoSavYK0TL|U3JHfDY z@`RTjKf1Kp^?2)^Ey}wW$)>-7E2U<2DObU0svg;E{$pITmRhvejEl&sQ%@V$+*bVY zUi10r{0Gsv8nkp52{@=PPWYcS8At1BTucj=L`Fv9V2z?7f2$(`|CY9a$A8yZmd1UC zm69C3!8*%#oH#h_v_XNzm1ESYBWA4g4@5(d^;UIYlOrb75&1<#^k60xn7Ex!P%HOC zh=}Y*{N4c!uc5pIIih3@CAUbz8p@S8IJclXfb~rS2iFZa*s}S$i^%gR)V~RIo`}M? zjlBWi9&{LcL!x@(s9D~KQtOVI8C?P>8cc33W|04&?MAlA16o|{@FUx;!+)%lyoypr z=8c30R!YvtiPGdI2he;QP*RJJ#x6p>NjUWxzC|kWJ+pMEJ)#u&GVp(zZ#?pt>f>%X zQ+z*wC;R?Jgh@WmWK8s}Lv2j(ad>^aZwB14iqV0fQT;wb(loHyf*C!HurRR6bv!Vz z`J@|92wz*crTSJOCQh5vn~rf@vq=M+A==&W&4brWyN|j-P}xKAVPKQ?8M%sa4pMS# z;wYVS8^b#G(T<R72ckIk6JdfB@f_h*jIL7*evBPMcon1L1G3B2f?-avp4=`Do;f}x zd%SuTqvJdUudA(UcFZgrqA??jZ!S*G@bv;(eFu?Sgl{EWY`*IFZ}%<5nML}jXddNT zj4%!#RqLF-5vW|3&jF71?Zc_UOec+AI_qhRN5u#UGo5o$xxVWNY4LGN+wgI{q1DHg z8xg)7jzZde5r_;konOEWW;!|g<)dl>Yz8787e%gzQ!oSG+DvC<q+qgAV5XCSEhbwG z%yhEF*v!}Ls>X4%^a!>z*y-dFfjpB#VX)Il-H$D13&eq)PBy%4Cf9t!PA7$f=0gmY zWH5(QCPyk^r<1Bbr_KBDhn>#75YC#^Yk-~3IS?+IJ0jG!<7Qk7&eFgrX92RfX{O?o zV3d=e5r4#<M6I~;3|<|JQJQNaT^+S#HDWow2TPswgQd>K%JaS%Uy4@^Mmg8P5k@&5 zQFY%pGtkEkgrBbr6Du%Mkqwl|tbNsj_svx6!AP~^eKX7YhFyKl<Az9;@PS#un68?B zV74$!HSYs+PNg!e;pp02C8lq_=sJg4CX4kPN)g>?Gu&axQq??RK2-4?I(22aB3)ne z8uwyx9Ii@q??ZOF3e+<vaAR?DJbD0A^;rT-A=up67g0sN`f!@*^KC$sc{sr79iNYj zyx*8<_5F;(%$#lYeFfi33$4C<)aJFtR^P`sUdM4b>hms+Ts!#e5;Pf{_<9`I!2bk} zQ&5BtaSYT#g4X~qBEes9{0tFhzGSsHGg){~!=HGy*dKWsJ&6LL;O$h856$#JRP;;m zcBd@_*B$tHd+1B#nu{>ro@A?wiW^>i>NZy~O62X$Q@6XGrF)-n^&Cgq-o89zhid|= z%KHej^tw*k)Rhm-46`XRKyhfz(^0DBr_64LN<3*MH2DrrHedD~IQjacG=?Q`6>Kv) zat(@@xAh`1!^cHeR$n2UBYZF7zs=(8tO`z=$+dW67=w8yI9ybfHu6~%w`(6x$r!>S z2K1UgV<?MmTH@2yiIZlc^<9U$bJ84X{mG$vePpJG*y;?Zp(D^T{AsI<keTpF$QeK4 zpJ6rj;_w^gcTsqe`HGuC-A5xr`;UcO8Cw1}Ev=_7jWHULTK<FbEtb@w8-6A-&Zxl7 zTO5Yd;ZLjbpEB#?!P)MVS;ojvLr&ot(N)dGp(A@kqob_=i4>!J=^s(<WNVDB>KbKQ z`+-b<UgdONE~B%J({I%wSH|MEt~Msp0aDfJ>W5S2JEgDV`WiK?sAxTMX%y{5@bnCI z;$yRQ`~W0tw6eB=Cj+#^pHWmFPkjWa@rha9zmfr3Tj@k&l<BXk{-2objaBNkPt4k- z^hL_Iz5-vPTjol2?-Mhr?g`e(21B1Yl{B+-s13Txv-nXBPo6@SzN{OJCWxK&i&eG$ z)U0AWt|onoJ3K?J_!RXrLG9sTR`J<S&1Vd_4*SeZHKwYCpXs{W_?h`zd7b(lD=%n! zoI_2l*Slk7CD4*cdR2AsbMxK!YCMgXBUq+voZ}NLMG-$yah|KsnAI|0LttZL1j|Bg zh>Yp1`b|1QH?)Y1My%@15v(ZA`De^hf1EM1Q4g7C%>?V&NY(MI8E*_P9(mTxG^~4~ z)ar9)912`~&a7sA!=b)9XI>8+VWPu(;gi6Q^5B!Uj=Ff>tkI$@B!3lti-g@HZBK)9 zY9M%^1=pD73__X0*gS|E0A@AUA^x`rRYpHTb00*hP8UoQyUY){fO7R!t1g%c#%Wc2 z!Av(ss>>J5)W(a@D$K5X@t$0UwN-|@)L2@qKrYUuvw$b*(}pE$MLlRovT>O%I)m2F z6z5zt>ja|`arRcruKy1UnFYn2?wSSBdVlQVI)9kg9RKTT0yQ(UY}w*0d(4tfp+mf6 zXf^!RVm-3G;+KY!QU`^<zsNi({HTv?;A-->o{W~rUj))9v6k7LeTjT8EFt^DVQ4AI z2!#1bGF3_W`-`mvb;92X6o?x4%<mIn#y=}u8vKPYzy7WZCxLGXr-1JYr-FYLP6x9; zVfvN9R&5~@LRAQSH=##$uvfSa*c5IGrkyv2$pt3~v+dH%8{IpBD+~7q)3h6P<ajb% zXGtyvZX?VcIl~)J!-EyTcN_*v0rwH+84MIo2R|yzGvGuk!}A0t3iG|cK$zdPA>n%9 zr-U1Tmw>f}%%%{E#G@5>op5_F-)oowM|!pj^BtdWb#xyDep7ff_>k~4Fqft<%sQ}M zJOSPSJ}2&*k-z0j5w^hNhVWMKZQ&i@d%|yk`QTxq2f>`-C7%LEpplY40Xu~+f=da1 z1&$HE369r{`o9l>t11|oPpw*Hw0u^3Jz-X9V_|;m<O(+fw-s&+?j+m|++DZ_xUVqZ zng<CF1P=>|Fc`uZ;i2G3!o$GRg~xz7h0MaSdglqx1uqchsNl20FM?MHuLZMnV%(kJ z^}?au5MB|159@8h9AMim{5E*M@Vj8X?J=RF;A6ta!JI0l`w8%A;g7-Rh50RbS@;$h zFLM}5LWEx-+z}7FRfJbzz}*i1S=_n6!f8VWxR-FH@Rby1-Ze48Wxz?o3E(v0WN<a% zO5iNv>g<0wRm?<rueT+mcVh;fgn7Sq7iLG)S2zeBB+O1}m@qq~F~W&p8l+>Iso<Hy zX<%CR*E?b};|1cu`HW|U8-w-A3q)=P)>bsZ&B0q423;=>dOEp;X)TEy3HL+7JQ>=W zqdO|~9}AgC>c18;SzTXBpd>I28Zbf%__lB=_?|GU@fYEA@bAKv!Cv%)w1!m`Yzp&a z$_nRzlfoR*>x`<12Roly!n{@L2@e9(@Ej8z3D%1(z>~mj#eD{tM(7ykNpN@J)nM8L zp!-_zAmR1kVcJ3_JT^iYBOb4SCkgZJm@d2rJX81}nBx>o^j+{mVYc>V!t8wXA`FDN z3|=elKZ7?4TSI8ouZh4GzEhZ!D*Sw82AotmAe;==D>dMr3jRRcYk>JJ#PIw&JtItu zYTOlr?)Aafgj<8Z0c#6s95MM`JUW1X67CHCU6@1523i#p;u4W4VGc8Ug!_T{8pSXJ zz-5Gofy)aQf-4DQ$T?)GD#9Xo)Dq^mc|GB!V7-C^i7IfexUU3rdkJR7v7`>dyTAj< zzVKuB(SPx1VMGZVxuhxq-d4j_E)gLX9Fjn6)m%->gxIS2IY_PvE+V5dK(}FeNtkyK z%_PyiJeVd&$h?Dg30DO3ON;K+!H0Eb5b8rXDIN{M+JYtAn}E-YJ8zrI!Y#mG33meX zi<F6W1($40-3P3VS;9RZtc_WM$AN88;qakC2pq0r<k{eOGTzbRz{$eN;56Y3F!xts zm}=lGVb)50;cPJNN-+#iriC#3fOf*oz@1BW#BK{gugE|I-uERNQ}+kcWDFA;2p%as z6g*y-_x)7inc&BT=YnSmuL0`?8MxLgoL-OtZovM34Ff@F1P{F;1I%jID>A?=sa}x* zX4k7%WPo`I^aj-6cHm=@P6zNO!n_1$g$IMb5FQ1-P7WdRSO~Yo<8km^;rZa7g`Woh zA<SnyzdKpzm%t8T_Gn(=4PaB4&-=2%e1l37W``E4B*GC0RfYL1uO<9BSg+1NX6L|q zbq4rLuwI=3z6#c>Gr+%q_2LZh-{9Voj>o_y6lUk9jaKsgpNk<zi$@voMBxOmHd={< z*wg9N8Q?VVTnWP|W^J?*?$yBBXeF51pxS69xDHqwtpqm(Z<M&4P<u^V$b?5Ogq`9+ zHPOAoRER$y%--;bFnhxfga?8@79IgUBRmQGg>V5_FWNv}bHKO7{Ym!!_eEF+rfm^k z*9~BrJK*-bsi;Q1f&*Ly93$?${o;i)!O6l|;51>rtX31|yG52T8*+Vch#7Q-&_q1C zfm;akR%|ES7u;F6AGn7wJC;X;9|aE<9swRMJQ_S!n4QmL;R(n;ytD&_m<Erh#e*Hu zbHcojpBJ7FUMtKyLa*jP+#;}E%>iBuE|xI7BMu4g1s@ZB6a0~8-2ZPw_)I(wgD(r8 z0_#;9NR%yKui5~A0scY4+yFliz6t(Y_)jorW>~uxTuN;!4D163#ht5u%eY10ba1)i z%pozQy)gILW@1c7SngSggY|4*b!%b_XUghNg6lZ-Bo5Y7{nYtMaJ8t6$#BhA1w8Cg z$9dSK%1pswff~-kHnn$3%!`;?>opb9FtvGV%v9^;St@0kjz4}HT&t=>(_*R^DHv(8 z2A3Da_^j8TSAl|<O7>gm3SUyqxItVexFgYl1u<#HYPI%-=+bHpoa~?H;c>6+h#q5z zzUmx9)KSLtm^AC1S5@WdF_lp6&JgXFd*Xdnn+-Km)!OMX|DEGn`o;Cqw#+&;YjTdu zdO5E+_OX~Iw#ZU;Dtf3sp_qgaO?+b}i>kB#oxX~<!qISSvC+@|6AunM=aDge^#*Dc zwn3kyWQ!^dKW!Uy5z>sbv0)+N8ZA5vA&M^6YzB_NDOs$4!b>K%xI(_4Y$$h`sXB%+ zy3MvmXK3RvhvP*=#gx`9_&7O?Vat9Eh=lGVAzS^AfsVOAOlfi1mkwiZNVGU7N2<$f zqvKN}kdVFkPjLD_=FT%rilXcL-Lo^hlXsTgnVw~L*-Xx1U7}0Q8I&Ly6eLJqKw!us z7zj!sqJW@+ieg+*q5_J71Tg_hlpu(x7!bwx|F1cN_x*f%eXi^M@XiI>zp6SFy1Kf$ z>eT6K?|GhQd_gya`|88n@U4eWyswwae8!XCn)3&&d@W~6eDyWHH6;xfyZHFF3V*Tk zl>njmcH<C$m9OXE(E93k;P&vbV>4_?c4f{C22+2ApK}XUK!&Rq1m)vx*r>4D%%GLe zT{WEtnX1>-nJ4=x*%#num(HVPzw1sld}gq8WC_#o9l>AI#}BXBe9y8Xedmya-S;Q_ z9lj6Y6Yt}+JHgil;!a;Z<mvJ?g^%0Ek*~)`wG+09^CLIAYs?PB^EF0*;p42!^wAR5 z=IaRWIA0r`^m-<Zw<ZoCqTRKUY6jo$2r+!rv2txlD;sJfV!G+Fn?nG}Ja1QmNns<I zb?Wk(tW$gPDb;>fFdX3(bCoh5#GzgCAxa0$C*XJ~c{ZZBN}IfZo06BKn65PK*pXbH zak6v<2b0^QIIglLU#>rrJcVMFOun=JW%3{<P{Z5~$MNJm#wjpUaX6VwJ*i87!Y$J{ zo6PsFUCqr6I9y1c!JyXWLx}q)ZZH)$J6Jx_ik{u|ic`E9+)LM;roLKckeAEVQ@ea- z@Lratx2cyQ%n-lY=IX1%0%ou;B?o9%k{KMw(hbqBQf81-W7l}I4$6>X2J141$!0&e z!dO@`zfdpE4(6GEtAn$HwQbenRQ#M^EnAjd)t?i*Q1}kwn)O&5{tEHmT$zu&(s-Ac z^`dtPoV+q-J%;dEmEK16o*OJ($k(6EK8%frqaK=>E9W!zDHOu&!`K`WrC+48AD!&d z)1Oou=LWOP_tYnIgJm;yPKy&Ugn9vaW=$M0!Z4Ro_H#JXudC#F!S?1{HDF%wZhW`% z!+F8XQnhh%_#|H=2(im47micc=LI8alj!f^TS&S<7LM5E31!RQr<Ohtd?0r!q|Ity zK`g3wu0##7S^Xc6$|WTY=Ld&76D}jbX4L&(XnpTe)jBvmC8HJxUv~U!eJ?(aRHLN5 z3U-Jq`Ex}u(}~VGYelg1(vm!@r2X1pBphkM3xNXj_cR&x%inKgR2qMe@U(ad@Z&m) ziH9A3+jw?(j`7zC@>GQK$3aqzIZY%()EFqtEI2iUf5c!~qa=XSGmf4Z0n-v=iZI4S z#th+9Fy@b1CL8>aa9QvYVGfFx3D*X1AR||v!z;p2ao|%VxRwlH2JcD$FDsSf^k-%t z2r~nkJJFw$o-c(t>N+7@0OpH6l&K58B+RDtgK!bph89~2waYh}qWWhzn3>i;gVVuU z{|wFnYyC4g51b{DSs<-{hChdgmBqgbnB6%uU?B>H>w_B!vp~(j5ehYiqm2Z#1k<*F z{;k1x2y>`-moSHld;y3ucYucqQ}I1YcmR03@V#KIi-!CJ@I3Ly$S<Om(M)Io0<<m~ zyc~?BS)IYtVD|5nSqFYucmwzi;a9-#2)_#EBZKm9gFhDD0{&e1J@84*sQ(Y)I41!g zfw?@x$Q%a#B>X-2cj2qxo5DYV?YJW-&qudgn8Uy%VLPsSSeTlgGQu<#tf1Avi0p-< zx&)+v3xqi_Y9O2s=3|nXaoDK!&tSeMr}fWZPKJ7mOm(o<Im5pWc&PZ(x=^c};UD4T zM(dp6=nB4Hgt~)g3G=?yI%miX26GLQN^{=RtAr60{Sp)Wc}u@2{vPlv!n~#5BSV0< z;)hxdEDo(h2D3lWI%IGfSnH6%8DOnL24{kyL)HmpgS847{<+|v#6KVWyKp(M4W(tq z6~SKN>S%vPNE|g0kR{v-Tv50Un9nCh=IF4Ia7S<}VUA?<COwep5AG@cL&5!pXM^t+ zUH~3JjvxXb=zPV987u?y+a=^Dz_WxmfaeRp1m=T<GHmUS3BLheA^aA2wJ`4jjsPjY z4a^ZU`F-%P*TnH59B&DK1l~(_N3YX?|KQJrd0q8}J&<8ndP@8Q;Pb+zz*>b2nXvk+ zbs$SURUs*}WaxXrx9ny?N#+N^jW$eL_V2~S=4yFW<|9l@W~h-LVPdjKZROz&<@;Dq zUiy3-`~ctR%-;uBD>Y$Xu-I&;zNc%dYPcVVuzGkuW-?dR&V#mOwQoNrB<t1J`!V%c zR~pSuxjqTz!eFn;C-9ksMiVvI8}SL|F`M8lujet3!3mqhXCY+!GFyG}NwBQ1S<C1x z$ZoX~?e<_NlW_p4oJF&Ge`)q_xh(U6|CrIJrw;_fafQ)OV%v5-RC4-2@OD?^X|(wT zxPAEWi2ZCMLANaS{z7}jJZB;5@1J?j?dWSTUFnBM3g$T+6WJC}t~ArZl&1#6oe7^J zWlVX#rpunt15eQClm|B^Cp!s-+Ogi55*Y@!d<VgeY@**muysW&`3yo+`X;ck+W5q} z^%;c2C_PO0xLLg`9{J-l2qwba-{DVu?OpnWY;_?NU-tqWE?SG>GYB<eG6~v*FUxS( zK?(_tUWQD-@GxFuh<K*}VBFSIbv+ua5ZRC7<1+|U2fL}yaf)#tTc)!u<6?@_3PR49 zaUTu1678<2ao;$U&j?We7727l^yz_Dae~tV+<9bbAO)iL2X4pTDS<EHGda)}p_2k! z4=N6{MpS%Ho7?<M2-HPF;{#KX(6|7{vSS0~5n)V#`ec~<bwLSSV(#aTn)^|o2XjAe zqz-dGZg*5Oa2|2;0#ulyQaQG9i@BeBF&~kE1_+tq2z-VR6W`HB-NM}O2Q~dzuuMY> z0&X$u<G!|TG3%oW&i&zLq!=~pbAL>ByWd50_d(W>*S$x5bu3sjavez+fwl-R1MFvP zfycpdfxl6^_P`PZIs#NB#s|3Im=Gw0k2CNP&n>_`J=_6q590~k4j)+WQAy;9TJMcP zEW0;qy~mw?j6iFoZw9C_w`qgLxWG_OPVE6c0b#v&9N~6v)Os&nmy0^$Th@DAT1hv( zc5Pdi!gKe=toPU?yfN#&9_pLpoS`AEx0J~hfOaV~7W4*9PGw$78IQtvW5#<!P-1V) zc#pdid9%cLuR7zzjQ8qMEM~mNF^)H8y!Q>#^cI-kpa>^ZK4Gbvnltev$J+<A!16XX zM?vC3$`J;|?D@V?OTR`_o=U&&=5z?)v)V<d2JfBPp2=&5_MrZ}J+%uKd?Q(y-sU5a zl+S8=`|2=!R-4aM?*Q#eGDCw|xFOnA$_(+N3*PZ2KUaotZF4^w??0A*4zA;P)uNA5 zvdlNtfNz4e9qG(RefLpHb;kf5nE5dRcdM)41a~!LIRm~nTt0BK{(bF;`0zFU_&Qv` zU%Q)gSYIc$F{hjMlRo_!YnOYU`td}tOk^K|@kIr0_oRCVf6RXHX$1Hi-b8vX4!E3& zZMom1`)8Cmu^p2$+=I#O$)@`=)Ky{!Hfx)kg-GnkB<)7pvpAULq6SfG!0Bu@@ZdUk z`d0PG$)J@+b6tGGLKi;MLaJto&HRAETh)$}!LXUDzB-BC{Su>IuuaAxeV+233YIJP z9*SvRw}p}MbrxjhNK}4~&f~f^i-M<-vsLvv6|91X(EL-uGUg@q{HfrXawRO;K5ZM; zUPnF7s9SNe@MT#><7UX&rd~ZAY>@m5*yQV>`i)t0WsNKG%gzL?3Oc9NJef0)sHI~+ zqbmUEl;_NV|7%$`RdgnJJIv!}oC&4`bgUhW#UXpGt!mvF%*zL=y=Q{uGT2F*M|qNF z*Fv4(aVBVXG3vIASH82DCu@;w6!}8OXPJMc5bY~!om5@U1`8{A={q9{e^H}aeQd7e zt{OFU?lYMC?G)dtUOyWwGH0u6XM?qB=sIqyZPXm7+q`zX9L-HuYYn<}fm-Nm)r{_4 zs>ip%bQr5m_%=ARenl4ag1*`*$aFRSV;^;2?2=s2mwgT5<&0(RU(osN*XgPn=YoqW z^`iGqoq!jSIRi0QX8RF=M(haTNw>!ToU!WixnQP=c5psewtfY8!BmfD%Zs!|$K$s( zqHUp-ZVTKDFPd>H-H5_SGH<IIc|N$M?Hf!WUnjtf*(aGR*D?W}alVf53L-=kh`Nu# zojYVKJ}6#J$4o%!^X94X7lK6%Y5HJ3Z8P^GjcB8PS{EW+*WlB-g&FmG@*>T#G0R~( z%VsD(lKAmLFvZ-e;x7g}CcjUa;TI4b)l?KFIMmRK!RDzEWZ@iRK8;c|zl!qXt2Ml; zEjFk<7lREV6X4|zz#tIw8*~Y&G;vSmEt<+Fnb9Hx;icNpqY{HxGK4Op<r$>n&e44q z-_sQ<xCw}r>{$ze))ezRK9FIwnM<9?Xl?caJxj^-Ri~GP=c$v&Q{GiKMkJ?}9J>_! z$dfP&4asJ7`~PFF-w`EuT@S8t{clt>=_RRgp}*}VlbxZq4I=|kB{7W*r*ARM%T6*z z()@ix<^{&DB^w292mYwWj2Y%pxfnCdyO%8yHOrqKW^ibZ-wU|RW^$BU@-~SX=3Ss8 z7!BZJT+B%CPck(m_>Dk8IhtWdIaU}$ZDW!!XKd4jv%qtNbHLgh4ROnX7m0rb@Uoa; zUKKdBIsig-z*-#u=HNuD1HkpbS{(o`0&8^uxD{Bd1HkNtwK@RI8QUJotSfk*a1Zcd z;a=3pd?}8*z~2au0iPA-VD&rUso<-^)4{(Av&sG`JO^yUC1Y(p0Co!V_V5co3r+z? zD6}4q(h~3jI7|2?a9QD3z?FsH1Z(p(#N7`r6#s+ZM#6`|+I$T%pMkad0Q@~zs}I0e zk$=>F4US(C&`ToU1dk-+`r}{pqs{<!jMK%R?P#uWDtMuAI+(kgFfM2AN;n7nlyE+H zt!C7JLpU}_!0q6e{-6o?P4RCA-Ynb>ypN2#g9SSLAN;v68|g(d?i$<}#t*`r$NnOW zM}l!fYh)nAgiJ^>0`C?ssE|WopD@odS(s<ZHzz2=v&<CE2ImXsf-4DE2G<cT0M{3e zu!Y|)4yx?BkbTiobLSE=I=txKzhLAS-TN2JGq_h|_^=!=Tn0QvI14;om<3u)W<>my z-s4vsPe}l3$5<<j{=(QOjQot(h4Da&?gNattgVme4^Ot0gTm}iJ{M-qaV|g^*4$}f z?lBeJ@D~AP5pYEUs)DZzR|nhCKpD9v*e_fg92RDk<_NP!D+{wm3xpeii-a44TaY72 zv>6=jB%lSji*PG2XV%QP1Gukn7jVqH><%!WlC-Pg+21eB+L|fMw)KE8YfD>^L7tZ^ zvQz?CMNbH`idG5dfw`{63|K=i3ReQZD$Lp{5oT>|6=qNRzA$Toi$P3>C&mdDIAXMc z<0Ks@8Z$m8%*Mju4*i+&Pr}UXcj21go5HMiz4tHV*;R8g%(yMVdhcH_YfJC_3+@fh z)_eTIF&d8Y5@8;=s_+Uh7d@HKDsVmFb>Jf5=fN$6H-h<fM9RMnrinWF9q?VkJHZ2m zKSTR7hKl1$FlTm*a1=aV_&k{FdGx;so+11@c%CqO%!h<A!Hs?&8S-)9<>DU?=17a_ zP#sK*vIreXaJ<O?^r>tV?+T}ZcM4~LKM*bt-Y;AO{HbtV@K?g@Jx>U;@qR1Z8GKb3 zmm^~QCJtVYzl8gPwdoiNGz_f2gAASk*55$}&jE)LqJ^FZ)_eTI|3R?c;}`rWSnu%* zUINy8{DOH|>*%<s|J88lJ$@1JELfYAfq7lKPzY7RUayBRf})mV@DGEv<rtU`7`?|Y zn0Lo$k*@{Td;G$m{RH(pOtTOi-QyRIdT`8_fCgZ_$1nWZX~ay*8iQjdW$ZJcWzz|@ z1jj7O+Jj#e|Bm386<Jqs%!;fBc$dgT2E(EE_(f(z!JkXOz2M`*ygN<`j|KlsM*qr= zMepSc<|s|?<qPI*>_BfsnLMyZxC%H)xDFT-Wf*2dh-aB00qhTQg?Tm=g?R?mg?oYv zg!_UU3f~QGDm)zAT9_x$QFtntukSJ6ne6|2i(>%-wCNZEmV>qF82Bl$wj2XL1Ev~^ zk=KFekVDb-u|SyZW05f1$1-8I4}N5o@@yZ^kRx!gfvlGRHjtNv*+AY9X8Yj#tc=X| zp)JI~Mc{qn-x^H4DP_8Wscj_p2cHoh0{%|;9&kkO>kFa#;J79MW55Y6M8-vB%lG{U zCkx}56y4(&GQ8fI;$H@wFPsgoB+Tx-hH!cCZBdTss%R(y>`a;p7l2y}vwd_FE&_KK zX8Y(Z+zCw88w-6Gc(^dz$3)=);Az5xz%yMXFLVht@xf~8`+lL0(5yG?k3&E`%tH_L zH4e7btyR?lp$@hSt<`iKO|RNN0HKRi#z2H#ZKFmFMCieGY8#Jd+bjPd95;1PeR(|C zQN4^K#Qz!;T7?&8pBju<FLhT}28SlX%xTCFq_teViG%IhI2C_)s3J51HSP}O+SW}_ zcibH+>llt|nWSdY>r6fUndL2ahXRgY&?chG3TNr8f+y@yE-Nfs>9MQ8Js~glBgnWX zRL=1@LJmehwS3n-p@3N(Ujho1^9@CRvf3UsFs;4R{4LGlY=Hqp^kd8HMt3efbt+l? zc~9upx0Y+FGS8=n<7(C^&^rVamh>DNdc_s-_%L{#X<`Kptz{DGHTJWy+1^@j;G5f6 zZ*W5BpY;Y#$FO2>hzFbFQ#TGyM-rX`SY+T!v;5{VQpO^~NTj6~8TdW`qHuN*Z+{5G z$Op!T{E@*(Rt%~-Go$Ek0sIbHTs->@8x7^ewCXmd7&EOpt2486cYPOE(_vcmE9BiY zSGL#Q3`FF65o)jdHPBTS4G5-HWg)6%91VynWn3sTzXI}bH04T#?={AVFX#{Uhfq|* zpU(pOkHo1S<3f2|-+~KvRqL3{LX2VJTT|3<H^krgw(Nkg=r9U35Z{j0o3N{@jTlMT zQ6L|6<v)m0;Kg5L67g?BuG9U$C#VDCLZQf$DEDOlo%lP+&*?(3|0AR_(SHa$!A}G0 z@%}eaE#v$rP-SENkKykaKSv~3V|W;%34M1V?Idg|K;4f2Q^;O1{8XMEHT+NFTG#aR zYo2-j&k+-Kvm8Znj;;<_#917f&q(_bG{fPqg%dOVO;G-whQA)lk40YFDWv3FKNw;z z&IGZg0M=p*_jyEdZXp`(HxW-P!`$6aB<F`~;q5FnV#p}N`7zn;Zc3ShtSGO06Jj|( zCHo?!qPAjm_}%X_^4Da37<s8KqpNlwi2G3#{G}zV=~qCTpPv<u^K-G%?q|pA@IQ;Q zjrUK$*(UhEgpAWq9f`~T9BSO{pNZr={wt988a@u9u(!Y?oYDC&Bi!&;Lx}0mM9td# zOHkT4KVNOL`|p9j!|-vKjJ*Z8Yo?zY#2fyWh{n~4jqplNMX=smfR&iS+QHre6gE=W zcCfbq+m1bD8Pa$Av?D!uPjNdGOgn0)u%%+R0e*m@UCKCIe(W~D_Y_`AnT=Gi+W;Hx zrj*(|nKbR#k#dPiXPM0NU`lIMWnw6`DL0_U)&iV298YP_bP7y<koaVZ2MM^f{TLP} zCbEdl&0^$mA!R=EZf(v(Mt_EGc+|mx38m|C28xXZ*1{7T3p79y?(XITkjGlZL{yFY zPLr1kYZbhp*lmC=tW~UWtFI@9%2!!}mg63xeX$a;4uS6RCQTW!62Tp>u?ImFxM(W& zW`e3&9Lhy!cSmukHVjD@@{pu<6o>L`B`$TYIMmE`&Y>z#3Qa5PLP@X(!EVIWx3s4~ zZu=!Du&3cm@ONGFr~{Ki_40?)t1C|--u);_>FLQrI^Ac<y~!^37*%z0$SQpib>QjG zR0D?V9+W-ctuu<J;8gu4hjQC;5a#WovvP9;>g~p4?e4)i74IEPD&Eb_KfFE238lu3 z9b|ZWF$JfaX?uH<!-ngoP3@l?%BfKgW%G@zhRfx2hY-<MTo3GZ`yl3<!o&ma4yb3} zR5qOy_ezyDC6p1Nn%wTcjRPD1C5RgSiV!mWamd5wF9OH;xjJL_e~EKJ%e6z&?r+Hv zkDoh`8~*M%d(&|7y|6%H8-7JV-_MEdh=#il{1ZE{`?R~cyK`cvXr+CHVkCC%60Nnz zkVc}e0(Yqi<A&hF)b#h_eqcsE8YkETwd^RAe*sPo+Z*67?k`+C7?|D#nLr_}-(6jm z@BWY#VHG9a#<RBRjw7j%Y<F|ul~k7;Z}>(a4Se?bU8YL2%~U`4cz@sU7o#F}8UF8Z z#=8yw8DxIY@E0NK4gK~5z69*wg|IcIzcCKanEv%Rmv`g*+fW~e;`~3xq3by2_s>G$ z#R~qpYSaCp)C#<(&0cnW7pE;nV&*4t9Nd_R$TR~R0KhH<wNS>Xe!4$2%IvHLObzAK zdmlAsu3#j9-Z#)(xeXC2@C?lrvykZR2&kx2e~NPb;WR33@Tjd*LsinX{~vJ-sQeqF zbhV>Wxm8P*;VOPwsAXd<u~?UjMnl!O$F;e{z80x;p}Q7N%3P}5W9c5o@W<^eI#<oB z<*P@gh0@IxB`;13HHkAb)s-2c+iVwIs@%*_qimgeqj={39Lid64=U4a6h9HMuhE^U z=FJRcR-%!**)*Q5ByRDhNcH}JyD-P7_5=eu#<MhCQRr%4yVb#&q4#X3J?gPpp#tW! zZ&s*LO`T6z=fk;CG@r1}=L@<yMm1A)I={hPZ8g5pK08!kHdNzgM~nN?>`)^!Rb84L z8emRV?dL>&=grZ+yXS<SU|#*_YUirCp_a*9xHm_#WYLw42CMAq`rJ^}@HU)mawYCj z5Dkd8bIZO)z18jWLY99&vUji4z4`60xYXczp;orf9O~tHp=S7y{Lk}3MQx9wl0v=t ztnZG=Mk<>{Dr+#6m)mGE3s=D3dHAg$woIewXNU*;vp6#tLcoApO@AO1N?(h!x7yI_ zRfa7FL<Nd&I@G2ILSf5~s~l>@oKD8lHHtopQzsDEn)|IgGj-p~UCyEf%4Y^mxW*b@ zTj`cBi)l2uj1r}`Z~Q-epN&&R^Ft{aFQ5hz`;Gmt(CDc({=%ik%nzkvMQ-8zQ0X## zP^yVYa5rTM(V}z0Vl-b|^8WmgD_~1=s@oGvXXpK^&o0*3<Qb*>pCHbtQ{G_7TTg_( zcIo{MRFxM4$tB6_LL>h5ib_djW2jEc$gj8yV#_FZ;v&S1Sx1pk@%;HvEwLq)Z*dV# zoEU$tP!+Ky6}?}9KkEM){W;IV?--f$ZTw86Nwqzl2~mz{b56dFzyRuPl7+LuWrTCV zY*3Ub3$7$w30z0GHkdX*l&K4DF5DPQ!xj2B1JfX$+#NhnFQcG@XtKuL3=p17#@VCk zMAu`47m7a%x>z_5tc1&fpAxPB);k3tE(@x63IJCD>m?X)b*j<y_5g5jdc0F27lHM< z3;bJwKNbJBV7=4=e@+~~75^^aOTs*}UxYcKydm5lY~oV##KwVnf9p>rPK868UZT5t z3|xjnU=A+xgr5Lc6kZFiF8mz0KzKb^TVW#Zi{K{WzY*L@_ziFe;Vo37brZ*71n6ZH zL_P{0BK{Y^BZPkj7Yp0baP^W3<m16}#GfXjH2mTTWPle5cLFaHrt$Pj&8UA`Pd_68 zv%nm~GV*-z8^Vjh+lAMHcMER>e=PhK_>k}}@E5`~hW=XkGcZ?pnLZ7pujpkIIL^VL z*H^$7z&AwbDp)VC!2c((US0wJ3D(Oi;4rQ)-`!!NG#1Jh=3P=wxE8pIFvmr;gd<Ji zs4I?6V7;V*gnEFRi$D8<w!)*qdZ`66T*1^PoZwmD{vyK_%)5o>fwc)IWO&EWvWf-e zoq>Jfqx%~?2Zvs3K>%-)IU@8Dc!4lyAd7@|gO>@@m}sRiO){PlJ_=qh%)8`e;q%}( zgumzgPlGj<=ywF{5cZ<_`LL&d5}39+<V^5kVcrd23iEFGMwqSsTj5UNOTuj2dUpV% z!^s%60i_~vu%-VcLKDGp=$)9^3@``y<k?`p>P4Oh4hqi)rwOywXA3_BE+@>veih-x zU`~;k&I)j(t~j29gO+OycnREG_-$}o;UnPA!Y9FZ3ZDb_5xxo@B>XFQm@vE8`-J1b zdhN%J>mPtaFa99oAb73_g~5*s=Yby=t_*%sxF&dwa0Br3!Y#lXg*$*>7iPoVEZhye zUGHyzjPHPBw*;_7e=OV^d{~%Mfv<$w(!UlS4W<c5DG!!n&_Vqw+ywlma5u0GgAK~u z33dwWWpuwd1|on)mlPTSE-gGBoFzODTvqsDu-+X2@=t?nivP3VLgBZ;jfBzNMt28* z{Kw!n@Q*OF{cz~TAMgRNUi<+c0_(*e@DVUoEtLNPtk-_P--7kp5BNM-ul<0pg7w-D z_;;{g`vKno>$M;7P4@qK@dpm-o|Z@kKCoW=fqww37k|K|!0SXN4g7*|8Sp0IJn&n> zmBCwttAgJXrW)--&A9(*=l_WWGzA|KZU;UpOw<08!h^x*gzo|WC_EDUyYOf*2bZj^ ziD11Z1b!H-*Mz{!!GQ<{928mshh7u{uLNg{KX()^FZ>>usz}OHwWt?@z<iL<HkST; zb`%NIRIMx77aidA6vpFUf5Dpm5ep8z_yb2Oc#H^fgu|I6g|fhU+W>G5c&7MQ2kSK+ zjQemCMAvx02#&7tfJ=k*8V@)f%;9rv-;}L-e*+8@8Tow%fEjtOFeB?V9{4lzr{d2- zoFii-=>%UEhM4h_a1!`;VV>koVWvYh0OMvF)o?w;!Fx9#TpJt`ZUxrc10X^h)%lgQ z!Z#h(F*m--e#&ie_uU#E9J;BQJQS)!JWNvAUL4+5V|XysP9E}9k`ISgYJksL1*?10 z4_8=q_FKi+mv1j!^Hpjh4kOgCM5_{JqhqFplhyh}D*yw^&52ey$Loc7da0dBiOK4B zc-!u20lhko(RxEk^>4DO5rFWkEimp{y7NqmYF!*m#H-CS>3bc%qoZ2&9RVxgJEGu5 zKUD`&YiYy%5$ZYwac0>`kZ*={q#xC*&Ek?(|0L@lmAZZ*xuACK+WLj$<9$oEC0VN+ z@oA{GGd4BIvT|E<toDz_{B^WPsK04q0F60kgV2~iOHXG4Hx+=!Jctv4#yk}bLTk(i z;~qkkiRyr5Wmn>jAnNh1NLh5^9L(L)iN8z{r@g643tJiaLAdO7IkI&1MoLhAv)6F< z#~()nqTxQBpicEmNW<jy&~&SUZzghva+_m9Y{>aa*a}CusZxA9zUTv0c3G6#R)Ay^ zYUU$4wxX>Qk1_`y#vdcF2$@9mMz7NYe;~rNz%THb8u%GW+#m2E?v%h5M4lYjj?hVg zmN<*zKt)8I7|1~AgaF?c8z1O`SmOfhpT`CgFXJ#KP!GXSb0^zX_f#v}*BvRkwsTTx zcW0^Dsa7r;)bpuU#R%_ssB_<Bsp1jU2=KvW2KW%SX>;|sKsn@Y4>X1dY|T&eBDq(7 z!U&5HU<76$32JjWv`Q{OY^}}h1xQ&40cdk6Y^1QVpv`4v*;D4i3))=OskBwf?5zfs zw#t^Tinag+Eo*v5N_`4sL5V~KZ4olXcCZmRj-;Gdua>q_&Ex809MY)Xfj0JOl=ni4 zmyu%H*q-X|(pK|I>ruRaRIGP1rQYT?h>JP6yRV+?!yNo$bzhp5W@~O&58-H@RqNBN zJo7=dKh3Ibs~o4|(ydyy9J?w^NBzB`?n<|I*_t?1PKK4+>qQjJ+rYsZG(2nZCkXW3 z2Y|ZJg%eBn-th>F%C&#*os_^!S>zsMo169^Uae!byE#_y_M%qM;cl!}Wmpzo*(u4e z^70!nhOglnro<tPuZYbRMj$wGUlYc#yK5~gV_A{UaH76e^l`fXKo$7fkX>kl{-%7s z1o+1Ya5=~fJcj7D0F7qjj5NNOWLDxd!nhm%u>&O}(|KXxt1l&dGguO{ipempe&PD_ z^vXOzF&Il_M6D3<CNBgsb>w>)w>?BN8>rXISQT<#rR)atLrCOmi4By<eH?Cc1AX%v zsK3it>E;5Jo@s@%w9Ma>*?y}8rY^yCxXY%fZkg8e<v0>B+w0=9^EOv<=_6YF_PY2_ zpnYXDP&rvv{Un`aAMJfK>OCsU%8smL5zewwO}<MOE!|n>oTtzG98WusqiXX!FF+n2 zBT+P}jc2rdI`VV3BJcYr@+XW8-6LavrNy{Qcr=f%C}zY}w>eZ&wv`gn<r|~R=SK)u zNOjrkXItm1>9A@4q#M!c=DdOnZ_YOp@pzA>IX^0*I_Fr~^>n1&I>FUQu+GrIu!-Jn zJ^<AP6$sJG`hl)g&TuL)$7k`s;Ej@(a;&PRsnoGtE48#v=Wp{c;&I|Z>l6JwEL5yN z50~siRVmL(wH4S^i#)3g9u7nDtQG~sAsUa<!Kv5Vg{$vgu1iwC9ip>$TFPOC)_qas zn#$Y9Xz-Cbm1m`xBh{~YR#sYhT;7DXlsQA;hj7*OAEUt^szyHgg}th6J__(&$<Tc3 zMQ1_?@;2k!|HV7ulmCsCvDrDXX33q^tcwZ%MtV$5XF0W`bZV87k+)e7+Z;oSvBFo< ztDaTIRF^h;LM1QOw<eT}aLOLju60H2$Fyr)YK$2y-^0txF&Tc;L&P*~)EUGyZJZv) z44L0$Geb@Br}zEE$cn$ekQWtO5XJLVbM&=wSJa`ES&71o!-p*+B!jbr!{D;QykcA& zrA#w0J8*IfFrOXduHcr!y}>a}+W>Ii|J1H=)s)&b4$<xvhOXA2K7sxmqH!gSjIPGu z`#|JO@C@M`@KQ4Fe~!?e5N-@!CCq|8E8GI3d*elMv<AN_+yz`B%#!lG046#J{Jt=o z>R#co-~+-_z@G_E1s@Zh4n8G36HGmW-aT{<9N$a8Jn+xL4}$*?UI<1{tqbu8FkTo# zFN3-W7H&1Tl<>=7t+9jut6;6M1HS>*8awb?oLy;^9UNN_KqUnedJkM6yceuhcJMy{ zZYutq?%_oOEq@%`QTQyFOJ+>xB3Qpf4ZZ^IC;nH#W6AswwH=O0+7TV1YL%Ufk4jj) zi9fZhi-g%QmkG0BQb|FDCFdqF%^c-lr#}*5d(sBZ;8Nh2mM#UnJEmO=!4Xr_abgow z)8&ErSY<-&7cY>}&GIg|@*jLnm~sCQE)V9}QNAKDUbr&YD;%i?M=5dC1XHQO2pnsd z5v~uWf`k4=;EKY$&8iEx1G9ssOdl{u3gkgxzKKd625uuf9NbxJ*AOrYjyok_44C6V zMi>tsB+Tv?4|(lB2|Px44j5`W?f)=XYv~Y|Ll3Q`1Fr=y5Siz|j|*=^`!iOF<5L7Y zC;T~BTSp@@8<AGWf!T<(HV*tdc!$W}0Bda={Gl_5YU99E`)X|*n0BFB8wd7-wKk3) zqNaJnMM;QT251!={6pYh#Gl&-IMJKYD4h*QTS|l3=u*U=Ll3<{C;aok`Qp!Zz$p#m zRsz=)W_yYhilYdQM#AiT^ah=XKvliopcC91+(~43X?hD6gSFK(WZ3x(75{1AQNpvp z<AoQ2r$;%WUyh$I0V@%pHEKv`16XU+z%PQeMh(0P{EW!I4PGz22mFfgL9o`SL7ta# z5B=qVr1#hq{?dU{VgNch;~Nn|mu{REW|jUz=1q^^jsIXyUFeUy&7f5k8NqrKPEJu{ zJ_wgno!$$EOJ2Iy>gL2u+8k$fTsF?Kt8U}0b})@w12?|1^CJ(VRpap%_64h>mW;PL zU=yxWaGI-CjS2AGRj6i7uwe66s1D-@1G?;qR<Z4BE45-GoLTDPL<rke-D1qjOD|12 zo2(`kV^ZEgJy?tx^5PuKv(=l$R<7-<irUWYDncEX&@Dvm+`^L}oU6=9mZgfw52?<R z5V1EJOrADYTLfPpH~(VqT?^+~L(jx#sJ)cCipEqnYTstR3tg5Pb0C<KI%wqRs`pjP ziv4QTsavylty(p!*W}DRu6p&lOBelC-W*)=@MNp9-BuW<-koOUW}HO^|IEp`?tlq4 z6{nb!pHMfZS!t!HHrLZ{>dO#%Bwo!J8w#q1(=E@)yKn_%622Zu$s|0JzA?kJHQHg1 z!*juP4=z3o(=OqZ+#K53YrhOcn`jLonVWA$HnF)mWny#lOENdVPtVOG)P=|9=3&H+ zZ(RUk!+ivQZW*2}N7--9)~Orjr)+LOF2IMm5#U5C5*Uc+(*s;yoTjJiQv-b=dVgRM z{!R(JhS13Yj@>2&xJ*<W;1$8!?w=!gf}ZP-53EN*;{vbZ@7O>-B8&;ViBL?@xd4&S zcQaz}<2KchM}XZm-ga*S#@p`QAXhW66LInaV-X*fF%AOG(VRN)<2HR6r#?bvI08u! zHUk_bsox`3RsSE9l!<@01ZD0{3#m3UEU)>b${LVhsZlem<SeSKvBB3bOy_;pk$%;j zQ+loiCZAAiW>}?dE{EDW1M}g{>huh&R(dmJh&{PDsXv(VI8GaTa<Rugl5#ac)tG68 zZTa!4?M$nt`Ldcm6Vqw8S~1hAQ0YmW2)57S69E=ae6b$eXMKxe%XA#uXE6-Z@%`!w z<9(;xv#fMmbBFT&n3ik1=ukC&Osi$iR5NE`TK=kCJxTBD4z=UQw9@L=S=JUGHI(j_ zOvZGdRoiD<xtSj#BfIA|>Yf9+C}wQt`w&EJfi}vVW0mpq`Dp~WGKWcfTUBL_6|Vjp zB6=Irc+15hc8a%kb*4TKf4tg!(Qs42>1`j)E?Z5QW96oDMJGC&ce+1k3Su#}L%ll3 zvTSu6>Z3VUUX2jMd<~eO>jwUm_jTHUgL^ruBl`Nc;U0iX;On*)1+%*`E6kj0<@oC` zyf<$N7)3p=I?lCn%Tj;rA4lz^(|w6t90YsaJ;+lSKj608)$+MkdF)rU6Uo$PHJROX zb(g{SDDE&nM_!qA5W&3DoQv3*0eF}_&4pxY)y-b!VWgCKqNL0`tF&pW=TP+?u-coS ztN9ODmEBXAV7ghQibHLCz&dKH6R%dxw{~Ib*6%^9kF7MkAGDTuQ<0p12G6u$x4LVA zl?i*bsSB+1P$B{XjoA*Jcn+i<<mD)wu3lb%Y25<#;R35wdMT7b%roXuhDA=zhn!LH zm8!hZ%E!C7T^6F5MoNkoS{EG&9BA2$ssD@l-~A=^mRK|5|5x)mg?U}6lIzQ@`)wtk zJ!!q00kzS?qf@O28+dH$#=bN*b$bkrj5DGzO1?rk2fSK15B!{PS@28395cKoTowGb zFo%oVggHdyk}}ed7){~$NCMh`4+^&fe=ghsd|bFQ__T00Fqa5e&^y3agnNLm3F84{ zP<ct2fnYwq$wPthdP)b!XgH{wV*m#nrG%dZhlQU8$1FJ3fb+!vc`)tt821Hmb>VH` z0%7*)^@NXu+mq40ia4d?Oq!17U|RZ;TY>utvsQ)(vsQ)+bL2Hfm?N)Z;XA?8gnNN! z3$rF36z&Ip6s&gw8vw`S5-<q-q%eozYlO#wpBLtEZlf@VZLbSI3f?Ttn%gD34*aq3 zbKpb5FCl-u?*Px3PnfSIU_bbb@MqwQ!pFcr2wwp6PGnp@j`=7c{|eS-Az&M>djc9Y z{khmi%O7$kI9W65zdRhN5>OeODO?YnFWd@TNw^KThH!82ZNl6Ry`gY_u%3G&Gb;4; z+!I_3)^ktr6mWMvrGtYO8T}<PZ#`;JSkh(Sk;1(7#tFXxo-Di>97|^}c&_*#0523i z0@m|Tq{%z!De;e-fMcyVXm!6qm=+n-)aj~2)#?c<B9{j5p+CApc7OYX-QdH*e(;yV z0q}9*5cmhOD;oEgI3q_p7+IT$Ab^pn9HkH=J4zaFvu<<Pey^aWypKWcwTkK^935Yx zcga%&4q!#8`Yx-`_GeXf?=C&M-MkB<+ri4U8w*j()y&;+l~;#&cuZyQ!I0M--7TvB z9;`H7yIqalW0iH>OyijJsXfq~=c%20FiI^z7pKR&%Raymca%!{0G^wg;RaVT4<px3 z^nOGQfVb^rGqvCYt1OnaUZvFK@_1lIx4m7d%nz;q+V+-TcFa;^4!g@Q&Hgqs@&M1* zLTv{D{MmF396=IXJK_=sUe*|Z!#~4ZHYqMW=`hDU9ys6QA%R^PmY%o_jOb5A4}Ixr zI@zQh_E~VmPtaoa8Jt{Vg^3Lu>p{KMsl-68*->RrcP?qT8ZtKhlAdYa@cXc)%~frT zJq)wj(ECOXsdmqR34?|X7(2My;2{&M4H-AOux3F)?5IvvbGB6{9!jrRVcf7OL;8(3 z{zV+>A(!S1Pga{or$46#d~CH*r~9T?E2+QF+KE>vRSjRD7&~<>?h~klZNYXv5YBa! zLxX&7>C9hq&HXCdA1G%#5vN{0gvFS!8Uv@}0@_ko@7I;0cKQRBT6gF_R{hkrLl$17 zDU7cAU0z#aJ8boG4pF!U=Di*$m+%aC@}%WwL$fz-y-710Hv}%uD-inU;<P}4P}diD zusLdDR%x4oLBXw^yQu%ib$S5}<fs*_I}R5P;#^ydw`1+nNLauuS~1Nk?7nRt6h?OJ z;?lG1*fm%s9<!{wI<W{&`*kGhoQZ;BgRVai$#n<(<7;mPB8AfkjjwwO=w6HJusi3| ztiYpHv!3q}XnLsSu;GhXxD~N~7uPRccc@v%tnzuwQ4I-A8Npo(iP~KSvl+Q23T${9 zv)G>L>XTzuzOM(X+SU96Ms_Saj>X1vs4iE#XW)UxMeCt}-Cd^@YQ}RLQZ+n>k$1$C zgF2e-;Vxp+=xa>%EI^F=Js0qIiia!XlRa2mHzs*LL=MHCRp=TfdU~MZCU~a8f4rwN zYHOTlBr0mGCmnyscxdV{I%3$eAnWe?AyN(4Jw2(0_4I=96~nU|F^?Laa!|R|^qfKw z@;rkP71eMNmEal8$1>t9rpDFN8zD0s9$Mj;9=>g{)9~DZ^O=SBXlUo}S^ogUoU3?> zo_BI_a82-I;mNawjPG8eIG*h@fp*t^%76G8IJ$|K=VP+lwH1kb4n7a|x}Xa98jECn zrN{F%z4+S9TgbxJ7**iatF-~UuQvO4&v(qivlFtWhYxw1X9|iN=Q#==yN93Rba)!$ zG~+$jaGD98^^kFTUSlCW+%U%NxsB)O>5SU<VjnRC+x=s<aGyrc41^n=N~jUjLz@(v zhYN>s9_pLzo_X+h815o?+5Ic2d-Qmao#8o#q&Pu42Cq`o%%q!syEy=mjCwKr2_}V& zWHuSU*JP8iC(~HM@6(R-lzWQtzLsA*YA3T<`b(K}kx#qi%If}au(0|%vhb&wY^pnw z|D-^c&fsA30`&?6n$|=~{54E2FdR?jl7qj%WZ_RHe}t_4dNVKVwj5x2nw!re<U;aZ zrXzcK1)uRL&k3t^Jx-SVT})mjyBT~7>G`{xZ$ch>FIPrA`0q6JRWpOMPxSZHF6_Ph zyGQjqVU@4)HP35^_QlT1!<hMavj*a0XJvjy&_CJadVUzM%lw_7-Z+70&}jAL39B}` zI^Rhg+NmZdF=eo+drn%-Vfe7|q%|jX3@Xr@SeIrqNt1>RHWC}?yWQ1AwK-+w)=Gze zVl$R2!BqnnKe2^wafXw+F?*mM_eXLqLKOuXP{?q7WmBsWvG6NY0j@i464Nsfr9-bU zmr;`HJk2QVSdt2)W2ujTq=s|h<$O}zIAztpgWFmsb!ArZE>2C8dNOsVi(6MF^(MPq z=PA=iH~J*LOOw=(DSKV*a7B~)lLLm6rul(Vbz0(PK~MD1X)CvlA6%+S^eh)4xKuZN zNnGEfl%?)?UgvogX_V?gPS9zW>cteCI_*-u$zizEb);A0JCrGToD+56bWKIP<YK;6 z>vd6`l01cJ2V7UtyppG~eWtkjtM+HC4702ne#WYk|0m9_Q%dIms>}5<T0u%zN?|v3 zq!i__Yn<AB#;O)!lTW#`H4?AwViQTxl~U-klY29xdah3p8s!EqY7SHSpMrmps}YkM z#1m@fs)!R!8A5LEdJLzMGAb3ZTDdl(3@M{$!XIy)y@b-+&Hjzy=iwG;h9|Wp;+Y;h zE~(A430`rYeJCpWL-o*E*jO}240E)uOQZDLD3f{9T#e{yY+~k3jUC}OZ!+t&$|#X} zb1@J%_(?R}biG5BTW_6h?t);3j_B5j80mbq*?eB#K4y8u&FKG+M@GKi$YrPwXve&t zH>*;p73#oTuVZCA>%iV%R?XVkEYDXgk2xGNY3x|cuh^5M(Hh14iiOJ3nIEH+k^a0} zZTr?rZKVB1*yx$loY{}E@qBZdpdQToqWlAs7#(H4@@isog^J6~>92z4tg3^KGkl&7 z=b7`y%X^O{^4QE@A()|y<FT<k8IQ7(JT~_JIXZKn&OCn=1atT)QZvQI_LB1pD?eys z0y&e_bLXu38NKP1Eg2#I_b6V&_GeV&Cd%T|B6Xu>?V;+PxAJ;-!cA^YHkqS27MD6& zoXNVQjb4z+`hsN8z5s%}mKmQi=_%1#)|X|9j+-+Om(`rA6U%wdrrthpb+5rY-`r~Z z3_+t1xBOo`#jUywkHTF+pZ<1z`kUw;qZ(a+?&J~Gmj_?T^b6Lbwn!D+3+Ae5YxoHR z{Ag>4dayMxP&bC*JdvoskynS^(YvM@PKw2NH(F?2(06q~joZ%SZZLP5)scH6p5)3e zu;x}?mur`<hlu@lc<Ae~OIHTXVhTsF+3hjUL)f;sQw3Vfng@0AUmzq}7l(8f75b}> zFIn4?p2Pia!cY;lw-C}5@=I1+w$_^YX{?gXh-8$*e{*HM6s#@l{5P{ztV9hq9-{_c zu_}Z(DKbByXpR;gszueBD^|GB%d1ieyU-y7KMI*EmqH+VE|v7T@RdTNDPP$)7gEw} zf-lEju~L(Cehst?_f*IkQ<C<B6=zl(#yWh~Y_XU*_tNX{RGOG8yI^7#O}Uqj^#x+# z>b1XW-7$O*&**1e6mu%%qOIy@Ef;N7KSyu#ydqw^zfE%)rF0el9Sv!b#f;nAcpA-h zhI6qz9?h`5ZZ3RMm!F~hKcb!Boy{Mu^<Ad2knTA1MTkc8bjRr%OQ-CP)3<kv<Gf9C zsF_F42V9v3eO0s}=4tUUxZxXoi6ER$`Jb$2$<MK2&tg~XKn_^#|J9}<Kf!RMzk2y6 zD^z+R!d;J>$8c!91mXVW`c&IobE|KDvQldw!C9E&mm!;I{8rSom=Vg0$0&ABGyd^t zTSZm+8Jgh3ZZ+U%=!*xaX+Ps(K1)6GvsJMww^~i?vlvTrVcw8o-d#r9WoRg#9DR#E z&mcXBZ2OE?{qeI^ChtAuV0l(Tuu}?7!ef~iV?tr}YDR~3ajL;Jt1!fm)u&A2*%p?T z9E=WLwcr{|UeeTtYgRSeAxFv4Yu2BEgz2b7n^AmgKfQ$P|N9&-`|;$We<60Ny|cQy zy4d0Vzsr_nCxmzFx4?YrzD>y$OQt7<n|uDXu2X;N_UrU;#}<(}yfC;q`CG@U##VwK zUv-QbqEtX_#|%;WlF?H6n?Oc;=C1(PBKFGHDl)nt{<wK=?DMu%rBVM^8~$38M$IN2 zT9t-?+rV0t2CfIzsx)u|uvVpk(KSU?Y2YSctx5xT0B@HJI)Qf!cL5(1?gsus_)hTY zm}avN99n&bg!+TE`V2e_tkq}Wv0$w}15+=c)o0*IV68p_-w)R6Gw@6>8y?U20dQ$y zJ_WLbpMhrW)~0pqz?CK7c`)aWjJyF{D9nc2NVo*tOqj#HHo`~1oJBJ32{311<V)bY zgnt7M1nV93{)A(w1W*|`N;nHVUN{##MVK0u8N$`T^Mnh*4++-?FA;7AUM}1c{IqZ< ze(G?YIJm+7i^4s@oOrR+gTZeL)7pNU@L2F}VJZwi7M=<|Bs>fJh45T3mwuS$eDE2~ zsDGO0UzC7H!CLnQp_SlY#Q$lqR=vT0HCU_Oz%*pmZ)brwg7w>3;CH~uxSN<6m5sD* zCR5p%DV&Igm`__+2BgAKNjMu^Lzok%+k|U^8w%F}Ya0;6Z2;!p(oCl@xTA1uFinQ( z-ww<LLUJeY0O3e)IPMY00PslRp<pghG6HYO$-?Wvu|o6qoGbn>fgcin1H43d8<@+p zOlL26r7-uDd_^0ppo8F0<V^;E*$42&d@}ohox<z`J`iRfuwS?__*3DQ;G@Fq4^9g6 zUOy+?3w&9)589vclQ>2p;CJCM;G4n|!FoqM6lf0EjWc24=79skOTZyv1x^=U0nQQT zlc>D#DsWXYKj6oEy|x6r1g6zDGk6(XBwPY+A^Z-wo$wBD7vcB8RQE9M9xzw8$$P<r zh4+EE;VJzOfFpbffR4j(Ocdr~!c^gJz_Wx;f#(Zf25Y+##HGHI!zrfY0(0(6P6Tr` zo}2<+FI*b@a+D(mJDE2mpaOWia8>X}!hCh-h;Rq6wktuRcY!a6KNl8gjLXcZ2mYIk z2Rp8!L4$5G#{Py!n2O{iy`vriEI2F)$N*;uXM(eZbHKI9-e{urgb_WuyB_@g;1=SK zQM=JjxD=T7{fvu2QS@aia0c3+F^mE7Nag1FF`h|Aisd0QU$_dG7TWaZUGunbA^1sQ z-Zg848-kw~ZUx>b+!p*gIKqUw!|{#;^Z@S=rapX+@KEqRVLtJwlVn^z@xBzE4gN-W z9{8;AgW&Ik9|P-`rx14?@{jJQ2ggeY&^zjZUj@e{L^Id|b_wqU2ZZ;4E#ZCO4B<oI zJmIgv6@`z3^@~(UpN+aP{rRa|Tn2;t`|{l&4qDm^r-1oh1^r8dsR|;egZm3-gYOnD z3mz$40X$x~Dws>^j7yV}8N!Xh^Yp7=2xtn&!xGQ|yi~XoSPAno={KoRO1A1v^atZ$ zyd{h=udzj#C-$B&TmD{Qp5#Gcerh$kiynO0+K)>BTl*Q|O5lsaJewbcc{aZa7l8j1 zZU8oL8?tasfXQUs0yr478i;YG-cb($yoK^5fCZ`~j5(4~LzuVCZNj_+dKW#!Wucpj zKQD*gMGyYvz<L)waCLBZkzt|rCVKEM-~|~V0d*0echN%t&tR<hHv@B<XO_AJcv?y8 zQQ=%SwqF}LDO_xOySF+wDck}2#yXS3{J!Me$?)CMN8OwZ-)^e?lrX+m*-t$^MGJjD zCH#Z!_x|de`@<b<TL!7BQ^OOn2=nYz#C57)aIjr|ShbiIu86r0-UQ3FU0$S?O$(QG zOhTassGaoss;xFS`*T`2V7t^-`KKc|w;j5nrHwDAsP@yti7GHTXjlEGhw~hR5P(lv z;>$1mhNU@PZJZu1=Uar9wF9k)9Y<xopIRrhud3=$jw9ExdNsN(ZKBp768^83zpyM< zGfNFvXV=Se9^TEcEaB{2^-Bz--7_5g&mzxsxUg!&RS_)m=tVjwx@EYW3DbD6JJ_{j z1#U(3Fr1#IvnE{sy#mLj4lLjl@nG7zMi<~({=Zy+YxHktPqCG^V}U{UjU7^L*yxD` z)rO54GQOZ{$;rOy%}lk(9Y`v9cux3Ho9$2g(nl^&gc0HYT#H+)*Wx~kuEiafwK$kJ zaxLyGE=y3a#RZ~kal7XK$3;*b?!req3+omZs+lDT<x8?33~#qbw5p|fT=aEZ-YT)* ze{X8XaV(bNXb|+zRhp<P)yY+QTqWKsSSMYo4+$JW<0`#Jmpy?!khT$Qiv(_cEEIE( z2wY1Lm@pTA;_Xl2uhTXYLbAu*JYoW$8#cYj8Z#Pv7(TeHeGu%bfIl!AJO?lLY5cL* z=EMgvenuJWb@u~ZOaVrNA^2z+M+2haHfyRAkA&0nFrzRWO@D-!Zw>xnM?3oXt5e8- z7JuXYgH`6E;rzm0s4LhNJ_bKGd+Yetlr-E_`^C3?8i)<;K4w6>`{0E}my7Zx4Odei z4VP`m@|i7{!>2hV%h1`H#T`Q@cO;2AchcGTR_IAO-%=+Y4W|WeB2}|pBls}k&_~L> zC_F5!0L3!D;iw=B|7l)euKW~!$)^qV$f9ti20F2m%!+f)l(#6Mo%wWfJv-_g3?~** z%u{bbbScALH`FhS!ujZI(iVp^0$j{8zhh1xp}nO%sah=#4^JD$1U{iJdOSTWGFKKN zocVvUI6SJ_On4_$ngp+?A}8M73Y@Lqma6;cE$;+YY|dwf8onf4CiEg4&LJ%HUPxpS zjNHL$)sk?!`B2H0CE?<P1a6RLGm>cGm7Z7dZ<fKaF^+ur@%oA|EC@ZT!w3HDO<Zzx zb@)f8S*v8<hH#Hiqzq46_e{7Hs4NptGX8?_i)lnSIOQyckJW0zeE8H6&IWVVOPO47 zW8r)-XT9|2L#e%R1u!SQ@Q>*4-m@R2Pz?n16Rr&&BFqOA`&Y{F0X0Ur8<;a-`u7A+ z6YdS>A~gN`fFBX=4}M&D7<je*(j$Z>!125U6oWaVWn^~Me2<sRrm<OgCV0E>Z18U3 zx!{k59{?W`eh~bH@I&CQg_khVGvasxd{KBM_y=J&nqP!p2Hz0g1UAu@S-9803BqrJ zeZqUe$-<w3IoqcE7vM~=)`A>`BVPiJgDVMt1Fj)_5zHHhk$(U;6#fa^RQMX0Q*X-r z2JR?qpupXQ<G`GGQ^r9p$N+I9AmAQhA9$oNr&8mDIhCS5m66%~%@$4vKPa3Dj;Y(S z!J=-{W?V6C8yn>sEsy$d2S-fZ))Bl>66y?oTeurIreb3Qjj7lMf@3PSyTM<I{Jr3B zgeQZ~3Qq-J5uOYFJt7Xa(3`>>5!i7n@+@he;}(7f>=%9s%+)TMUuB`H%L(U$s|fR! zt0i0qthHy5=iS5yCgVox!x6JMD*|_yfY#vN!kxhbgn66AjL(LGW5#Fqg2#!>2yo2! zY!o<Vd^Q?9S7gS5VVr;saZn20W?Xe3&jBmpW#E`4+H&w(@m~Rs8KUut8#6>(3w~2% zo&&!t{33X#@E-67!UuR$?-vJe4?b{M2;K!>37-O=5WWunR`>?^lJH;PABE#_X}Ge@ zbX?%Sgp<H=cnHv+dH}v?Uy8G!95}c_$^dq?L18|-(}X!L%ob)>%T;2^HwD)eZVT3L zO2Pk5a7*#;18y(OM%q<)6gbjT9OK~_EIbiBTzEQoqVNpx4B>~s3x)Z_TP(~5tAw8g z>-~vPAU4<y;{PUCzXZh%F=zn1O#=3U`JCjL?E@bWJ^<F*E%+Y;bDT(-@4!C@e-Hju z_$rtN9hCVUthX2f<1riEVhGIM(&y+J6>`Cmh1-oP6h8jB??H_9+fMN0RIR4?`@x06 z0dOPXQs5>f!#)Um9eBb{+!rom!!Fg2e-bW+IhyYPW;)ANp9A4lwj*WL%>$Sg?NaRz zV$$?`WwqxZoaI&U5QL_xA&0`1%$92LA<TKM6{xokVV*Mulfr@O6upk8>S<8=VN8Rr zq^hci5nL8i^|1b4<p_9V2kU8v!{r=};OmUqGj5^xP_-Z4zE&8x72%}wQQ$N^37VgU zo0DU2$LJ>L9o5b?_GER}r~iz<YpF*zr{DvYHEQZvkok^k^j>_Z<lv{_=1K8KQKN3V zO8YjP+x-k`-o~wfY)jdT{4?Bs1Q}wE!;M)m+<uS;r(*^^oeA&rGT9yM-!R;+6EDMU zZrqM2%baTadS_6r|27<|#4m)&D>+XitGI;O$i-HRzRq#LIJ=!Mq+@j5SzY`#oRQZH zF1!Bzq=(8Ld;I)L$juu88{X3hG`&ky#dF~@*kHKzISi)rn0-?Ud0xdIdqM$cVcx|M z#hwT_vv_Z9_29X1eq=Qy!wJnlL9lx+f)iR((s1*Ml+bo95QFIegc90qfEQ<QIBo2| zT!#-wFV+5rcP~yd;vI+R)4kkac$&8fc&axAqW627;O`Xgr|_BV<#TG1mm20`Zzn{p zFwuJ-f+u*nx-s6%3H>;4Py8M0t&0d_yxh$eFX>c^S9hEbXZyJ4uWS2E#I(DIs5$4u zx#nAH{rPak`ZO-XwixGFDn6?XZ!;uA6Rpc|B~yi`x5XHXyi?{N9NS`0*hpEed>6v) z%J+c+2Af}SF0mtpJI-M93kn}hVK)JLOZEy!Qj*oo3*l6=s(KO!e+Y%d<`*=Xx{%^f z?_CI&5A<L{UChlaq#0`FP=8zqm#+L4C3~8zQM`7uiAnZ0KS#WOcEMm6Uc0&CQbiZT zrOkU(?~CDdn<GI@zKHW&s-C(Su5A{p!#LO)#VhA`@a?NAe;59!^@BWnPaQYT(#;OT zQ?Lt(p;fU*@ihDq!LCWD$`nuQ6_nY4(s=ac#cN*V_RQRLk5;!|3g_0K(SfHYy_{4_ z!90-ca#Pdq>BBQ~>rH|^{g|WIeOWEN6wVKG%<XN!3|wUpue`TYGV*k{Q3o%DEpwr| zfV9oa%6mB+Zp$sGy;GSizQ`B{o=(PVKeVQ?c^CI#OfFV?mqvw-Qs{9J;<l<b@48u9 zNZp47ea|AE-TU_TsMlkc!?~rOV0m^hN}S=Uj`&XRr_^-07pg-D_veDW$5>N#!}X!E zeIL#(%TIy%#`VEpr~44OcqsmQ-F&gfH-)DjaK|}R+wa5WZ@(9QcK=lFW$vwov<z<^ z(DWWav2CzxWWtHHUSjZ8)STgMgQ_;Y)O%wi;q~gZ@55D7KZ7e!#6pJMTOk@~LQZvW zQP;l@S2Me)3Rl9B0C$x!@8H#(jnHyk)Z16W`E9!+F1Bmo)+H(Mo`5TFu6zeITZ!$R zA!y;>!ncx+pJp<FB=}XPBG=5&F*y>h{G=-XLpU?(HI_e9f6ne*dhbv@eh6o@<vUDf zwr;%DP>q$>;$+3$gYMD{&(Yz<baPZ-=4$sExGQjOeKZMwD!#6E{1Cn^=@nMQ-zKZJ zBZ^eHi*jBK-(G>c+nG)qYwTVmS#2G{%oVmdNTb@fD35uky&L_%Q=_kj%fnFZiL2o} zycN3bYPc&7rG5+-nnz38{uutnL_2HzbGTu)u88G!Rs_H7P+8}^!p@xUgS+5<wd&_^ zcXOZm<>&Bih*afTxM7lxG($%kkJ_x<NZo%e+{x^!_FdCL_FuvcYiOZF2UEU@XKOU& zfP*QQ$4s+;3wLIcqd%%YZt)ut<TUn|a1&dOL%sD&xJ7mjt6;jL7pi4D#49J#9dYbJ zEghk|tjhQ`{7g2#YvG&0R@>lX{3+Fn`LQljc`c0w)78me!zm#y&?NWQeGZ=C(T@{0 z+^F2Yg{zw<RQ=z=cejj3%_Y`n-M&SU50FkO6Ekk-UPHmP`~HXT4akSupZ*`dXG<>p z7JfO&_L^5cn&8b){r9K+8$*i!u@&wNcj}eIe?8+LRXVjKPW|+xRk~z#nbgajBb=7T zCjEK~anuZdT<VNX`uUo3>}9VzaS^pKIAkW_TE)yG4v|sW{I$X{W*%`I>2vnN8b19W zOoMIsM+~HQ>t!s)za~Od*8d@lisOB*6XM+&FPshb3Ug5?_AXX)aO_>I?%>$FSiQhG zB7YaSjy8S38K=Whp8;Sd+E_Rb+)}tKxV><BFpa(`Um4t2xH@=<a82-VVJ-|z5N-z6 zb3Mdu%}M`U31|miDBKaeShzn}2@e84B|HSYR(J$>gYXnESD#t9d0=)w<oVz|!jFIt zf%QvWE8#dM0dIp(32z0T7v2H>QTRRZ4dFdt2RapI@FCbEOig8y@KG=yOq5|yo*{e! z`5UxXV!$Z`#HOnkz_*D%H3<!cuY+3&+t4;*vsF7dHe2<A`-@B#I5tBq3mz-}Rl(6& zDeAufj@Y!6ll}!F)CC-yiE`4f#J?B#8R603*zA*2r8mT%ll$0=a}HR)28EM+5FDFi zJ_`Ocma&2(Hp_egd{z>o_9-^Ad<7hvS-u9oAu{iPwJioR*a}X-y~Y~lNL1TmfDeL` z#s4r^+hV{!as&=-i~+}2;EE!|Ih3})fIoH5vDxHxu(r8?zlk=`TI8ug;>M!Pn75d= zvjFFT?-u`ZU~O6f|7zed+VlaAA~@zy$Qgb5E)Y(`^<E^L1zsjx9;|IBAYTcrXO>|0 z0epp@=~M&joo~Us74<9=OfAQDk!i?D{~mD^Az+_yH}GNMKHx8f`+>g^9thU6Pb4}V z{GIqyJ%3erE|?D&7U&`HpTfNTZ0HrW>BAy8xFSTMC1AY=2lz2?iuhCgq4(f`{~B;? zhPnY9o1wl4j?GXvf@3q(P2kuJ^>uJ;hWaKrqW9xKqTAqTBbj{w*86e5e=qnB@!to& zOZY4BK;bjsp~ByS`JNI_<~#6o;qSq7gl~c$iE>2mQu3Gtq@Z!F5H1g1C)@-qwh~5j zaLiPq75E*I=?mT_JO!-x<G>T2m*WfigQtVJAsu-J_>A5K7mkH+T$F%^!L;wD5HHOy z!dwiZwLSfJfX(<Qe+W(xW>1$Sd>X9HDIotXSesLTF)}xDMJ6i(2Q3SkDDQP`TLGqi zwUPMO1veLN2JR%>0^D1eR=q=nJA;P{cLPrp?gO47JPf=5tam|Q0Ef1rK*n6oStUYG zf;R|14SqwI`qFK}G<n)9Oe;kFVL_xr73tUFzY~03_<gW8eSi#9r(*g52M19$^aZR5 z>QTMI--9{#p+6r$sltDOGlhNV3G;<ZfvXGixpA9tQ!wYxOs567oo3wse4ub9&VVl9 zzQWzWLxgEPI9!+y7rj?3<Y_QiEdC?GoJBDmnj}-HL7ooQd&Pn|{C-mW7lNPT@SZ|^ zpllT02!367GkCM`7BJ^zl-~~CElhQ$9?-)7eefai-wpmkm}<_ih4}!|Rt=Dk9DqZc zHNbHgtj!w0KY{ta0W-S>z9IY@I3D*l{r?90gdOPFw21@!Jz#C(0OkV-CJtIY0M-@` z@J|85!U0NOI6`n}69;e}SerP2YlF3k1DHmC+Qb1|1lA@F;AY^il0ge_FX1-e{=%KW zcMEp`j}Y!|$Mr83M;`>xu$cuK1fC;247@;?s?bHkczQ)Y6bSk8VEv&$@I)}bSHpDp zD${!5r@$`@uLJXQRi(Hk<Lhv|BLQ2$JB0a^+9UiP_@MAE@aMvO%aNAt%<N<EY2p3g zi^5c${vgbU+AqR<s6}pwgF01?@tM%qV6QM=XydC+^uGk=TSVj^!TdN2`5HK1_&S&q zE&AU8>kkNm4fLG)1A<^~XQRI#=)(2q6RxR5pv539&>5M#OmUh?E)Uip5Cm5Q>kkNm ztAhuK3@5z&N*CoDfT<cJb8GiW!cD-ear$$nHkbRf(ZMI#LJ1fFrh1S5e0nM2`QT@S z9|lwLLz$IePKC+bP3TSG7r^{R5&d5Q^QBAjYv2!r-;ThsUmUx@)a_B|Bk)(kUxH5v z{|f$A_$K(0unpbokHTIszZt}IN`e0pP6x+fx<&sSunVmF|H^RiYeo#H4h{;}0%r*~ z1eX(T4Xz?gB|<G>K8)%L_W|E7+z;GbnEJ4`!m#s;7<^ld8BapMKr;Skp}h<ht^wwI z67(+uPZn+po*~>C%=b$vGZDO4cn<hU;RWDlg*iIn7x+rKas9Wz@s<Q^2X7JH3Fhk) zOq9>{4~36|KM_6wJ|cV?d{p>b@JV4Bgr5`UdJR7`$26OPf8tjV=-^7?@4^GYH-(3Q z?VhL%M>THY8Q_5MNpMJ*Q|xqMPD*ox2Y~si6!RJc=6iGG$lY+%6$j0on+lHtw-<gG z+(URJxUcXk@DO2+2}THW@;O?VFCxz-<3G9@<3Zsd7%#q||A$8|94jOsAG}7m9Qb+R z+rY00w*+q%ZV%or+!wrC_&)Gn;W6OjWN)+(r-d_+zi~kv6(Mv*xH9;fa2@a;!Yl-B zADGZ<z<6N}rTHcn{W*i?k^ecW4h!!9mk|!)GUbsY_!EYMuWK?wLvVFrPDTraxdPol zcqq6?_+D^VvM;J)=_!nZ(NCBwR6~TRJsB=s8XOrTjyyPuh0B7c30DBm7Oo0@P`DQO zQQ<=H<HDR?Jt^D>yhgY&_<7-G;Ehp^H+b*9TJrs@)JJ{z;_9?TsU6KMwI2uD<$kKn z;?xedF9)bmJRTgOw&93%E8h}G6{$Wvysb9kV7qpoy14{_JyiRpsl_<#UJBnYSEwsJ z6GE!;W2uE$b{q0oY9*|4EPgCC7t3vLK9*X}@kSG9X4EP8*ebM-uB1Jl8gSG{vx@Fu z*No0_a27=u)ZoMy3a34exUa)^esrh$E%aWb_QTuP;0`>)F*IV&m7^Eb{_Ke%V00I| zFq+3~)wy$eit4j0HOVPE*VWP%ZI0@-3kqthE6<tbN;WS`tyZ>YQ7Jr@U&R$14L#)| zT<qA-mIJ!AyF^#q$}nlG0HJ@@*h)|aESPbWhBda_L>!!s7jP3|jqO3zcx!6Nbq$>^ zM0VQsHg}QDh%d%!4T$#U%!GZ^|LN{Mz^f|OzV9_VdndcBgcTA(HfskG5<(zA=)L#e zi-<r_5K&aBNZk|>#70pDHA=NNP%(;tG^JPoMMVJxfddu<yV&^t|Jio{pL3q`dEV=J zujl%{eL>c5`mE_|=AIc@WUKE0V|TN<h?GdPHATEG9)ZW62kUJd8w5C01!*<~^I#ah zc<b&k@%L~ewJgK2r;}y4EPD@1g=KTRq3n$?@K}Mf(1NrZ7n6cvU1oDQuhK9CEo*Z3 z(j!@u<1~Y1PsHDN8{2>v{3AUlIu@RkEXqBOA#BN_9KR?NO0H~OhuVE{QEoBZUtE;? z9M#IQe?gi>?Slw)h8>1o)(tMoJ%-ntYIjHaPO<mk^(Nc*;qR?>0aA66T?kvzTWsF0 zKGE(9g9-L(B;R=Z0+M!|y$63$`4E3B%6$Z1{X_P`*JN*C;2ijCzYM$ISauN{eq!1C zP!4L_RiT$-{{)vvnrjiaz?dsx7j724KsTSmWTwx~#fvJNb5l*XTJ|!$&}^JN!BeyY zPjKNiZ~|IRU_({JJeUBV0~?7}kW05EXX`Hy=`F8^(<*UKTR`q?<ya~ZyR+3?*&6s{ z8Jr~rJLunD50{H3z}T`^;JuZ7C!=Vm!}B<sb=_<Ki12;(C(wzvZ^4Ts*l)s)-~IxT z3E1x<b%XX3h(^f%25)9tA&T{QLu0w`$$lTD7a3u^eizx{v5OI}IQs|;y>@jt@L8Qg zKSR$OD%wvMuOT=jAH3zt<wwv;NrQ0&o7>f3L^PEz9!gNOY^AcCglxqrGjD1wePl~G zeH2SxsI<BZ8Q3*-6aI$Es3JU`Nu2~Ip>k${b8YG!2qILn+R5`>LYXFjeX0BLW}#d) z8-5>1U5s!-`HH(U4yK+!<U+MnF%*YW@6$uJhQsYPBlAM-)H4X-bn0OGQ*!!$geG0h zQj(?0-Z){R73yJB9+k%JhoRm^g(cDgy>V;Ub(l|~iw6_#PSU5ghVwjIgF1OzxLmS} z#1Bn2cg&*e@q8TAO}C*zyjd4+3)fYR^!<D^)O)stb3B_8^|@`~wpgUCw>`Y5&xc47 zyZ;WnzRR0x?EwbkSoW?kn2*G;2NJD7ZzOj$yTe30f@=^>yJI1e*9tNl>`qMg)ZjOc z4(|wOHs6E%wfnL(RSNQ($G-9yT;y4Se1urj9{d75;WVE;B<2av;<tyAQ-h`Sq#fa$ z&UZ765toH=Z7d9~7uzElCmb>O8Is1fuTMo7!RHz14MZzwERCimZ?J_v3ID29hq1Ex zLF2LS0ms=7BT%nB0PpCt0_#vSoy2;>=~GzOdn25k8;@*F>`hOsU?GeX`#xtpY=aa} zl-psqCg~Y(gwvv5AcqqN(KQb~gv0ctdc3tg$fhZ&K9d4Tg`koekX7&q>?Ad$ho0a` zc$m~E7TX&UwWP-M$ZrL9!-w>w4p(3F$XuHs9(B6Rqh_6BKC!4InTF6C^R+A8`hv#S zZZTgI>24gflWu0{R^SHR^UZMCTob#Ymw8%vS?q?H*ja&yz8iL<#_p|`*_|A-`)3lo zokD%2JL58y><ex{z9&tio%kS2UD9;==MQ$~o6jJl?c~&4UecZ1xgATkyXaWn_U_99 zyQkV^F}wG&bX#cNF!%<2T_l;&N%z=^`ViLRcZO^BZ;L!nDyCnaSOi}o#|3|+lUHM2 zUCAui5R2fC<ky&pb})`Fw~_Ws1z9?iHZcg?EL=~YM-ZNqjxN6|oE_zNtg@%zH9d9? zUM9}SczEsaP_a(nZe>)Jla}qk=L?q2<057%n<qTaQuh038)hrJDa__5`zQjuP1&y? zl)1{j29Mj7JrW_$Q#Kb_=PR362H&CV6hulZyBQwK^p;&=$KkMWx3YV}`~rjrD(R!U z!eu)%-%6Qejg`PscgIrFM(bJX9`pKEAfENYsdoi@F#Wt!p9XlFw-Kh(tOfJ~$-33< zaFa^wsndsk#0UB5@5o)u>&bGm=sdl0cerd4Ylu@wPmy9(^_#oH*|n#@dGh#9F!2ZL zBWlT$`hx9XZKPWA6ng6fxm!1R8k_Re;PyD}?g>W*a*{t&70!oc_Z#G#8pcB7uq{<r z^C$+F`J=8`1zjs+8d6iuk6#T|U&2ZG&NQ4Ke+-c<&*lrvwxz<FpkBBqT-9^Xt2gcm zSB!oLO?8`}ajL-R<LFV-9%Y?|zv?%is*N~TghcvpK6-9tUtmZ}R3Wr;jK@ppZw`;Q zQAS#$QZ8(-F_x{2?)0)$0#)icI4M6Rrcn~FiZnG5GZ*tF8=Doly;7Bq@mw8!E1Z#I z-2HIb`}|<uClg`)WM12<+)ZzJD;!px^(SwI%SYR>gqDjptKtZ~9b-_`7m?31NmI^v zH5R&6;6=pPdm1XM>N39IX>TTY9&$t#twieQnO8mSWmG?hN#4iIlG9$kM<Q(Hu_b_- zHK!5O`JR0tJ^Af$wTff;!e@-d6*R~~DyVOano@%Ke+2Z-x5L{}dGCBD98Naj)bTN# z?`Ry+>)#1ikNMKj$Kd9nid7jg4mXE1@=*@!QT(Sb-gm=~M>jL_%T45G!MQ5BfKnfe z{Bjfd^ROL@{BjeACI~1N`Q;|^7<XCu{LoV?y>z=8>MFQ1dX<+0u9s<Q-e|RPeSm7t z)~Ge!=kV%}SKS--;7Y9g{o#6^KNI!U`@?J6UcsbV>{UJR1zr9u%gJIdyRh;m%@&(r ztqjUSsP3_nGKV%z@$Q}wD=E73d-zT<TGy6n&3G?dQKjjX?}f`0PGu2)jdmNG?A^pd z-1u5%%4XK=#wYnoF<iqmdYw7Nl4?YR8uKoy7*=Y0mN|4V)*i%rS-+aJ*J<yE>!@nF z^ZViIjlGQO^KpLoQ&0`zgpj5q%OWNA@#XRr3(P?{%dd?vR5kTD)Ma7R{6@X*{cw@W z(cKS(D<reSQqL>KG;YztXnrL<<3M<Q*3T?3)jaJoVjueXg{;ZdJzb#Y$9sOI;=Uh* z{mS!Uq8{>Lct|p3rqnu5FPJC8$Ncj8oe#sc)zqaQh0~Kw3Vi6{%M{Y^?&2yRg+EiC zXB-{;I9xuN-H56d7mLH1C}P;?<M8C#x3Kchi5m<*IYQ5mwGwe`B`g$*e4Z7o=El+6 zicmLy!_g-`4qxS2pQu}ZVsd4~C*e7sHKp{IpM-x*Hd(UI)VLY=p3hIy=MIHC)HK?+ zOLj5?ZZ}N<>-3$m%I{^a-Ic&fY-P;VBM*mbl@Bvh3*-5zuFh6KK{4JGO4FcUJ{+#B z=IT!mhx7ByVNL-*ty*pCdEsEUpH-$O)EtMaqAM!0dgxk5!Wpqx?)I|~Ekgm!d#HHm zk?<*%Zw{>a&d>6V*EaV-sG{w3XhQzZxcE8Ucr^C2aDjS2uly`r1`Sd1XW<O&BKzR8 zaK*Ce48Caq){MlsDw>vUTqGTZ9a~pB8m``;AIs0M0P@6|i~p*qTn_CpX@&*ZB#gui zNS<kGhXq!{#!9NQ^}?g!3hH*f_Gox;X=8huv3(y`qdQF06^?~#m;Ri-3}&gP@B{R3 z)7Kme7o<<d>z2-c69L8a<GoA4ogUUt9Sc`((}iWU+lh;&i5wf3sf2;S&G5r(b?obf zh3-D+#GEH`+*|)L3yXB>=i$sK_j0SA9WL7I$RU#Iv*TiXI&z$(`d-rLya=T&dFE-@ z>%!(D;3zgh>){287XC0p!u*P~x;BMdPNTj@L&9a(cX#U!AM}f#hbwtr^y*JO57#Pt zEsA%bqB(oJZ7wXEZ^`bhbj9Q0n(7AK=Xkg!j+NB+9}j1zaXF}r877{iRR(JHxLv<{ zJY3H6RkHr_c({CO6TDm?OEs%p;#aqo0UbFJPWK!O6xTlyPRLH^kBs+N`~S0jQa9)$ zjgzv9^ZezSyO-S^{*UZ(4<`O?0V<pt^SSG(TdR0@w{q7lihjy&!N<2ikB`JF*)vs0 zMoZ2gB~VI4qpo8HqebMe8{8?DPW(7euQ(>dZ#o%OhQGsPG=}_f{Z55roWmx=<@6<f zPcg62xbQa&o+#8~{_Z1Z0`U8uoE78YY2cg~KT1YE^H&!EsoWT^BO?d+Ymd}cc`^P1 zFI*zeb+%;B6kh7$wj}e?czaqxQLz$)(ePc|iqsHXvK6T{xUAS|2R7$p<4x&jP3jAq z^RdD7zm@3Qe19%|(-H&dF3ed-E`3v<o?ao`0c>Ql;7cZWEcL<J;7P(vfa$_D!K@v$ z!|uoIECSa9-wS=Se9{04v$Y5Y9l=~Sr-LqFPK%SffgcyX25fc~L7(;hMbRG%<`O#X zPXcoZojeVUrE<f3;kSfmBmCF_*|0Ph1|NyReDD$BJHf|=?*@M%d@uN{@DcEj!k>YS zY#01I3Ffy4BXJs>Ap8xOOYY{Hqi>-|5rdz>Vc{eclnTP-z?FpSg7bwNfNKdi1~(Aq z_7$$(GvMyvHo}|)>?GU|+#@Oq?rSjuU~s@qR)a*JGp0j@mx0HTQ7SVL(OZS9gSkde zedagU=*e}!3xt{93x!#DmkLMO85W766?m0!8!#uc=uvy{bHbg#FA1}JY!L1a=A1F@ z_W~P%F>oKSIX4^J56mTc+PMOJ(CnFl;z}q!6@$TGBRmHEVc;)Ce>nJ@@D%V*!Yo|B z3sd08gL=mR9tQh`mxGgp9|flhKgIT^oG4y^L8kC#aIWwUa5dpK!L^0o0yh+X7u;O< z1h}p6mtd~rGeUl3AJ_58lnv@n=JH8RD6SHNdf-A~7OwGRG`E@Xh!U-2=Jy<7=JDOa z^}$Po8-X7XZV6s4%&dG=m{}QpS`@vZSSQ>UTr4~Qyh->b@OI&e;N8Nk>t=fsA~zlU zf#}Z$9}->wJ|?^rd@9CK>pLjUh`|rw?}dK?bLxt3{2Ta!@Sk9xFQ(54){w9ZP8Oy_ zWLaU(?Pmx#2XiT&ezpe}81X46D2G)~3|L=z)+;TI2DcLCW*B}&Qhzbn9MXf1%Z~^R zp*|S@Vu$nqN`tQ#eT;I=MZL7c4)7Myci9|H6GbMNQ?0a=1Lk@?neDleHUqOB-zWO) zBaE;a^jQ^Gh(4>|W5Ue7XM{(Axpq%KM}uDhN2y?*8Oby7{a~)+Q-2wls~coir+vb# zPTa0S{Wajj!Y_e87k(LhT6j138{xg+AB2yw{r^=IXJKH)$2?`;Q$(EsoCgPme+Orf zF&1Ew8Ywhzd9V>e16Kxf{epH{g1P;Q+#1Y*8JX3)m0_g+Rwz1%!FF&r;Wxp3gm-}l z3j2`v6bPV4{MI*8YhVX#q}IUfFUE?UieOH1(>`T*%^^T#V&&!@?%OI2MLGhwPnd7R zjWg6|JzgQ)4E&gIJ1{5OX@~Xr1>rv6SA_e4jg%Ygu({nK`h&oGgrkF@*e8mi-~+<f zgN?{r*;uJQLw#@r`rivPqCAY9`kCMh!ZpA_3|y#R51cIA99&kI1-7EOL>!j-LQzEw z7@-1TMxwDW2N$h`+5Vfue&BW<xVPxv2j-4E2K*p+s4xqxk%WW(TCkCX1HZ`j--yCN z!91QM4&DY&7k&>sNBASK5sQO;4k$Q@&%nL{-!II<YeeLr&jPzr^tp)0^NMMoWyna# z@e=nC6h=f2%tB;D<iIRAMnn!=32a2<z%{@|L=Mcs$OqynTe{O^v@mRxz7b9a{~(+O z{#BUS7o|-)V1pAcoCmgrYl0~XOFPWVbYT|2h;T<R4~8%8LTChBPxv^viSS8qE8!o& zJe?Z$qvj5iZenmA21XPP9{mR9?mv3US(Tx}oK71d{1W&E;bJhShG~BT*hs~JDNsIJ z^tXVyLyLBHfwdp`PsIT!R*Jz#VD5~e{wLsK;nU!)!soy{g(+PAjxdGG-xrR@fb?VG zQs5K9Wx!tvyHO~<6-9OM&%!Ohe+ah*#|2^$>I@DD4+L|k5F<JqTt;|2*cIj_09nG6 zfUPXdtrnDQi_-BcP&5&P&EQtTd%zupDbd<Z_#n8C@G0;>VLygpLxszNM+is2Hwbe? zJytl2<G)Fw$c4dl;TqsM!W>fHA>0<s1#?FFb@2Vd+rSSAzX4t;ybJt{@E&lnFbAPq z4I}?K^YfM%90h+Ud>njC_*<}%R71e$!A4RI%z>woR0DJ1X(ZLa31B0s22KG}QjL+O zoTw301LuIt81X46IM~b-OL<@;sRsR;U?Zsp=8RQCvC{}_q|>0^1l(ElJAiu$cLNU+ z9t}3aX|O*LJWBMV97u9s8)J6|c&hNdU?Y(R{iWc$MV~^TON3tnKOnpXyj*w}*hs3u z?Z@D!MgJ(6i;fKIB)B+;{HNj@C^m_~&*1IC9NY1h0@~r&Zm)1E_yb{zSsoJ32Okq| z06rzmQ)$i!w+DYO+>ztI^P=Ev#s%RXU|%Q}FvoczVXm?#3v&#|X<SBb3OGafE^uYx z2f($2p9S+K5Zb3WWixUVir1hpQfuJtU?a5#ej7YM9J~h}EX)l6!-bE7c|1Hl<#219 z@b_TuZlgX$E@udHv~`<s9J=f10#W#(SSVZ-yi~Y4xJbAWc$IK#@Dsvaz|RR^34TfV z8t?{Tj*_+rUk~P4+lXA$8V$wUVlW2$p71#ELE+ip&xGfJ{~^o;fUkuq*zle3%iv#x zIU3@gOs2#JFz1lTl!pj%{)LKdP&i`1p;4MJm;WNd?|~}{bCgs?_$0VMn4_e6!hUqK zO@u?>R>Is1z)K1kZW_hsyNQAqV;WI77}N(FQ8+LcaE&M&csSUI!ht#WYDD3{Gr>j@ z4!jU-B;mkIz(x`d`~cWU!htzJp(LDX|0xw<MB!kt0&GO#z?A1VqHti2R*Wbdcs<yN z!htt|jVK&=H<)*P@XhvuUlslk{JQWV@EgMa;P~$?QE;@fU-(<_N5VYt{D`m*d|bFJ z_#5F2@Q=b(!M_RD0dpTGBh(h0AlwC<Xc+m=BL!2$fJX|3g}LfjLHJH^Rbh(H*A-q0 zZX&!4+)8)_xP$Ox;BLYcpYJ1_jlN}IR1_3Oxkk7Oc$9EM@EBos%aer1fM*C(IQ%x@ zDc}Xd6ck@5yb7#^9|b>BV&@4c)`(&q_$lF6z-xusRlY3z26&?|g}`}f6qEM=c$e^} z;Jw1^K|c^a0X`&r2K<jiY5#wL;*1#l3I0LYi{|)O;Y2V`W@TXY!STZE5pChdV1Ay{ z4#ii}g{Ohb3$w?~5ne>`>8hf57zQ<k9|LoBo*q2|ZYoSM>(;^)v+gLo72I9;V{l*L zFThs{Q*4^c<n;49@U>*N|35-8S`66fj1y+3bE|L)c!n@Ln%jgcf)@z411}Wr4PGkD zWuziu_9v@^DS#1uLKL&1cwTrec!MzegssBMz&nMX1ivHv3iy5DTBv#-3-dm(&x9L* zPYO2%pNnzS;{71Mia~p@uT(6FdVxy`_XUTAuLD;Qz8+jj_!e-!@H8;*0b)|m1ve00 z0B$C{6x^niwEqu4(Mb#*1@{ns8r)Af7X@*Ua24<{;cDQK!Uf=Q!nMHDg&TqA3AY6= z67IqJ|BxtpgI5YueC~1KLh!S~Y!_Y>=ED1{!jy-2U3d=o4dJ`MZwW60?-zau{1G_T z{zGv@3|4@T3$FryA^a@(tnhX)rG%Kgtn<GKv(9rpi24*fO%Of>P86nSWQy?btp8zA z@EWfQ!qdT3g`?oQ!t=q+g`Wg>5`GEXN4OX~P<RJ;sPG=}^}^qPCm2Tl{|v=cF<?QQ zEzI@&JA_lg3xzYmTDT?n5#e^=Rl>c%>&Y3h6_wY7Im^0LnA0;mqoNoD#XG{B0eN4z z5d5j|U0}-1(bGlXuZ14~e=ocOd|voj@CD&@U>_y|==N1`NI1F`ieypj2A37y56%!i z2+kHh0;ZHUJvs_55IzZREc_+7mGD_`2Vs8qcNezsrQ9!>?LR!?d3i&{APgQQTort? za2@bO;a1?O!kovQCEN)-PngrVi-oz=@__JF;N`;8x&HU4C^QV77Jd-CPWWMPvG8*6 zCgGLf?ZQuhcMCrU-YdKj{DJUh@FC%C;A7+{-hL+(r^H}4_>Azo;O~V$0G}5=2&M?O z$pUZyGtK1V;1pr5a%KpB1+FaoEx4BOkKkwnQTz-=Ghu~q`ZmH|a3^7|g!T{)^1EM{ zCs<q~%$bf+!dxM}SvVa$QMd|tYK)^+H7I6@K@IRcVJ@BCEnEkzg}IFSuyAwmYGKZj zJSof-)#rt~f!7Q70KX<Y7`(MK+kYe-msEF&0jEsf71rR7g}E2tGvVdnQ^H&cJtNGG zL*EN;0-qP&2B!EF!{SP)4|Bofot*y(iDEZ6S@>;mM0h_qTliye72(gp1;VGn^@J&O z*;4pda0lVv!QF*Dn7HT%jxrWD6a&Se40trTLTm+lk}x_#Yql^NNo&3^=Y#JOh7)T! zIWsnA{HQRL*3-fj!7mHvAbe|+D5}6<yKqPFZs7soy~124{6P3>@FC$Fz{iBAfqA=C z=}eR>@K?ffz!%6_F@c}>R5J3P?XYbWv1#%Y;X>$_6J}sp!Xv<W!Xv>2!sEd8gl_>i z5ncgqCHxGygYb*s?mW4jG1?48U*Rp_D}@h%3x(Oljuie8e53F$;PJx0fhP<92`=%U zlh1QSpDpa2!ci`pEfz(2@G@a8L_Q+S=5~!Ro7ks>x#w@K@F?)h!V|z7g`?o@!fau8 z3$s<-o67b-3m!u8ffzgkJ|xToLyif*2|gvvY1uQvpM$>_J_|lC?4Yz?5au2eUzu1+ zj|PW?C-C^3WKm3kL0RFs;0)n~;B4U~;3~pP!3Dx=!S#eGg49I#b#N=;9pDbatm@s! z(X5y_L|-v@7Y2ib_ko8AbINt3@TcG#g^z(J2%iB@5k3c=DSRG$yRaA4`z~Qt_2^<z zaK4seZp;o!Ks+MMx!X0u<-t!0w*s#d?hh^&=84>!gekbNU6_Xp>=wQmyf?;CYa$dM zh`}uIA>p~;W5V;mr-bhSpAlXL{$6+u_`L8_;0waffPGl@;EQo5PDpq&xO5uwp9Y*L z4vPU#7swRm;R3nB6mG39%z5HE!W2qqB>W4wg|LN*%yz<*8tWol3fxOLISR!UqM%6N zRl?=LH<NQ>YdI5zF`Toe3ZpTzW(i|;#+oP0Ci!mRYTzZp1>gsSYk?mIM;Sm}DAv-T zQfz(iWns4G8-*)^cM9i$-xY2KJ|N6N>?gv7;G@FVg1-_T1^!O>9=89#h~jw|{3*O1 z?8WL9BeV+~6y6VZgpY#LgpY$G!fYig3ZDY!33E_dP55hY3vw><pG&Xpj3Oo?)kU}- z^m_?61`iN!0Uj*e0ep>cXYeTDuHc)6dx0kk_XkfEW@k2w>wl$lV<&sh6TTV-cMCJ= zmIyQH9uOW4UM@Tx{HX9u@RP!~gEx{Z$GYQfm+>y)C<Z0gyP`miu?`3`RX!1BIXEiJ za_|pf<c{^Va8>Yk!Yp*Z2-g7rDO?lmg~yCg9dIz6?LQPvpm4;1i^OTdt-ujsCTT_C z-rzi8cDpr%nG$t{k+W7~;rZa^!YFiBFEUH9h5FjBczS{xN~cKVf(q^spL$7uk>mDI znYvLWJnqtW;Ndy^n*OAc+a24=s^mg<g`UjE7QLH~>vXs>9=r4?KHk=^^3hfY^6)6s z1M%=2KCGY0gL_M#r}E$t-MI>s9rXiMVCf0{1s@UJs45<I@f}s&Vx@|7t7=fD>qXVv zNjOM1P@OJY>MN_m<qrL1bvIvKsnx)Q6n(n7>p-;le08^S`~|%37o~M>4Y#7_^h5fa zQ;B6$<MENj_m$tT50&f=o?pXte6@?v`0HLn(^4H+MAKun6pLH*)*5bQ-yT@_LDy;> zm$I|~0j<%=1#V@$eIq^`Jq!=uvN_7SXG!vj6uqLry?EV79sS7OGG)CDYS(VKWYN!+ z@os+<xOWBOd0I+ipT4(|o1MYMic7nGIX=dg-qo;xUBC17-bQZj=sd*U+*!d@IGA#w z?eZ(+Idv&l$aA<XSIBb>(dTW4ck#R#1o|2fDKq0sm_wXP-I9ZL`(PRi8-EY#VU694 zHZQ^`zR}mP6+DN)z4rV9h2CR3ELoxP_^U$OppP4)kv6<XzAuaei3mKQDbWf%t+zII zBkE)QX=As_^}MSm-QVs-+TtMy{!TX=TY32F@A5ePusi`+@^`%lS~y*IK2pH(2I|#? zpP>fKl~58Q6%D<OzcWJBQFf<?xM6o%i1XG{LtOHn5*n_@HgU^FUxi{~h#lL6&<>=- z_z;ij7#F$|4#tMo!4%teA%S59hP)52aasL99-k0u26NmPe>EK9#`s>aS35*ut(?$& zxW@~hMiB{);Q}?>EaDeZh_lo)eW8Q!O@%0OxE0qOHFc{cE{9Gqc1CYtvu@ec&Bj5{ z!<)Jdqm&_0q5a4TPbdvR#)S&tlQ+aOV0<AiTgHbd3YHKWi9r1!E|dg9+-DXHb%iM= zN1<a|o-v4Fs3FHP!4uH;CXRgq9OAmQ6{1KK@(ETvp&+#5LKFw^h92i?GcI%IW-f1H z(N?<PI1i%(<}8X9&l@V;U$<)JmQ(xmRn6S4dEE1w=qhIJmK09LCuS-x8tzM(gTINn zY8)O1Qr7By&D^l3TtI)-%&qN7_3H}F-E#f7ewEl;Z9*WpSiK(tPVA>v;(?3Rxdfef z@nZE3w0ZGjbqZr84pQr2GfAc0H1S3&afo^xzBsDP-TI#9uB-0VPc?TVp4NW7t2t8m zTm5x&ca*1Af*#Pq&Gx8(p4P%W6@G_4w4}@QfCnj+)S4U)bkoyXx(#Ylma0_KEF`L* zJCE~9^?VQ<;3`O|-n(Ga3h<2EQhm)E1YXm}Tf*}!zxKCsv!gsi#A!eeRbUOAI}K^g z6X1%C(<tU-3bNB_OpXumloqE6WqbUP?t;RbT<`$whT`zLDn!u~PpB%=I4;C7m^bt@ zJUxMH-)u_thOS3mU9dtcS?*M5Q2_ONmI@7nce7P!3?6e-C<Tw(ROkro%vGVQ5XS8) z#5wPID#Qar=Bv>4`dBNsRx_U5;w@e81%z)ZaOwKH5I$mHL^hf+UVd(SPA%Q3HGB)? z!*yv>Ww|S`M{Bo0U8SR~-Lkp6VXO3DzG5(TBl}Q#Y6r6Lw{#&Hx4jS48(X{Cxz{7f zQpT@_hyFlS@}%d$c3>3#rc9w9P9Qm6``Wk-Re#;Qjhm(R>cTc|bM?4h-o~w`YUvN! zAn5+u*VZkluoy3)>Uo|<+<t}IO4y`T-&2YO3+1)qgSt;!_Z;lDZRd_m<KnHFj_fe9 zg{p`vgjM_Nt?k?=)na`^dv|b`dk|MONU`nVc#=nasG=+J<)76b=?W9p8GdnOZ9sgX zW>w~gLq!T{sKLsGwQj&VM|DaEcT4^;I%{G)L}=Ev_^*n%B9Qd~J!oP)I0Oe-8}y$Y z+zN<m`Ht?D$tJk<Cb)TsF--612-Bnb$&T)uYJncp$qgqPFYYs5j7L0R>A_CMiw&LJ zG4LtBvwK@kE?y~dnenOFbSC&r=4NxgMC^v)7VQ%B`<>lJYPC-6;^v|Mt>48huRbmA z*TvPL1a5BjSTp{YFAdhXG<bCJ>MPvC_TS#~5gp+^9;Yj&L^5>e`l_Ptx~+7%;-jP7 zmW`u#;_XZJe<U&IkWKuZB;$qo>yC6UIWm`dP;z8051TC67qSk?&ZSoVxa3~4N2DIJ zy;Mx!VVU9=41N^DQk?(gkDt;d+bwuL51C&#tAsIJvz`#<VDvfRJTRx+Xg?pkL6~1R zTZH*>^QLf1FlW|izYX{!b9^oo?V;djH4Qp}PY8Dfe<|Dp%+G4t;h6p>;l5x_tx=!j zdrqy92ZG~;uL7HW1xO86CrUwaYeyBnzu8y-1&7CGV*$86*la8Sb3|-57JyrU&Bg+7 zPq5io0PX`e8w<b;xQ7J5fcps#0h@gVurmxi4EpBy+-soV9v{Yt^^)J}<Wb;~dr)o$ zPZs@&;HdCaFhA94{{WbW0+K%hFB1L~tc8z(9~MSO8@+fBij5Yg<Rscuu-Rk)k2qUp zzSY4Mz#P#qfNXHd6(^Jr{8;oU<IVn*cDOcR_6(pPqpZgE41m!_#`X;G_%t*@Ms|yP zHCQ;!rU5X&jLfD1FuqG;n+CxA)HZttz|6}`_)NDfm}buaI16m{41lx2X3qe)8n~(0 zXBM~S_dgvsgrdDLzlH{q(MI864HagrM+h_0HwY(#Dbq#!jL=kJcB00A=rck*7^XBm z!Ec!`%b)d#D3EHgdre>oRoGf9`mEL)g!u+rglm9z2(!w4L`LJD1LhHY<m%w#!YtrC zEQR`f;j`xWTqs&X@uL{D24iSuEDZn}`F_|L0ZtbEDPSYt5B)#EM!p}+S<Y;+!y}bz z2>ZcCydQQ_z%4~T%=MoRqR4;&hjWZw74QJzW?-JTLj4xtYlPc@M+xJ*&bnE+CwQXp z2=G+lG2mIk<G}OC-2ZVa6nBfk6z~$^X<!PFF<?%kE*G8+epGla_(|cr!8~(_M`^Jf zY!j{w-X&ZW{Jt==FZ!t{n14oIACB2j@SBVtjRyZA%unqE6b$O$4=ydd5}Yo)23%hF zF>oc}7r^<#>%p~R9JOADqJbD}12+@i0d6DwCYWdTF<>?<J%m32b0kguBVcowEci3< zFwy@UJW}{1_$J}g;ECquU^w^+im77o4VVIF^z<Cq$m@f@2b)WK!9RkHxIUN#(1`1U z*@&$Ww;VDVaee4#f{nO7n4;Wk#ZF~2Jx&EGG_pB%5-pg$-(JyY<MV+q>+~VvOz<(` zieMwI54SmB3Zl_Z_K-$gAI!Y}L-g7BB%p;fHwQO`!pP{uQg^VC(Fe05;TIx3x(aMW z^ua72)kS|8xFs2VJiF=k!ff@-3ANDA1rHE?M&fGW>ImN&EecMD8S#5KxDGr^^lt*+ zDZB{0RQO?Vk?;!eD&bY&Cxo8^KQFuvOu;oqv>5!FVbp()w6}`E8{nP7d%*7q?*$(a zJ_!Cq_z?K0@KG=%+Drgvz+Vf02mVf&W#t!PmX$yGS<4tDL*ezun7f+%!Yo8C89fur zhxw2IvwTz*eU^{v!Ym(@dZYbJa3f)sj~2o#AMJ#rc~DRsjt-bN=7L=?hfPN09^4o_ zO6+t8-z<Cuc#7~K@GRlM;JLzuU`odE7GXTBM=s+v=J;F~uv6l>ZnVU=Su4x}^|Ej| z@J8VbFhA;PKNGx5m~Y0zwWwbOd_cGs_!D8i*iqreRtw~rC_2I5oN!n0Pr`g-j)duH zFEEdOBXh`Q7k7Hzy*K3hx&sQMu2spOqR(x>_u712<u$j5?;!l_sP|KQ;cIR~UuI`? z|2iud>Z4R&1$AFNmg<@t-G-jEo%Qt_F}IhhU)>1j!x1!QqbkEVa}#`Rst0a@_O6~7 z#cGuY?Jdyu-G^8$)V-*7Hbb4$o4&53x)5r0tA1cJ<`2_#^6QvQyiO0}W13#~I;Ibk z^-8aUNWbnno)hD>XN#Nb%c=>%bls{~Mv88^1+#tib+0X$-|L8GB6gzSLh8=cE1~O2 zkLvRI{xp3QdcJ+IGF*SV8n<mZx8j!Kg*v<y6NGhjD?EIC+oRiv9U}O{Z44soDx7Ti z^j5dj#X|&_)To~3YgDgp!`SV_+PBR;6y;u3#YsEP3|{{8jECyt5rSi34Mzy_W98Ch zBFD#=F60LTCKE@&K8_H443!E;2y$GEYq}0o<xRK~W@d&l4I#nFt?(z_dlyEo^Twqm zML7*4Cku9ji5w?5jJmNKaf^)K*YU5{yTXLv&4Y2E$V8|PyO<yk8uQj=vxJCq6yk04 z9x%WSkT@fdi?POzuPM<A^3-Hs^JR#{>7fa!sz9q9Zk1?%nBmr2junEeoAI5v;n50? z#tX%loC$ayTJc>e`GTp$1@Na7t|I#lN@oZyI|C7V)R}<@&2V->XS#C_c$zaAJk@y@ zrc<03;cT+QBOz{e{4ky5urds|#n}kOL}x6FCpaAQj(0fH8Rsm5)v-<&{Ke$rhcHMO z@+w>ezJreA-@u(I!82h0MxqrwNq+qnpf`Bm(l^|)NvY8H%V~W*;&j%qgtV(TeDfbc zDp;kECEQn2nqQ3GK+$469JZI1^ECc&;%*tVQu@H(hzfWW*U?fLVjw}$vX#oj3)qT@ z=S{ucqn|sA$x^0&ptNcYi(OOeA{hf^RBtGrNqvdd%i;PYv`VQz(VA-%TT-XMw?L)| zVPEP329c}Uz`}vl`{^cMJqyLb)S0waOR+c|PJNq-`szI>j;3~`qK(4aSFlc`E`(m7 zow^zxola$+5hyu5Z@$veS!K&L;^b1Gw^|J|oRrs!R{EJa$9R=?imCzT2n$=K@#`;e z@%X$O^zt`dxAC)dKFnB2R%slG21XcFX_eN1F`j^Ph>$=kZ6~8LS*61Y`XA4S`iD2& z95qmfce-^wClyW?bL)5#EPdNfOy0W;>q8Fr<Gmc{m!l_Plh&TzddE(;ikhLn+38M> zR%XP5bt4#pIETSA9j79)<aWo|0@XIh2_V4rGd<4Fc+Q;daX3SD<Zh2M66)g%Jx*h& zPvFT7%;)etjOXG-9;X22Yw-LH-n@-x2fWQYc)Cy@$CH=e{k$mZaX7&-6O#&oRWOMU zHLZuJnEDoKHV%HEs~v*~sUD`9Ksf>bRS^aGBP>y>hj}e%W{ib`MYtLikpu8w_2A)t z>=Da%qaVHanw~|4<y+B@-ta?@*zK-LzY%tm^4q{mA0op<<2+?f4P9XmQmT~hv<FKD z!-}un;~w%Pd<n}QYy5w9O2|#cN$<KXm9CxaNiBYUultne@6Hox*!JsT@43~BSH0(M zOVsJR)9vV;hy>>|Fc7d736}*^nuGf6m?_Oc=I~>+a3=Uk;ao6<IcO&zyk58l_%&g6 z%v*)os!=Qs_B&fGp?F6O(4kuI3-<$mEX*&(&xAP?IVn5>{Dtsj{cR(E3*B;ILQZkf zF*nuYIZ#Hwa2);ZG_6i>jV?|1KH=Vies(vM=!L^4@o1<=okUOhP3#uQCr+a8>#1Ko zi4Ls`M)O{M@+9WLd!(47cQgM1(_y;SKVbR*#%O+Bt7AqgQx1j0ya*mvo}NVuD`BCp zIg@t_oz>O*q3ii2MgRH_Hy6Ej)+tz;Ujc)|SkQ&1E?ZVx^681PaSdwL(PQ2VRw>?e z%024!{1B&?e~l{n1_Ha(1#+7p`ZEsj(FG3CpMCARrQbwGnBJ~6MmaF;>o*7J)<26v zDcu}*`$;!<8$6V5?mOD|OE<@c87pQT^?);OhRr>P(w{ZbGtanXJvD>+*w6%5t=He) zQ@To&_koo3Til#b(r?AVn~VL{(}>x{evA8NF7{h&)hvgLTv3PH4`(>5@oLi@4$h`I z+}%9Y`4xYsIA1_#vNHmvw>oTiCpr9NiQeK=gMSm9Qt)VklMIi>J6Q;BobwBKtWyD| z=(n~&E7ot7^7;pIS;|=q^KUF?C-@V~;Wnb$4mU02IQ!uSm2?H%_{Xqof}2G{=!PF5 zGks2bSXRz=(9ws#acd-TZ+c0W*Dj#d8*ZAean`jx+XJSz)4k8SDNVVd4E-AqHF4_W zkLBEn;Ml+MY?Bmj=`#J>EWBOn9WY1#M$1+zZi8HT7R_}d{pMLWw{_nj%u2efb%+wW zEIQhk%HA7Y)?;`aNUcX}`O1O62UADUzgmh%Hyln~plh5%bHBiAIw93V&p78+8NMB{ zxzxjGdNoL~H<v3c14B&Lf-5XJD|M;cnM|)Qb~_c27U*_*!5zAt$LQx|#rYC;J5TG- zw{DK7b%L(-ty@P8)+4@k>tYGy!EfEO(Sr!l8!UJV9yrawv1w(G!!@foCk+|wb$Dvo z3CrOc?@7y92CEk==S${_a`*u^OF0Ufvz5bD?>Wl35eaykauy>3bCttoq}vtNIJsiv ztViVLD~Gd4cVNZa|GnEFdK?PNxgI9U;jUkg69C6KX2j=oMYMd*uka-v!Upi#8=S!6 z>CAwZ6}!a|M{U8KH#jW}J?DLxS`OzMl*1_wbX3<u-ydASMUWt?N$^e%gK%Fc0;(94 zV=b#7iov^AL*Em86`=<2;RqA=SdP?3zjw<f(sHnf4pp#<_Ws~Dt;N~4P}4`?ZJ;Gw z=Y@K5KUEODIu7GC<I^Ay-3j%juijvTcs=$9w_;Ldnhz?*U!3{cU9bGXP0!&Bzuk<^ z1DoM%s@-V|y;^}lZ8I3Pg174<KVYTmcb)j7TVOn~3v0p>j>Y^`cmC1Mu0$t^<Fnw# zALNo_;-qSHA7oI8Qy2*+cw8_3(XEm*l<6}|Dehc~V3li@`VcYA;7fw}mKm?=&){hy zj}KL|l@HmJ@slp~lbhF(`>fQJO6B6E>G;aa9A7Dp@e<HyB4jYh!N${@=-Z%}Z-qMg z6B5=0FxYrj;iux&Ke^QuF6rF&vzwi4qEpYfYy(fKzN)>yxCP0^MFZnv2ek8l(rtfn z`>B_TAN<AbuhdHY?RmGa+O6CF>OSG|`1HA7-I~cJ<kBYO=TWk&7V28Rxxad<_;mH( z-C_2ZOs|<t!3O2@gTK2K(%RsSOO4<gv_sz$JEW}9alQ9<j4iIyU;mD^t*3RFKisR; z=la$^(76pPUh{{0WgwwH-ra+b$>`bCNKSpL;JTY{98oZG*u-nD8#Zou!SE5c6pR=@ zreW>+^-G=_mpM)?K9~@>E8*{sGKz<niVTh`#%k2{`B4rW6sr+_ZIO*7%TH|C*{<_< z9p1TQ`H4#kCCg7ddZ=XiiJP@cmY*sz1CwHIpMd`ybfiQ1oNzXn!+PjPtx8aA5QEC# zEy5hwQRI}4Yl7bvt`Fw@bJXW3<)ARWe63G~+k#IBcLQ@6NBcd%JUM{OnS`H8jvwm_ z#qVOkk&Fj#PfLYhes__t1}6!R1@l9R`uqkiC(IA2OySw!T;T=aYQmhjtu4F`(_dCY zQS1gc72Xe~usj!0IC|+P%yHi!VUGKT33J>xQaB6DmXvOp)Ep+0D}g5qGo>l|ZkC^_ zKtX|9T4GXjNs?R}yhxZyO;Ho-w*;Fb%D~;hW;GCHg#$>l8VGIzHmiZ)=HM-K3vLfK ztAXH-2tT$Q2n9VVIex4s*sKOZzYo}~27);sYE}cmW58xL5WEy@Rs+E+z-BcN{217* z27=du{V1f21n0l`DPoQv+X_Xh7;rA2obU(WOyQ$oO03ZFX>c`RPBYdP{t;|e24Uw9 zFqh$J{{pzPun%Rdr*IayzgfkDrG`*kB?c|Qg~A=dW(5$<C2Cb{1rUsskF5ZLS<}o4 zAlLy@K$o3<8n}oYin(1SjNoD?i$R~;-(p9LL4j#d>jkk?2K)xujyZlym;vt>X22f_ zGhhl2&^`m^IF=LmXcS|se&AFv4{V@5+k-f>`~(F{Zvd}HgNk5E=#ulmX~I>(X4Mb+ zEKt>{j~Fn3I+rmIW}rUa$7&(Wh_(}EM7s#5^Obvvg4L;C@uD`7?-P8P^$}A&YhgG= z7j=m=gk0bUT_O}Ztke~cF?u2&_vttA@V$bnk)x9r!)~>1k%qp*Q1{itsGbJ3r)CrV z+~RPWew&7)Q7`V(Y6%P@-QlsN`*n{@^8C<MzuP_19Rh?IJt93k`}*mddPJ&1ws7k{ zPl|q~N5p}w-=-ds%D#=+^Z>Vwr0CzN-BTy_g!a`nO6CT;_KY~b2ceAJHganvOf2pj zq-WfZC=|iW^GOZ;T+c{uV$G{iiBKzR;=OAuX?4O?UG*RI>lxJJab}tjFWjwHq{^k) z!B0=5$JK6_X#@$EEy+4rA#@*Hs~ISz6)ioql;e&Z2)^{~Ga4#<-Q@7$@h#xPk2aH! zgz0>EeVqEh^xu84#|_j}{@PIaytAQ*pJ=RkZ#8bctQ@@fULPyvP?jxghJSIh6|mwl z2M#IqTT&vHA-ND~;lKJDJ?OCle;57PU6JO0w*y^L@rD$=c1+}u{(MNJQt`xok+<SJ zzj&A2^Ytyr&_#nW-?2t-otK{NtBmx0c*(4vcv(zVl2h69VVr($Kkl!0^jIi;M^X05 zEXn#g8z;{0zw%N_*TvW6zf5VSOG!$P1Yb&N&Zk{U>AR@<uPNP*n%;z^v4^BI6ZEes zeY<h%<&r8=dRQ!_`~9z`^h>(ykVw5^B=_h4CZ(5~lzuao(g**N((34v3<|&MVUr@| z^v%N~7pJ^qNnNLQY{L6endVGONlO2_GR?C8Pbn>BdOpp(3ICrf(+!IkUKiOI=lMNW zroI1ErdODh-Wf~jk0qs3V`cgT%5=IZ(~jPn<doGv+!(nijr^|)Hfyh98kHnBr?M{< zY*X=-zb4c2zcwLvz!jPh4)8BEA(N=7{LP{H*MfZ;t@*uO`B0vrv4Y*_f2CmSMPnkr zviVqCJY!s>_rEFBf4BKS!M@l~|F@~kw5%Zw^<Pt&-7XSMQkheZmkRY?Q<;<NNbLVM zmFF6_|5sDF#`sYqZyGT?lV3%D=NoBkZGYuUjrI$Dl2VH2OpWaSH>v)JDd2C!3iwBV zX-Z6^ohFU8Dd4}){I>->x)N!Nqn5E-4gdM`aA2bj@Gnx5qZ6!~U5j+PRO-13g#4(* zhsXEV{8(Vz`P$OVn;`jdD>ap$0y2Ls^>dSG&+qNVhw>E0ihbYzxnjRO(nK$v6LJ2J zy3fU!)$*@f^7R+V#hq@C-0S)8`_ca>OJ*+kr!1)%8@4RG)WoxSE@^YF0bfde^y5rS z8Mbga<5F#qVGElVr2gXA<G*d<DJz7;HywiV42~s!um8Ek|4)Z4HSdm`j15~Jx+n5# zoadZr;yu6kbkhD{)yu~%51A^kEmj2%NENVSZ9Er#QcM-_a@^uBy)TkfGD`dxjZbtH z3a6<79BlIEse(WMwFdml0S!kyr~!W+(A){vX!rj*pyAXeGVNasXru=GUmMYw8n85y z{2$i<j%Ws`;%*N_?)*0;|L=@zOhYvD;eRUimk-we|DO$A|BrH@k1Bp=)xT|f{&o&{ zAHOUIbos|4>2VDj)->Nsql<?<9(g+u?T+ssw(k4_F8O)zEp|zef^tac5V#g_sY$AZ zPYIN69^sGbKoKJkrE=rSu}YzJ%BHzLVVh}>d@obwP2gIGS!LqlHe8PjSbED7{?t~# z!M$wP>Ikc{UF$8(8ps~4SKvVQXnhASFYeJAjoAaVXFqE7LZnQTlQiD=I;CO5K7&8; zb$6Io^6(_W_(tcU2wejg*qzn7#7;s}qGfY8PeSwOfR2?&XT71FGzEaG2ET&)gf^52 zEw!J?;IB_%Os5CjSk6%B#5*|rTHpUdBs;ndFNuv^TVTQFHJ1KPv}@Vh@W<bU0bpZS z3M~1%J_G~wfgd3eJ$d*On8Mk+lt++|feb|sJr2+P!DP<#+2dd(So%HV+xJMZV9F7& z*9!5FMt`tD9a@Ucfs0^6&Pm|zNJKE$i0rjW@u)s;s5yn`omohQuyY&SZ8rzqSvxGJ z1ypZfKP{$A_F=;g0{hK!C{l+74qjTmQaRTk8&)aj3&j4lIHwQdxj)WX0JB3$&Qnl* zQN@X7Bm5WNz*~ClddbjpctW$~Y($7rXFtN2;c!N8x-%X;&EZnUREPJ;PjR*&hLatx zm*46<gP<lk?cnql=R25AbZWt~2@d7F#ybV@ZJfg`Gh>|)Y+{)%2f^4w_Hqi-vmFi+ z2YnAr^(GDE6qj=pF0f?B9r#$XqbOo+XD`Cbakw)MZg}Eh(wNGy3pa~66XtvbH(0Xc z34qGs?B3Scn%`^`iJ5Sd^aSPSL!6>@k~aJdwl6eAmLzQ?TQ<)lOnQA5&};LM!=zoW zg8gMikGRQ7dW#&i|A5V;eJmEXU8K*w6saBMjz!C<j6ceuB#Ot`4NGwjWsbZ~HgtRr zr+ed_KHvn06P<o%Isynd*CO|V&RIk}<lN5)S*89!DtVo;b79wM00YapA6AuF@boy> z!J{~501J}iz=6-wE7wQLdOCRZhV_xUwRo6U&*WZ<5w`ssQZ2a;OSWY%hJK9GZHhW1 zn>)~I+M9KSmm}FXU4W(J0dK*euFdlzlLzt@8`{kfT=F2kdSiPsy))d@<}q){g{+}1 z?R>mL@-?*I)@HcLv84+;gy<#T^bq{)Xg^DT#xQBSTAp5d?aPr$T_`!>S8I75W|{FL zuCdg*9Wb}-Y4BUUKt^2|fynsPD_k+P?*^+)Jog;Q^(qpjrrN{vB<&+Qvp7<ASXHLe zJB*0O=ApLgU2>f5B1P3+<DvZ`0#*CSe)~__-%qyfX<qPq^v$uKqW$;D={Aq~R0qhJ z_LF*9aU>G`9TCV>CwD>5=J}}V)FOBhYr@nQOm45enO=O&;3HPraFkeelTzp4qU^A7 zBdK6gq=$L717w*P1<X})K~hCLsv_c8t`2>Oc-Zv1Sm`S7VHr&i*Y;M2evXHBP^7#} zn6#VdaG_FHKr<G=LK8r^jZYW85-C%;AwpJIf#lj{*-^u9rGk+w_X}bRW++z1R9*B+ zBtu<Syy2BdNO>B2_0Cr#IqLr6uV0M}RFyyFySDLg9<~+!t0Eq)SK|;9sEvn7up6G$ z7@|kN7Qv#L-t!vVPSa=c@HC9mWj01ymu4%kUQ!H>duwVm_vuj^5#%I2Z)4;oOkg(M z6gi}R)#;lf(=k!HbaUk9rh^&x9UexPu}m^S*M5s>y4OP;wg;*x8wPdf;{BjYyQ;TU z=Y8Gk^+*}@ydLm+q-y2U2vPlFoUr#)MGwG9jSlqw7Y`fVDex`-lz!s%h{jE1Ew@C{ z)f7E&OQfLOSM;}vNv14*y5`~k)0q9uKciP|iL_|RwGGuaj<ds)@gH0AfHk}^UB-rG zrbcT<pluw@@(^lnJs7mZ|C&>D*49XY`bziO8X2wpdh^yuCC6mVEpbd()yJyWPk+BP zQnfUv=habq852Olb<G9aBAIo0KDs(vG5MlCC3V$zms$LnY5&t@8awoyZISl%vsuHs zFU7kz@*<Z0v5MUICuHs{1alN#1_?nXQII{X)g&W9U)UC@SUUwalPa3U)^ep`YTD6e zJVG(?#(LD)K{q^v#CTyfEwB4*j}$`s^rh{1;Uaxvd!%YgBQzjo&L^&h-MAFYyIW0f z)>%6umDDlaVMipV&6V&k`BpYg*T6W)SFoBD;DwWC&Y%WOf^27Efi(XDZ&W6fME@2V z|C-Fy&+UkmSL2G`*%A3Ul&}bm1Fvsd`7@-1KHC=wW&OXelxE$Z((-RuJJ!u#Q=ePp z3;sR3-T%&zlYSQOd@piC;P2SxbVYIP!;xp>i(4L#_&b|nR>>mm02Uu4H-BG~lVZFT zsTUK%z=8`Ixz69WY*|?2@#7v`#g!fWipgB5!H=iumfR8b6<Nlnlt#dPQS9NdVT6iu z2CYJJB*qVsDG-j|?JTn8V_cT)cZC?YCuhc(+iO);jK4tr;u>l-D9;Ml0#lNP`gOp+ zmFy8@Wm9-#8gO|rLAW(IQMfbMEat&ZH?UdE1NQ)Di5-r$IqIN4!@%6fPo4m-BRmb< zNO&&azlA8~f!hh+5AGto0!;ZRdc@*=H5u8&c82TcWVHL%O~M?tPY}jplQl)S9eAd2 z2k`CSC>`_7?h=D5z>9^i2J;vm+8GJvSeAS}m`C!EZv#_sfxHm>s_;_qcHt+%?+C92 z9}wPv@U2fou@MGGg?E8Z2!9A>%fW@WOfbh-<ZLij`3&cR%_1N4tAfoUADF39M(i+E zTw$h4mSLoSLntbXK{Ig4>R$_RL(y*wZY|9Gru+{h(GT2Tcp!MN@Nh84*R;dbx>0yM zm_lpRp9zkdJ$z8ihk}DT8ZhbZ6n+4_NO&cf(pa>!2K=z_Q{dIY&w!s4ejfb1@C)Ge z!mofSN<@F6$OG$bDjbw<FvXY2oKvJA7MV4W{X3bpj??huM&K`n+kz<_O#QB4wkh06 z!Sa+KJP4d9JOrFVAq`p@4n<fDt_4>Rz7AYTn90a9;A#Ixa4q3m!8{M1`cuKJglB*$ ztWNzo;C{k$!Tidj{#|T;Mu_4b7~CMd2s~E!KJX;rN5IpCSAh9_Mvqp3?+{)KzE_yZ zzEqegT_n5-yowx!W0rQa&kwv0%md`<>DS=(!ajwsG~p!hR^c#sr*Izl9brzkzb{-L z{IM`6c0Uv5++&n-eGIGz6kiDU19MDL8U>;zBH=;1O=c^}FDo)@O_Fe9Fi)YOep7Hc z;pX5>;a1>W;V$56F^(GHjM`$rD#Xz!J!0cSp;Gb<;I_gu!JUPfuRVnqg8K>=fk%?d zaEOiaBAf*tFPsCOZuSVmQZ5u6#?t{CkVV2Q;SUM713xO<6a2I=OZfA`SAjWaP&zF( z9_4313G=*pvI9Gxk;}pk%Aa+-L;?PZoE~#bfx;3_L{G?TT2R9*ej1f9Wedr8SQK$3 zqZ70$38PhxZS8|TytSHAzg*0p*5GJ~qN5mKbYyiGM*Cp(6-E)U_ys}xh<NOp9i*)v zJeK-k+A-Vwz{s`OEjwVgALf=FFxwAv%MKW2D;m3I2a1+3SRx*^2R}xJOD5Md!gvYm z1z|X`UJ<Sg-Ym@Q<6-r5TMf*^>d6J*4~1)kj~Pb#H-dsgcv@-!{#KYJmLJK~XWsL; z6LM#8NSJ*=8R3E83c_sZst6Z?%?&zm%R+6o?SXFsx1l^FJskr@XW?<+p28Er{e}5$ zah337@YTX>^{x|M45mmS{d^ESL6{Ac+0F<3b>JDIAAJdmMO2iJCAAi2VR=~C1+Nxn zxBH}UF8C$kJn#nLeDGG`8sN8u*?xQ|+ys2s>=8u3&7d$_^}wCLXT%a43QmqOavXA< z7w!qZAY2Icp~%zDb>NUNQ_I|-1N|xBiquExgEK4dA|wB6h=L`*t}sh}V_}x+=E5v= zy~vrdDm36S9xRL^V+|7yf+vvC^04ai2>%kEY3#s&4sI6%I=D+1ZH2Y4cz?r;-%8=Y zv3ELV^zf|crOS89=nmzLouGWBuii}MXr0&@%Azaukj_x%>1UyYyvQGXr0Z^7@TjRD z=A)xN!^dddtSekB9Hj5*n$g{JZjk;IPt{Ua?*`KxJ)Mt2{SF_u6=!tMXrVk$4ADb+ zz|s}^*&Z2_JTKj%b9=(=53}?we6F3N-|U%DRo$<@?U|A7SvXgx^~%Wgg)z{c#T|#) z>cJ&99xtn>^~!KO&$Q6@(DVdq+(NTY;%#Un;3K^<D*Gn1L`!9k8;kUY<=+?S8oe`e z6W5|$Scpck9}=eh67{o-_)hN)`wf?2JP_NPxUqM}zmo`v&VyUUWqP#q=I3EvUtBIS zYeAlb!LV>?etZm6nBgwVhsQUYkBjmzthiV%s!C07!UM6#5NaxaC8++oU^<O`H|DtO z@S!~IV{3Me|0mb%s#Y04YRZVA6aMqX>&E>vlDU3YP<*I=#-@L>g1yQt-|dbq-yQmA L5slQ#R<Qpc4B}(= delta 286198 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%0D-o7?_><8668_p< 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%0D<QA_woa1-G( z;5NeN!J&?#xBx{rVJ?yO6n2683&(;73w!z9FU+GhCJA$<W14U>c$P3%R38$~2hWdi z$fyLx0x_rpUL;%yepa{!_*G$^!LdfTF?hW&XGt~-bJ=y9aC`7a!X3e%3Ue3pz9hE) zNJgH)aYzg}W%8Xc&(}C3%smJfgt=phQdM-zmD6a<`I5O~$tS!KoG82noF>eb(+uHl zod3xd#SU=3@Q2`<!dy~qAiNLURQOwPYvJSI_QI6kyh->sa9?2_9eJy;g^7z{;1FZ& zhhn4{lmg#FE*n|FepnbCp|MaHjij+ynDfEQgyF;plQSc8#v6s9G~N-;0)H%=gYb>d zM3E1J1Hx=FzY*>Z=9OJZnUQtElfna_e@^%g@I~Rt;48w@z)>j?w==+L<Z=;VpfZ|~ z|7?eI#DLS}1;YKn)rA>YJ>fy%BH_W{*21H}?S=0GcNJa??jigVxUcXk@U1*(o-uk0 zilM@rz@vl@fX557i7l~z9z0X@e+54vd<i^H_%c`tbMpBqVYaYKg+p96dqEUsz^@5& zA#$xSo7)Y-Y+|<vbF<-g;UVCUg~x#R2#3H2gxSJ=Bg|IySPI+!a)<yFC&l0;@Ht_g zRB}=HJ@6G_PRmA@ilp4PV4v_QaH6n{(w-*Fy)7BSl&Z)U9z*$$d{In<K~>?I;9A0S z!3~7xgPRIJ4sI>{8o0eMH_%Xuj4$>!xQFmoa9?3o^+DtiEKz)7s2F?<9xc2JJVBUK zt|8&Cz%zxv0Y4~w68wnpX)s0C7>SGEr-fap-phnp)k80cg7dYn2~%WZtuW_qHwc#j zZxL<^-XVM=c&G5q;Ln8nf)5B&xZxY&JHf{y95Tj2aZ(JXfzJug1YZ=M1->GDA2=Gz z7<{uQz&_z+;6&jUz-huSfir};(<fW_EpWwD<Uc*)L~%7S;IRgEg?Xw$V`0k3wiM<( zaa&<XF&LeNe+73JHZYOdTbQR83=~cP4-rlbK`}xU>EJQKWx%t@Igz!ThlDZwGv*7U zkuw$uW7Wo3B+MrHS>a0H7lo^WR|;1HuK|Y`KusvN)1Z80eeYvow�<v%p^q=YhWy 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 KO1V~6?0*3(#*bM5 diff --git a/tools/sdk/lib/liblwip6-536-feat.a b/tools/sdk/lib/liblwip6-536-feat.a index 5e901a6879613f007ebdffd7b80db9b36fa5c02d..592df0cbf66ed748d5d258d13061c17b67ab1619 100644 GIT binary patch delta 282947 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%0Ao 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⪻ETR{LyMTWo=MFc;etU@j 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 delta 286659 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 diff --git a/tools/sdk/lwip2/include/lwipopts.h b/tools/sdk/lwip2/include/lwipopts.h index 6ee039f7c0..1b26f35257 100644 --- a/tools/sdk/lwip2/include/lwipopts.h +++ b/tools/sdk/lwip2/include/lwipopts.h @@ -3619,6 +3619,9 @@ struct netif; //#define LWIP_ERR_T s8 LWIP_ERR_T lwip_unhandled_packet (struct pbuf* pbuf, struct netif* netif); +// called when STA OR AP is set up or down +void netif_status_changed (struct netif*); + /* -------------------------------------------------- ----------------- TIME-WAIT tweak ---------------- From e73057a5fc3bf505d81a26ceab5b8583062874f5 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 18 Jun 2020 13:50:49 +0200 Subject: [PATCH 063/152] sync with submodule --- tools/sdk/lwip2/builder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/sdk/lwip2/builder b/tools/sdk/lwip2/builder index 92add5010f..729700a31a 160000 --- a/tools/sdk/lwip2/builder +++ b/tools/sdk/lwip2/builder @@ -1 +1 @@ -Subproject commit 92add5010fc329cbfbbcb1ce713108451cf9fc8c +Subproject commit 729700a31a432a3a058d352a35613e25cc0e5b38 From 0e245879b450e0f9ec0dfee1486073200ba9cba2 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 18 Jun 2020 19:37:30 +0200 Subject: [PATCH 064/152] use interface CB to restart mDNS --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 37 +++++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index af004c3e19..5c439bfb17 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -23,6 +23,7 @@ */ #include <algorithm> +#include <LwipIntf.h> // LwipIntf::stateUpCB() #include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" @@ -256,11 +257,37 @@ bool clsLEAMDNSHost::begin(const char* p_pcHostName, bool bResult = false; - if (!((bResult = ((setHostName(p_pcHostName)) && - (_joinMulticastGroups()) && - (p_fnCallback ? setProbeResultCallback(p_fnCallback) : true) && - ((m_pUDPContext = _allocBackbone())) && - (restart()))))) + bResult = (setHostName(p_pcHostName)) && + (_joinMulticastGroups()) && + (p_fnCallback ? setProbeResultCallback(p_fnCallback) : true) && + ((m_pUDPContext = _allocBackbone())) && + (restart()); + + if (bResult) + { + if (!LwipIntf::stateUpCB([this](netif* nif) + { + (void)nif; + // This called after a new interface appears: + // resend announces on all available interfaces. + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s a new interface %c%c/%d is up, restarting mDNS\n"), + _DH(), nif->name[0], nif->name[1], netif_get_index(nif));); + if (restart()) + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s restart: success!\n"), _DH())); + } + else + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s restart failed!\n"), _DH())); + } + // No need to react when an interface disappears, + // because mDNS always loop on all available interfaces. + })) + { + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s begin: could not add netif status callback\n"), _DH())); + } + } + else { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s begin: FAILED for '%s'!\n"), _DH(), (p_pcHostName ? : "-"));); } From 39622af0e33d1f24c960d23b06b8558e3fc73596 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 18 Jun 2020 19:42:16 +0200 Subject: [PATCH 065/152] ditto --- tools/sdk/lib/liblwip2-1460-feat.a | Bin 1592566 -> 1577124 bytes tools/sdk/lib/liblwip2-1460.a | Bin 1418632 -> 1402742 bytes tools/sdk/lib/liblwip2-536-feat.a | Bin 1592490 -> 1577044 bytes tools/sdk/lib/liblwip2-536.a | Bin 1418556 -> 1402666 bytes tools/sdk/lib/liblwip6-1460-feat.a | Bin 1920874 -> 1906288 bytes tools/sdk/lib/liblwip6-536-feat.a | Bin 1920798 -> 1906208 bytes tools/sdk/lwip2/builder | 2 +- 7 files changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/sdk/lib/liblwip2-1460-feat.a b/tools/sdk/lib/liblwip2-1460-feat.a index 4840eb4875a9739c2d2071c12e9b15465b5176d1..2a0016b7e7580665eff5009d6f90735fc7185308 100644 GIT binary patch delta 277546 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⪼R<o;A0c=dtiQNko*~#cRu8A!O6lufvXAs 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 a_%{A``lk6Y)Qf-rdD*$Q1p2kxoBTK5KQZ_K delta 289133 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 diff --git a/tools/sdk/lib/liblwip2-1460.a b/tools/sdk/lib/liblwip2-1460.a index 458a234143901649882142ff7cd049442f129c56..e426c70c5ee77dd9e45df878f3fd18e58deb7122 100644 GIT binary patch delta 248985 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�rn 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 delta 261501 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⁡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 R{`YLt@W(#J`6J5;{vVZB;)4JH diff --git a/tools/sdk/lib/liblwip2-536-feat.a b/tools/sdk/lib/liblwip2-536-feat.a index 05098cd31090e6fec7ff6b0aacb7163c76c235d6..3e635d404e4b01aa1778770776453a3b9b5b1e3e 100644 GIT binary patch delta 278170 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�yeH#g+t(S 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ΠIXI1xdcLG$W-dv7;lcm;`yR%Zc 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 E06b=hhX4Qo delta 288674 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 diff --git a/tools/sdk/lib/liblwip2-536.a b/tools/sdk/lib/liblwip2-536.a index e7c15646ca7c06e0c7958134cc039fa053d4112f..faaf4e564854f773338da8e2530ff01767654e1c 100644 GIT binary patch delta 248896 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 delta 261664 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%0DePwGWcC#KBUeF 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 bY(hrgqnFJ8g>~;HVSu;pwu}GG>)!o8P%Dx< diff --git a/tools/sdk/lib/liblwip6-1460-feat.a b/tools/sdk/lib/liblwip6-1460-feat.a index 8f9f42ca0c43f048faa02b5ee633147877783590..0e4896cd7475dc2f9b86a4f741b94f80ff80b13e 100644 GIT binary patch delta 358658 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øL0Zd|$++!3}$k<&Ry4xM9zc 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ⅅyRW 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 delta 366679 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�-pGA#rfI`v}Zb;u>jqQv(X0p_( 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ℜ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	>08fy0uHQ8{75ybo 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 diff --git a/tools/sdk/lib/liblwip6-536-feat.a b/tools/sdk/lib/liblwip6-536-feat.a index 592df0cbf66ed748d5d258d13061c17b67ab1619..aadc98a8bd301839d35aca4a64af099faeb55ef3 100644 GIT binary patch delta 359432 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Π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%0AXyv1s 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⪻z=%E?&7Che89!09qx!o{OTyc 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 delta 365928 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�gjof9gcbO4;jLh<P+{adz|RQp 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òjIa*j{0i=n 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 diff --git a/tools/sdk/lwip2/builder b/tools/sdk/lwip2/builder index 729700a31a..61b01638dd 160000 --- a/tools/sdk/lwip2/builder +++ b/tools/sdk/lwip2/builder @@ -1 +1 @@ -Subproject commit 729700a31a432a3a058d352a35613e25cc0e5b38 +Subproject commit 61b01638dde63088cbcdfe3c37ac036b75bf7a7e From 9f99c764d2f80a15fc1d6abcc2e07135a0c69a42 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 18 Jun 2020 19:55:37 +0200 Subject: [PATCH 066/152] use netif callback to restart mDNS --- .../LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index 18fa15c074..0ebd3acb1d 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -35,6 +35,7 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> +#include <LwipIntf.h> #include <time.h> // uses API MDNSApiVersion::LEAv2 @@ -62,6 +63,7 @@ #define DST_OFFSET 1 // CEST #define UPDATE_CYCLE (1 * 1000) // every second +#define START_AP_AFTER_MS 10000 //60000 // start AP after delay #define SERVICE_PORT 80 // HTTP port #ifndef STASSID @@ -186,8 +188,23 @@ void setup(void) { Serial.begin(115200); // Connect to WiFi network - WiFi.mode(WIFI_AP_STA); - WiFi.softAP(APSSID, APPSK); + + WiFi.persistent(false); + + // useless informative callback + if (!LwipIntf::stateUpCB([](netif* nif) + { + Serial.printf("New interface %c%c(%d) is up(%d)\n", + nif->name[0], + nif->name[1], + netif_get_index(nif), + netif_is_up(nif)); + })) + { + Serial.println("Error: could not add useless informative callback\n"); + } + + WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.println(""); @@ -246,4 +263,17 @@ void loop(void) { responder.announce(); } } + + static bool AP_started = false; + if (!AP_started && millis() > START_AP_AFTER_MS) + { + AP_started = true; + Serial.printf("Starting AP...\n"); + WiFi.mode(WIFI_AP_STA); + WiFi.softAP(APSSID, APPSK); + Serial.printf("AP started...(%s:%s, %s)\n", + WiFi.softAPSSID().c_str(), + WiFi.softAPPSK().c_str(), + WiFi.softAPIP().toString().c_str()); + } } From d50b15cf220e7afc22cfa085fc0b9fbd52b37e19 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 18 Jun 2020 19:57:12 +0200 Subject: [PATCH 067/152] ditto --- tools/sdk/lwip2/include/gluedebug.h | 8 ++++++-- tools/sdk/lwip2/include/lwip-git-hash.h | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/sdk/lwip2/include/gluedebug.h b/tools/sdk/lwip2/include/gluedebug.h index a53099744d..f7a1917799 100644 --- a/tools/sdk/lwip2/include/gluedebug.h +++ b/tools/sdk/lwip2/include/gluedebug.h @@ -38,9 +38,13 @@ #define HAS_PHY_CAPTURE 1 #ifdef __cplusplus -extern "C" +extern "C" { #endif -void (*phy_capture) (int netif_idx, const char* data, size_t len, int out, int success); +extern void (*phy_capture) (int netif_idx, const char* data, size_t len, int out, int success); +#ifdef __cplusplus +} +#endif + ///////////////////////////////////////////////////////////////////////////// #if ARDUINO diff --git a/tools/sdk/lwip2/include/lwip-git-hash.h b/tools/sdk/lwip2/include/lwip-git-hash.h index 8a40c5e20e..3535d51f7b 100644 --- a/tools/sdk/lwip2/include/lwip-git-hash.h +++ b/tools/sdk/lwip2/include/lwip-git-hash.h @@ -1,5 +1,5 @@ // generated by makefiles/make-lwip2-hash #ifndef LWIP_HASH_H #define LWIP_HASH_H -#define LWIP_HASH_STR "STABLE-2_1_2_RELEASE/glue:1.2-30-g92add50" +#define LWIP_HASH_STR "STABLE-2_1_2_RELEASE/glue:1.2-33-g61b0163" #endif // LWIP_HASH_H From 6b49de9c630a30560b2b4651471109a82576bfc4 Mon Sep 17 00:00:00 2001 From: hreintke <hreintke@tauri.nl> Date: Fri, 19 Jun 2020 11:32:06 +0200 Subject: [PATCH 068/152] Fix Announce Failure --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index f471999fa3..c321551f36 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1680,8 +1680,11 @@ bool clsLEAMDNSHost::_announce(bool p_bAnnounce, bool bResult = false; clsSendParameter sendParameter; + Serial.printf("Announce : %d\r\n", m_ProbeInformation.m_ProbingStatus); +#if 0 if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == m_ProbeInformation.m_ProbingStatus) || (clsProbeInformation_Base::enuProbingStatus::DoneFinally == m_ProbeInformation.m_ProbingStatus)) +#endif { bResult = true; @@ -1708,8 +1711,10 @@ bool clsLEAMDNSHost::_announce(bool p_bAnnounce, // Announce services (service type, name, SRV (location) and TXTs) for (clsService* pService : m_Services) { +#if 0 if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == pService->m_ProbeInformation.m_ProbingStatus) || (clsProbeInformation_Base::enuProbingStatus::DoneFinally == pService->m_ProbeInformation.m_ProbingStatus)) +#endif { pService->m_u32ReplyMask = (static_cast<uint32_t>(enuContentFlag::PTR_TYPE) | static_cast<uint32_t>(enuContentFlag::PTR_NAME) | From c90e9e2dc6df7a424e35cdd31fa73b0606e6419d Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 21 Jun 2020 16:50:00 +0200 Subject: [PATCH 069/152] allow user to select mDNS version before including ESP8266mDNS.h updated all examples using mDNS --- libraries/ArduinoOTA/ArduinoOTA.cpp | 1 + .../ArduinoOTA/examples/BasicOTA/BasicOTA.ino | 4 +- .../ArduinoOTA/examples/OTALeds/OTALeds.ino | 4 +- .../CaptivePortalAdvanced.ino | 4 +- .../Arduino_Wifi_AVRISP.ino | 4 +- .../SecureBearSSLUpdater.ino | 4 +- .../SecureHTTPSUpdater/SecureHTTPSUpdater.ino | 4 +- .../SecureWebUpdater/SecureWebUpdater.ino | 4 +- .../examples/WebUpdater/WebUpdater.ino | 4 +- .../AdvancedWebServer/AdvancedWebServer.ino | 2 + .../examples/FSBrowser/FSBrowser.ino | 4 +- .../ESP8266WebServer/examples/Graph/Graph.ino | 4 +- .../examples/HelloServer/HelloServer.ino | 2 + .../HelloServerBearSSL/HelloServerBearSSL.ino | 2 + .../HelloServerSecure/HelloServerSecure.ino | 2 + .../HttpAdvancedAuth/HttpAdvancedAuth.ino | 4 +- .../examples/HttpBasicAuth/HttpBasicAuth.ino | 4 +- .../examples/PathArgServer/PathArgServer.ino | 2 + .../examples/PostServer/PostServer.ino | 2 + .../ServerSentEvents/ServerSentEvents.ino | 4 +- .../examples/WebUpdate/WebUpdate.ino | 2 + .../LEAmDNS/TwoInterfaces/TwoInterfaces.ino | 149 ------------------ .../LEAmDNS/mDNS_Clock/mDNS_Clock.ino | 5 +- .../LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 2 + .../mDNS_ServiceMonitor.ino | 1 + .../mDNS_ServiceMonitor_v2/MSDN_V2.cpp | 1 + .../mDNS_ServiceMonitor_v2_test.ino | 2 + .../OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino | 4 +- .../mDNS-SD_Extended/mDNS-SD_Extended.ino | 2 + .../mDNS_Web_Server/mDNS_Web_Server.ino | 4 +- libraries/ESP8266mDNS/src/ESP8266mDNS.h | 37 +++-- .../ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp | 2 +- .../ESP8266mDNS/src/ESP8266mDNS_Legacy.h | 4 +- libraries/ESP8266mDNS/src/LEAmDNS.h | 2 - libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 2 - libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 4 + libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h | 2 - 37 files changed, 101 insertions(+), 189 deletions(-) delete mode 100644 libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino diff --git a/libraries/ArduinoOTA/ArduinoOTA.cpp b/libraries/ArduinoOTA/ArduinoOTA.cpp index 64e8397a2a..b27e3f9d3b 100644 --- a/libraries/ArduinoOTA/ArduinoOTA.cpp +++ b/libraries/ArduinoOTA/ArduinoOTA.cpp @@ -21,6 +21,7 @@ extern "C" { #include "include/UdpContext.h" #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) +//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #endif diff --git a/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino index ddc5629741..b7973d4517 100644 --- a/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino +++ b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino @@ -1,8 +1,10 @@ #include <ESP8266WiFi.h> -#include <ESP8266mDNS.h> #include <WiFiUdp.h> #include <ArduinoOTA.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino b/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino index 7d05074e15..9fe1a8798e 100644 --- a/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino +++ b/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino @@ -1,8 +1,10 @@ #include <ESP8266WiFi.h> -#include <ESP8266mDNS.h> #include <WiFiUdp.h> #include <ArduinoOTA.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino b/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino index 5f1f5020a1..2435ff9cfa 100644 --- a/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino +++ b/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino @@ -2,9 +2,11 @@ #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <DNSServer.h> -#include <ESP8266mDNS.h> #include <EEPROM.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + /* This example serves a "hello world" on a WLAN and a SoftAP at the same time. The SoftAP allow you to configure WLAN parameters at run time. They are not setup in the sketch but saved on EEPROM. diff --git a/libraries/ESP8266AVRISP/examples/Arduino_Wifi_AVRISP/Arduino_Wifi_AVRISP.ino b/libraries/ESP8266AVRISP/examples/Arduino_Wifi_AVRISP/Arduino_Wifi_AVRISP.ino index fdc34cff2b..362e0f1b7b 100644 --- a/libraries/ESP8266AVRISP/examples/Arduino_Wifi_AVRISP/Arduino_Wifi_AVRISP.ino +++ b/libraries/ESP8266AVRISP/examples/Arduino_Wifi_AVRISP/Arduino_Wifi_AVRISP.ino @@ -1,8 +1,10 @@ #include <SPI.h> #include <ESP8266WiFi.h> -#include <ESP8266mDNS.h> #include <ESP8266AVRISP.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/ESP8266HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino b/libraries/ESP8266HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino index a2514e171d..534643a8e1 100644 --- a/libraries/ESP8266HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino +++ b/libraries/ESP8266HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino @@ -16,9 +16,11 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServerSecure.h> -#include <ESP8266mDNS.h> #include <ESP8266HTTPUpdateServer.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/ESP8266HTTPUpdateServer/examples/SecureHTTPSUpdater/SecureHTTPSUpdater.ino b/libraries/ESP8266HTTPUpdateServer/examples/SecureHTTPSUpdater/SecureHTTPSUpdater.ino index a28d48de81..b0d0d1f70d 100644 --- a/libraries/ESP8266HTTPUpdateServer/examples/SecureHTTPSUpdater/SecureHTTPSUpdater.ino +++ b/libraries/ESP8266HTTPUpdateServer/examples/SecureHTTPSUpdater/SecureHTTPSUpdater.ino @@ -49,13 +49,15 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServerSecure.h> -#include <ESP8266mDNS.h> #include <ESP8266HTTPUpdateServer.h> #include <WiFiServerSecure.h> #include <WiFiServerSecureAxTLS.h> #include <WiFiClientSecure.h> #include <WiFiClientSecureAxTLS.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + #pragma GCC diagnostic pop #ifndef STASSID diff --git a/libraries/ESP8266HTTPUpdateServer/examples/SecureWebUpdater/SecureWebUpdater.ino b/libraries/ESP8266HTTPUpdateServer/examples/SecureWebUpdater/SecureWebUpdater.ino index 11e23a929d..4e73983cf8 100644 --- a/libraries/ESP8266HTTPUpdateServer/examples/SecureWebUpdater/SecureWebUpdater.ino +++ b/libraries/ESP8266HTTPUpdateServer/examples/SecureWebUpdater/SecureWebUpdater.ino @@ -5,9 +5,11 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> -#include <ESP8266mDNS.h> #include <ESP8266HTTPUpdateServer.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/ESP8266HTTPUpdateServer/examples/WebUpdater/WebUpdater.ino b/libraries/ESP8266HTTPUpdateServer/examples/WebUpdater/WebUpdater.ino index fea3c4023a..cee1b69c03 100644 --- a/libraries/ESP8266HTTPUpdateServer/examples/WebUpdater/WebUpdater.ino +++ b/libraries/ESP8266HTTPUpdateServer/examples/WebUpdater/WebUpdater.ino @@ -5,9 +5,11 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> -#include <ESP8266mDNS.h> #include <ESP8266HTTPUpdateServer.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino b/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino index 2fc8508ca0..92cc76044d 100644 --- a/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino +++ b/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino @@ -31,6 +31,8 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> + +//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino b/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino index f6aff52c7d..fe3b50f2c4 100644 --- a/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino +++ b/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino @@ -40,9 +40,11 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> -#include <ESP8266mDNS.h> #include <SPI.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + #ifdef INCLUDE_FALLBACK_INDEX_HTM #include "extras/index_htm.h" #endif diff --git a/libraries/ESP8266WebServer/examples/Graph/Graph.ino b/libraries/ESP8266WebServer/examples/Graph/Graph.ino index 4f73455676..c17b043f18 100644 --- a/libraries/ESP8266WebServer/examples/Graph/Graph.ino +++ b/libraries/ESP8266WebServer/examples/Graph/Graph.ino @@ -33,9 +33,11 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> -#include <ESP8266mDNS.h> #include <SPI.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + #if defined USE_SPIFFS #include <FS.h> FS* fileSystem = &SPIFFS; diff --git a/libraries/ESP8266WebServer/examples/HelloServer/HelloServer.ino b/libraries/ESP8266WebServer/examples/HelloServer/HelloServer.ino index 1335c347af..5f902d1d07 100644 --- a/libraries/ESP8266WebServer/examples/HelloServer/HelloServer.ino +++ b/libraries/ESP8266WebServer/examples/HelloServer/HelloServer.ino @@ -1,6 +1,8 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> + +//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino b/libraries/ESP8266WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino index 4b786dc1a5..daa5d8f381 100644 --- a/libraries/ESP8266WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino +++ b/libraries/ESP8266WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino @@ -12,6 +12,8 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServerSecure.h> + +//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266WebServer/examples/HelloServerSecure/HelloServerSecure.ino b/libraries/ESP8266WebServer/examples/HelloServerSecure/HelloServerSecure.ino index 87c34ccb58..a9b21d472d 100644 --- a/libraries/ESP8266WebServer/examples/HelloServerSecure/HelloServerSecure.ino +++ b/libraries/ESP8266WebServer/examples/HelloServerSecure/HelloServerSecure.ino @@ -44,6 +44,8 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServerSecure.h> + +//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266WebServer/examples/HttpAdvancedAuth/HttpAdvancedAuth.ino b/libraries/ESP8266WebServer/examples/HttpAdvancedAuth/HttpAdvancedAuth.ino index 857048cf0b..0b175c05bf 100644 --- a/libraries/ESP8266WebServer/examples/HttpAdvancedAuth/HttpAdvancedAuth.ino +++ b/libraries/ESP8266WebServer/examples/HttpAdvancedAuth/HttpAdvancedAuth.ino @@ -5,10 +5,12 @@ */ #include <ESP8266WiFi.h> -#include <ESP8266mDNS.h> #include <ArduinoOTA.h> #include <ESP8266WebServer.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/ESP8266WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino b/libraries/ESP8266WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino index 7c06637caf..26899ea71f 100644 --- a/libraries/ESP8266WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino +++ b/libraries/ESP8266WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino @@ -1,8 +1,10 @@ #include <ESP8266WiFi.h> -#include <ESP8266mDNS.h> #include <ArduinoOTA.h> #include <ESP8266WebServer.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino index dc998986e5..0d37972f51 100644 --- a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino +++ b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino @@ -1,6 +1,8 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> + +//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #include <uri/UriBraces.h> diff --git a/libraries/ESP8266WebServer/examples/PostServer/PostServer.ino b/libraries/ESP8266WebServer/examples/PostServer/PostServer.ino index da1703807a..5a963bd131 100644 --- a/libraries/ESP8266WebServer/examples/PostServer/PostServer.ino +++ b/libraries/ESP8266WebServer/examples/PostServer/PostServer.ino @@ -1,6 +1,8 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> + +//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266WebServer/examples/ServerSentEvents/ServerSentEvents.ino b/libraries/ESP8266WebServer/examples/ServerSentEvents/ServerSentEvents.ino index 77ae1e958e..3c35dc3dd9 100644 --- a/libraries/ESP8266WebServer/examples/ServerSentEvents/ServerSentEvents.ino +++ b/libraries/ESP8266WebServer/examples/ServerSentEvents/ServerSentEvents.ino @@ -37,9 +37,11 @@ extern "C" { #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> -#include <ESP8266mDNS.h> #include <Ticker.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino b/libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino index 17646fd172..e71d771890 100644 --- a/libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino +++ b/libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino @@ -5,6 +5,8 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> + +//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino deleted file mode 100644 index f561b867f6..0000000000 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/TwoInterfaces/TwoInterfaces.ino +++ /dev/null @@ -1,149 +0,0 @@ - -#include <Arduino.h> -#include <PolledTimeout.h> - -#include <ESP8266mDNS.h> -#include <ESP8266WebServer.h> - -#ifndef STASSID -#define STASSID "ssid" -#define STAPSK "12345678" -#endif - -#ifndef APSSID -#define APSSID "espap" -#define APPSK "12345678" -#endif - -// uses API MDNSApiVersion::LEAv2 - -clsMDNSHost mDNSHost_AP; -clsMDNSHost mDNSHost_STA; -ESP8266WebServer server(80); - -void connectToWiFi(const char* p_pcSSID, - const char* p_pcPWD, - uint32_t p_u32Timeout = 20) { - WiFi.begin(p_pcSSID, p_pcPWD); - Serial.println(""); - - // Wait for connection - uint8 u8Tries = p_u32Timeout; - while ((WiFi.status() != WL_CONNECTED) && - (u8Tries--)) { - delay(500); - Serial.print("."); - } - if (WiFi.status() == WL_CONNECTED) { - Serial.println(""); - Serial.print("Connected to "); - Serial.println(p_pcSSID); - Serial.print("IP address: "); - Serial.println(WiFi.localIP()); - } else { - Serial.printf("FAILED to connect to '%s'!\n", p_pcSSID); - } -} - -void setup(void) { - Serial.begin(115200); - Serial.setDebugOutput(false); - delay(2000); - Serial.printf("\nStart\n"); - - // Setup WiFi and AP - WiFi.setAutoConnect(false); - WiFi.mode(WIFI_AP_STA); - WiFi.softAP(APSSID, APPSK); - Serial.print("Created AP "); - Serial.println("ESP8266"); - Serial.print("AP-IP address: "); - Serial.println(WiFi.softAPIP()); - - if (mDNSHost_AP.begin("ESP8266", WIFI_AP, [](clsMDNSHost & p_rMDNSHost, - const char* p_pcDomainName, - bool p_bProbeResult)->void { - Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); - - // Unattended added service - p_rMDNSHost.addService(0, "http", "tcp", 80); - })) { - Serial.println("mDNS-AP started"); - } else { - Serial.println("FAILED to start mDNS-AP"); - } - - // Connect to WiFi network, with WRONG password (timeout 5 seconds) - // (good password will be given in `loop()`) - connectToWiFi(STASSID, "WRONG_PW", 5); - - if (mDNSHost_STA.begin("esp8266", WIFI_STA, [](clsMDNSHost & p_rMDNSHost, - const char* p_pcDomainName, - bool p_bProbeResult)->void { - Serial.printf("mDNSHost_STA::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); - if (p_bProbeResult) { - p_rMDNSHost.addService("LEA_Weather", "http", "tcp", 80, [](clsMDNSHost::clsService & p_rService, - const char* p_pcInstanceName, - bool p_bProbeResult)->void { - Serial.printf("mDNSHost_STA::HTTP-Service::ProbeResultCallback: '%s' is %s\n", p_pcInstanceName, (p_bProbeResult ? "FREE" : "USED!")); - if (p_bProbeResult) { - if (!p_rService.addServiceTxt("path", "/")) { - Serial.println("FAILED to add service TXT item!"); - } - p_rService.setDynamicServiceTxtCallback([](clsMDNSHost::clsService & p_rService)->void { - Serial.printf("mDNSHost_STA::HTTP-Service::DynamicTXTCallback\n"); - - p_rService.addDynamicServiceTxt("user", "admin"); - static uint32_t u32Counter = 0; - p_rService.addDynamicServiceTxt("cnt", ++u32Counter); - }); - } else { - if (p_rService.indexInstanceName()) { - Serial.printf("Changed service instance name to '%s'\n", p_rService.instanceName()); - } else { - Serial.println("FAILED to index service instance name!"); - } - } - }); - - // Unattended added service - p_rMDNSHost.addService("MQTTInstance", "mqtt", "tcp", 1883); - } else { - p_rMDNSHost.indexHostName(); - } - })) { - Serial.println("mDNS-STA started"); - } else { - Serial.println("FAILED to start mDNS-STA"); - } - - // Non-synchronized added service - mDNSHost_STA.addService(0, "test", "tcp", 999); - - // Setup HTTP server - server.on("/", [](void) { - Serial.println("server.on"); - server.send(200, "text/plain", "test"); - }); - server.begin(); - Serial.println("HTTP server started"); -} - -void loop(void) { - server.handleClient(); - mDNSHost_AP.update(); - mDNSHost_STA.update(); - - static esp8266::polledTimeout::oneShotMs timer2(esp8266::polledTimeout::oneShotMs::alwaysExpired); - if (timer2) { - Serial.println("FIX PASSWORD"); - connectToWiFi(STASSID, STAPSK); - - timer2.reset(esp8266::polledTimeout::oneShotMs::neverExpires); - } -} - - - - - diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino index 8ea7237f54..c657d49bdd 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino @@ -49,8 +49,11 @@ 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. */ -#include <ESP8266mDNS.h> #include <PolledTimeout.h> + +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + /* Global defines and vars */ diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index 0ebd3acb1d..c8b908c87d 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -52,7 +52,9 @@ 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. */ +#define MDNS2_EXPERIMENTAL #include <ESP8266mDNS.h> + #include <PolledTimeout.h> /* Global defines and vars diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor/mDNS_ServiceMonitor.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor/mDNS_ServiceMonitor.ino index 98269fb48e..e7a293f25c 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor/mDNS_ServiceMonitor.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor/mDNS_ServiceMonitor.ino @@ -46,6 +46,7 @@ 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. */ +//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> /* diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp index dd87b7d14e..e0b630da83 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp @@ -46,6 +46,7 @@ 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. */ +#define MDNS2_EXPERIMENTAL #include <ESP8266mDNS.h> #include "LocalDefines.h" #include "Netdump.h" diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino index 9ca8b10f60..569fe35a27 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino @@ -62,6 +62,8 @@ Netdump nd; 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. */ + +#define MDNS2_EXPERIMENTAL #include <ESP8266mDNS.h> //#include "LocalDefines.h" //#include "Netdump.h" diff --git a/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino b/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino index 34ffcc5c89..a39518efa3 100644 --- a/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino +++ b/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino @@ -24,12 +24,14 @@ // includes #include <ESP8266WiFi.h> -#include <ESP8266mDNS.h> #include <WiFiUdp.h> #include <FS.h> #include <LittleFS.h> #include <ArduinoOTA.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + /** @brief mDNS and OTA Constants diff --git a/libraries/ESP8266mDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino b/libraries/ESP8266mDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino index fda2fe6562..9b180fcc2d 100644 --- a/libraries/ESP8266mDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino +++ b/libraries/ESP8266mDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino @@ -10,6 +10,8 @@ */ #include <ESP8266WiFi.h> + +//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino b/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino index 7560864ce1..66a10b4c5a 100644 --- a/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino +++ b/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino @@ -17,9 +17,11 @@ #include <ESP8266WiFi.h> -#include <ESP8266mDNS.h> #include <WiFiClient.h> +//#define MDNS2_EXPERIMENTAL_V1COMPAT +#include <ESP8266mDNS.h> + #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index d5f73d75ab..d18bc86bc5 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -42,22 +42,31 @@ */ -enum class MDNSApiVersion { Legacy, LEA, LEAv2Compat, LEAv2 }; +// mDNS on esp8266 Arduino, 4 available versions, select one with a define +// to add before `#include <ESP8266mDNS>` prior `#include <ESP8266mDNS.h>`: +// +// - original (default until core-2.4.2): add `#define MDNS_ORIGINAL` +// - default LEAmDNS (v1, from core-2.5.0 to core 2.7.2) (nothing to add) +// - LEAmDNSv2 with V1 API compatibility: add `#define MDNS2_EXPERIMENTAL_V1COMPAT` +// - LEAmDNSv2, new API: add `#define MDNS2_EXPERIMENTAL` -#include "ESP8266mDNS_Legacy.h" // Legacy -#include "LEAmDNS.h" // LEA -#include "LEAmDNS2_Legacy.h" // LEAv2Compat - replacement for LEA using v2 -#include "LEAmDNS2Host.h" // LEAv2 - API updated +#if defined(MDNS_ORIGINAL) +#include "ESP8266mDNS_Legacy.h" -// clsMDNSHost replaces MDNSResponder in LEAv2 -using clsMDNSHost = esp8266::experimental::clsLEAMDNSHost; +#elif defined(MDNS2_EXPERIMENTAL_V1COMPAT) +#include "LEAmDNS2_Legacy.h" +using MDNSResponder = experimental::MDNSImplementation::clsLEAMDNSHost_Legacy; -#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) -// Maps the implementation to use to the global namespace type -//using MDNSResponder = Legacy_MDNSResponder::MDNSResponder; // Legacy -//using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA -//using MDNSResponder = experimental::MDNSImplementation::clsLEAMDNSHost_Legacy; // LEAv2Compat -using MDNSResponder = clsMDNSHost; // LEAv2 +#elif defined(MDNS2_EXPERIMENTAL) +#include "LEAmDNS2Host.h" +using MDNSResponder = esp8266::experimental::clsLEAMDNSHost; + +#else // default +#include "LEAmDNS.h" +using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; +#endif // version selection + +#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) extern MDNSResponder MDNS; -#endif +#endif // global instance diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp b/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp index 8791195523..f7fe8c9030 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp @@ -38,7 +38,7 @@ #define LWIP_OPEN_SRC #endif -#include "ESP8266mDNS.h" +#include <ESP8266mDNS_Legacy.h> #include <functional> #include "debug.h" diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h b/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h index 0a66a7fd32..70bfd58e23 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h @@ -43,7 +43,7 @@ #ifndef ESP8266MDNS_LEGACY_H #define ESP8266MDNS_LEGACY_H -#include "ESP8266WiFi.h" +#include "LEAmDNS2Host.h" #include "WiFiUdp.h" //this should be defined at build time @@ -66,8 +66,6 @@ class MDNSResponder { public: - static constexpr auto ApiVersion = MDNSApiVersion::Legacy; - MDNSResponder(); ~MDNSResponder(); bool begin(const char* hostName); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS.h b/libraries/ESP8266mDNS/src/LEAmDNS.h index e10080adf3..27329bc5cb 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS.h @@ -173,8 +173,6 @@ class MDNSResponder public: /* INTERFACE */ - static constexpr auto ApiVersion = MDNSApiVersion::LEA; - MDNSResponder(void); virtual ~MDNSResponder(void); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 88d403baa8..81510e2bb0 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -274,8 +274,6 @@ class clsLEAMDNSHost public: - static constexpr auto ApiVersion = MDNSApiVersion::LEAv2; - /** clsServiceTxt */ diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index ba5c6bd9cd..3dde731c6d 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -801,6 +801,9 @@ clsLEAMDNSHost_Legacy::hMDNSServiceQuery clsLEAMDNSHost_Legacy::installServiceQu { std::list<clsLEAMDNSHost::clsQuery*> queries; + (void)p_pcService; + (void)p_pcProtocol; + (void)p_fnCallback; /*clsLEAMDNSHost::clsQuery* pQuery =*/ // hostInformation.m_pHost->installServiceQuery(p_pcService, p_pcProtocol, [this, p_fnCallback](const clsLEAMDNSHost::clsQuery& /*p_Query*/, // const clsLEAMDNSHost::clsQuery::clsAnswerAccessor & p_AnswerAccessor, @@ -813,6 +816,7 @@ clsLEAMDNSHost_Legacy::hMDNSServiceQuery clsLEAMDNSHost_Legacy::installServiceQu // } // }, &queries); +///XXX Aways false if (queries.size()) { if (!hResult) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h index f78245161f..b0ace4d371 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h @@ -129,8 +129,6 @@ class clsLEAMDNSHost_Legacy public: - static constexpr auto ApiVersion = MDNSApiVersion::LEAv2Compat; - /* INTERFACE */ clsLEAMDNSHost_Legacy(void); virtual ~clsLEAMDNSHost_Legacy(void); From 0df1d3bc18a57cfba20280553eace2a44c763c2b Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 21 Jun 2020 16:54:03 +0200 Subject: [PATCH 070/152] typo --- libraries/ESP8266mDNS/src/ESP8266mDNS.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index d18bc86bc5..2ed2ea27d6 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -43,12 +43,12 @@ */ // mDNS on esp8266 Arduino, 4 available versions, select one with a define -// to add before `#include <ESP8266mDNS>` prior `#include <ESP8266mDNS.h>`: +// to add before `#include <ESP8266mDNS>`: // -// - original (default until core-2.4.2): add `#define MDNS_ORIGINAL` -// - default LEAmDNS (v1, from core-2.5.0 to core 2.7.2) (nothing to add) -// - LEAmDNSv2 with V1 API compatibility: add `#define MDNS2_EXPERIMENTAL_V1COMPAT` -// - LEAmDNSv2, new API: add `#define MDNS2_EXPERIMENTAL` +// - original (default until core-2.4.2): add `#define MDNS_ORIGINAL` +// - LEAmDNS (v1, from core-2.5.0 to core 2.7.2): default +// - LEAmDNSv2, with V1 API compatibility: add `#define MDNS2_EXPERIMENTAL_V1COMPAT` +// - LEAmDNSv2, new API: add `#define MDNS2_EXPERIMENTAL` #if defined(MDNS_ORIGINAL) #include "ESP8266mDNS_Legacy.h" From 411a9412aa467e65561449e837ec6089430e3fa7 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 21 Jun 2020 17:38:15 +0200 Subject: [PATCH 071/152] fix namespace imports --- libraries/ESP8266mDNS/src/ESP8266mDNS.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index 2ed2ea27d6..ae580fd4b8 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -59,7 +59,8 @@ using MDNSResponder = experimental::MDNSImplementation::clsLEAMDNSHost_Legacy; #elif defined(MDNS2_EXPERIMENTAL) #include "LEAmDNS2Host.h" -using MDNSResponder = esp8266::experimental::clsLEAMDNSHost; +using clsMDNSHost = esp8266::experimental::clsLEAMDNSHost; +using MDNSResponder = clsMDNSHost; #else // default #include "LEAmDNS.h" From 7e739ff5760503aa36a17146241175711fc9a41e Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 21 Jun 2020 17:38:59 +0200 Subject: [PATCH 072/152] reimport clsLEAMDNSHost_Legacy::installServiceQuery() from initial sources --- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 47 +++++-------------- 1 file changed, 13 insertions(+), 34 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 3dde731c6d..01fe26b33e 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -799,45 +799,24 @@ clsLEAMDNSHost_Legacy::hMDNSServiceQuery clsLEAMDNSHost_Legacy::installServiceQu for (stcHostInformation& hostInformation : m_HostInformations) { - std::list<clsLEAMDNSHost::clsQuery*> queries; - - (void)p_pcService; - (void)p_pcProtocol; - (void)p_fnCallback; - /*clsLEAMDNSHost::clsQuery* pQuery =*/ -// hostInformation.m_pHost->installServiceQuery(p_pcService, p_pcProtocol, [this, p_fnCallback](const clsLEAMDNSHost::clsQuery& /*p_Query*/, -// const clsLEAMDNSHost::clsQuery::clsAnswerAccessor & p_AnswerAccessor, -// clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item -// bool p_bSetContent)->void -// { -// if (p_fnCallback) // void(const stcMDNSServiceInfo& p_MDNSServiceInfo, MDNSResponder::AnswerType p_AnswerType, bool p_bSetContent) -// { -// p_fnCallback(stcMDNSServiceInfo(p_AnswerAccessor), _answerFlagsToAnswerType(p_QueryAnswerTypeFlags), p_bSetContent); -// } -// }, &queries); - -///XXX Aways false - if (queries.size()) + clsLEAMDNSHost::clsQuery* pQuery = hostInformation.m_pHost->installServiceQuery(p_pcService, p_pcProtocol, [this, p_fnCallback](const clsLEAMDNSHost::clsQuery& /*p_Query*/, + const clsLEAMDNSHost::clsQuery::clsAnswerAccessor & p_AnswerAccessor, + clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item + bool p_bSetContent)->void + { + if (p_fnCallback) // void(const stcMDNSServiceInfo& p_MDNSServiceInfo, MDNSResponder::AnswerType p_AnswerType, bool p_bSetContent) + { + p_fnCallback(stcMDNSServiceInfo(p_AnswerAccessor), _answerFlagsToAnswerType(p_QueryAnswerTypeFlags), p_bSetContent); + } + }); + if (pQuery) { if (!hResult) { - // - hMDNSServiceQuery handle is 'const void*' - // used to retrieve pQuery when updating or removing. - - // - unexplained - before multi interface change: - // there is a loop, only the first is returned, why ? - // Store first query as result and key - //hResult = (hMDNSServiceQuery)pQuery; <- before netif, only the first query is returned - - // - netif transformation: even more returned values (a list per loop), - // still, only the first handle is returned. - hResult = (hMDNSServiceQuery) * queries.begin(); // take the first + hResult = (hMDNSServiceQuery)pQuery; } - // this was overwritten ? - //hostInformation.m_HandleToPtr[hResult] = pQuery; - // ... overwritten with only the first query - hostInformation.m_HandleToPtr[hResult] = *queries.begin(); + hostInformation.m_HandleToPtr[hResult] = pQuery; } } return hResult; From 2cfef0427f471b6b77b419c89ba0d779ccadbded Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 21 Jun 2020 22:40:14 +0200 Subject: [PATCH 073/152] clsMDNSHost -> clsLEAMDNSHost --- .../LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 20 +++--- .../mDNS_ServiceMonitor.ino | 1 - .../LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.h | 22 ------- ...MSDN_V2.cpp => mDNS_ServiceMonitor_v2.ino} | 37 ++++++----- .../mDNS_ServiceMonitor_v2_test.ino | 62 +++++++++---------- libraries/ESP8266mDNS/src/ESP8266mDNS.h | 6 +- 6 files changed, 64 insertions(+), 84 deletions(-) delete mode 100644 libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.h rename libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/{MSDN_V2.cpp => mDNS_ServiceMonitor_v2.ino} (93%) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index c8b908c87d..43c5c6e8b5 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -1,7 +1,7 @@ /* ESP8266 mDNS responder clock - This example demonstrates two features of the LEA clsMDNSHost: + This example demonstrates two features of the LEA clsLEAMDNSHost: 1. The host and service domain negotiation process that ensures the uniqueness of the finally choosen host and service domain name. 2. The dynamic MDNS service TXT feature @@ -41,12 +41,12 @@ // uses API MDNSApiVersion::LEAv2 /* - Include the clsMDNSHost (the library needs to be included also) - As LEA clsMDNSHost is experimantal in the ESP8266 environment currently, the - legacy clsMDNSHost is defaulted in th include file. - There are two ways to access LEA clsMDNSHost: + Include the clsLEAMDNSHost (the library needs to be included also) + As LEA clsLEAMDNSHost is experimantal in the ESP8266 environment currently, the + legacy clsLEAMDNSHost is defaulted in th include file. + There are two ways to access LEA clsLEAMDNSHost: 1. Prepend every declaration and call to global declarations or functions with the namespace, like: - 'LEAmDNS::clsMDNSHost::hMDNSService hMDNSService;' + 'LEAmDNS::clsLEAMDNSHost::hMDNSService hMDNSService;' This way is used in the example. But be careful, if the namespace declaration is missing somewhere, the call might go to the legacy implementation... 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. @@ -81,9 +81,9 @@ const char* ssid = STASSID; const char* password = STAPSK; -clsMDNSHost responder; // MDNS responder +clsLEAMDNSHost responder; // MDNS responder bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain -clsMDNSHost::clsService* hMDNSService = 0; // The handle of the clock service in the MDNS responder +clsLEAMDNSHost::clsService* hMDNSService = 0; // The handle of the clock service in the MDNS responder // HTTP server at port 'SERVICE_PORT' will respond to HTTP requests ESP8266WebServer server(SERVICE_PORT); @@ -147,7 +147,7 @@ bool setStationHostname(const char* p_pcHostname) { This can be triggered by calling responder.announce(). */ -void MDNSDynamicServiceTxtCallback(const clsMDNSHost::hMDNSService& p_hService) { +void MDNSDynamicServiceTxtCallback(const clsLEAMDNSHost::hMDNSService& p_hService) { Serial.println("MDNSDynamicServiceTxtCallback"); if (hMDNSService == &p_hService) { @@ -226,7 +226,7 @@ void setup(void) { // Setup MDNS responder // Init the (currently empty) host domain string with 'esp8266' - if (responder.begin("leamdnsv2", [](clsMDNSHost & p_rMDNSHost, + if (responder.begin("leamdnsv2", [](clsLEAMDNSHost & p_rMDNSHost, const char* p_pcDomainName, bool p_bProbeResult)->void { Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor/mDNS_ServiceMonitor.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor/mDNS_ServiceMonitor.ino index e7a293f25c..98269fb48e 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor/mDNS_ServiceMonitor.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor/mDNS_ServiceMonitor.ino @@ -46,7 +46,6 @@ 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. */ -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> /* diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.h b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.h deleted file mode 100644 index 62ca01f6ab..0000000000 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.h +++ /dev/null @@ -1,22 +0,0 @@ -// Only modify this file to include -// - function definitions (prototypes) -// - include files -// - extern variable definitions -// In the appropriate section - -#ifndef _MSDN_V2_H_ -#define _MSDN_V2_H_ -#include "Arduino.h" -//add your includes for the project MSDN_V2 here - - -//end of add your includes here - - -//add your function definitions for the project MSDN_V2 here - - - - -//Do not add code below this line -#endif /* _MSDN_V2_H_ */ diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino similarity index 93% rename from libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp rename to libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino index e0b630da83..6bb8161a66 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/MSDN_V2.cpp +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino @@ -29,6 +29,15 @@ */ +#ifndef STASSID +#define STASSID "ssid" +#define STAPSK "psk" +#endif + +#ifndef APSSID +#define APSSID "esp8266" +//#define APPSK "psk" +#endif #include <ESP8266WiFi.h> #include <WiFiClient.h> @@ -48,25 +57,23 @@ */ #define MDNS2_EXPERIMENTAL #include <ESP8266mDNS.h> -#include "LocalDefines.h" -#include "Netdump.h" -using namespace NetCapture; + /* Global defines and vars */ -#define SERVICE_PORT 80 // HTTP port +#define SERVICE_PORT 80 // HTTP port char* pcHostDomain = 0; // Negociated host domain bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain MDNSResponder::clsService* hMDNSService = 0; // The handle of the http service in the MDNS responder -MDNSResponder::clsQuery* hMDNSServiceQuery = 0; // The handle of the 'http.tcp' service query in the MDNS responder +MDNSResponder::clsQuery* hMDNSServiceQuery = 0; // The handle of the 'http.tcp' service query in the MDNS responder const String cstrNoHTTPServices = "Currently no 'http.tcp' services in the local network!<br/>"; String strHTTPServices = cstrNoHTTPServices; // HTTP server at port 'SERVICE_PORT' will respond to HTTP requests -ESP8266WebServer server(SERVICE_PORT); +ESP8266WebServer server(SERVICE_PORT); /* @@ -88,6 +95,8 @@ void MDNSServiceQueryCallback(const MDNSResponder::clsQuery& p_Query, MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, bool p_bSetContent) { + (void)p_Query; + String answerInfo; switch (p_QueryAnswerTypeFlags) { case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain): @@ -124,6 +133,7 @@ void MDNSServiceQueryCallback(const MDNSResponder::clsQuery& p_Query, void serviceProbeResult(MDNSResponder::clsService& p_rMDNSService, const char* p_pcInstanceName, bool p_bProbeResult) { + (void)p_rMDNSService; Serial.printf("MDNSServiceProbeResultCallback: Service %s probe %s\n", p_pcInstanceName, (p_bProbeResult ? "succeeded." : "failed!")); } @@ -138,7 +148,7 @@ void serviceProbeResult(MDNSResponder::clsService& p_rMDNSService, */ -void hostProbeResult(clsMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bProbeResult) { +void hostProbeResult(clsLEAMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bProbeResult) { Serial.printf("MDNSHostProbeResultCallback: Host domain '%s.local' is %s\n", p_pcDomainName.c_str(), (p_bProbeResult ? "free" : "already USED!")); @@ -232,21 +242,17 @@ void handleHTTPRequest() { Serial.println("Done with request"); } -//Netdump nd(Netdump::interface::LWIP); - - /* setup */ void setup(void) { Serial.begin(115200); -// nd.printDump(Serial, Packet::PacketDetail::NONE, [](const Packet& p){return(p.getInOut() && p.isMDNS());}); Serial.setDebugOutput(false); // Connect to WiFi network WiFi.mode(WIFI_AP_STA); - WiFi.softAP("Soft1"); - WiFi.begin(ssid, password); + WiFi.softAP(APSSID); + WiFi.begin(STASSID, STAPSK); Serial.println(""); // Wait for connection @@ -256,7 +262,7 @@ void setup(void) { } Serial.println(""); Serial.print("Connected to "); - Serial.println(ssid); + Serial.println(STASSID); Serial.print("IP address: "); Serial.println(WiFi.localIP()); @@ -290,6 +296,3 @@ void loop(void) { // Allow MDNS processing MDNS.update(); } - - - diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino index 569fe35a27..6a7f483624 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino @@ -51,12 +51,12 @@ Netdump nd; /* - Include the clsMDNSHost (the library needs to be included also) - As LEA clsMDNSHost is experimantal in the ESP8266 environment currently, the - legacy clsMDNSHost is defaulted in th include file. - There are two ways to access LEA clsMDNSHost: + Include the clsLEAMDNSHost (the library needs to be included also) + As LEA clsLEAMDNSHost is experimantal in the ESP8266 environment currently, the + legacy clsLEAMDNSHost is defaulted in th include file. + There are two ways to access LEA clsLEAMDNSHost: 1. Prepend every declaration and call to global declarations or functions with the namespace, like: - 'LEAmDNS:clsMDNSHost::hMDNSService hMDNSService;' + 'LEAmDNS:clsLEAMDNSHost::hMDNSService hMDNSService;' This way is used in the example. But be careful, if the namespace declaration is missing somewhere, the call might go to the legacy implementation... 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. @@ -72,14 +72,14 @@ Netdump nd; Global defines and vars */ -clsMDNSHost MDNSv2; +clsLEAMDNSHost MDNSv2; #define SERVICE_PORT 80 // HTTP port char* pcHostDomain = 0; // Negociated host domain bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain -clsMDNSHost::clsService* hMDNSService = 0; // The handle of the sapuducu service in the MDNS responder -clsMDNSHost::clsQuery* hMDNSServiceQuery = 0; // The handle of the 'espclk.tcp' service query in the MDNS responder +clsLEAMDNSHost::clsService* hMDNSService = 0; // The handle of the sapuducu service in the MDNS responder +clsLEAMDNSHost::clsQuery* hMDNSServiceQuery = 0; // The handle of the 'espclk.tcp' service query in the MDNS responder const String cstrNoHTTPServices = "Currently no 'http.tcp' services in the local network!<br/>"; String strHTTPServices = cstrNoHTTPServices; @@ -103,30 +103,30 @@ bool setStationHostname(const char* p_pcHostname) return false; } -void MDNSServiceQueryCallback(const clsMDNSHost::clsQuery& p_Query, - const clsMDNSHost::clsQuery::clsAnswer& p_Answer, - clsMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, +void MDNSServiceQueryCallback(const clsLEAMDNSHost::clsQuery& p_Query, + const clsLEAMDNSHost::clsQuery::clsAnswer& p_Answer, + clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, bool p_bSetContent) { Serial.printf("CB MDNSServiceQueryCallback\n"); String answerInfo; - clsMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType mask = 0; - if (p_QueryAnswerTypeFlags & (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain) + clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType mask = 0; + if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain) { answerInfo += "(ServiceDomain "; answerInfo += p_Answer.m_ServiceDomain.c_str(); answerInfo += ")"; - mask |= (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain; + mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain; } - if (p_QueryAnswerTypeFlags & (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort) + if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort) { answerInfo += "(HostDomainAndPort "; answerInfo += p_Answer.m_HostDomain.c_str(); answerInfo += ")"; - mask |= (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort; + mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort; } - if (p_QueryAnswerTypeFlags & (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address) + if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address) { answerInfo += "(IP4Address "; for (auto ip : p_Answer.m_IPv4Addresses) @@ -135,10 +135,10 @@ void MDNSServiceQueryCallback(const clsMDNSHost::clsQuery& p_Query, answerInfo += ip->m_IPAddress.toString(); } answerInfo += ")"; - mask |= (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address; + mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address; } #ifdef MDNS_IPV6_SUPPORT - if (p_QueryAnswerTypeFlags & (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address) + if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address) { answerInfo += "(IP6Address "; for (auto ip : p_Answer.m_IPv6Addresses) @@ -147,10 +147,10 @@ void MDNSServiceQueryCallback(const clsMDNSHost::clsQuery& p_Query, answerInfo += ip->m_IPAddress.toString(); } answerInfo += ")"; - mask |= (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address; + mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address; } #endif // MDNS_IPV6_SUPPORT - if (p_QueryAnswerTypeFlags & (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts) + if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts) { answerInfo += "(TXT "; for (auto kv : p_Answer.m_Txts.m_Txts) @@ -161,7 +161,7 @@ void MDNSServiceQueryCallback(const clsMDNSHost::clsQuery& p_Query, answerInfo += kv->m_pcValue; } answerInfo += ")"; - mask |= (uint8_t)clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts; + mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts; } if (p_QueryAnswerTypeFlags & ~mask) { @@ -171,21 +171,21 @@ void MDNSServiceQueryCallback(const clsMDNSHost::clsQuery& p_Query, #if 0 switch (p_QueryAnswerTypeFlags) { - case static_cast<clsMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain): + case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain): answerInfo = "ServiceDomain " + String(p_Answer.m_ServiceDomain.c_str()); break; - case static_cast<clsMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort): + case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort): answerInfo = "HostDomainAndPort " + String(p_Answer.m_HostDomain.c_str()) + ":" + String(p_Answer.m_u16Port); break; - case static_cast<clsMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address): + case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address): answerInfo = "IP4Address "; for (auto ip : p_Answer.m_IPv4Addresses) { answerInfo += "- " + ip->m_IPAddress.toString(); }; break; - case static_cast<clsMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts): + case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts): answerInfo = "TXT "; for (auto kv : p_Answer.m_Txts.m_Txts) { @@ -206,7 +206,7 @@ void MDNSServiceQueryCallback(const clsMDNSHost::clsQuery& p_Query, Probe result callback for Services */ -void serviceProbeResult(clsMDNSHost::clsService& p_rMDNSService, +void serviceProbeResult(clsLEAMDNSHost::clsService& p_rMDNSService, const char* p_pcInstanceName, bool p_bProbeResult) { @@ -220,11 +220,11 @@ void serviceProbeResult(clsMDNSHost::clsService& p_rMDNSService, If the domain is free, the host domain is set and the http service is added. If the domain is already used, a new name is created and the probing is - restarted via p_pclsMDNSHost->setHostname(). + restarted via p_pclsLEAMDNSHost->setHostname(). */ -void hostProbeResult(clsMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bProbeResult) +void hostProbeResult(clsLEAMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bProbeResult) { Serial.printf("MDNSHostProbeResultCallback: Host domain '%s.local' is %s\n", p_pcDomainName.c_str(), (p_bProbeResult ? "free" : "already USED!")); @@ -281,7 +281,7 @@ void hostProbeResult(clsMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bP else { // Change hostname, use '-' as divider between base name and index - if (clsMDNSHost::indexDomainName(pcHostDomain, "-", 0)) + if (clsLEAMDNSHost::indexDomainName(pcHostDomain, "-", 0)) { MDNSv2.setHostName(pcHostDomain); } @@ -387,7 +387,7 @@ void setup(void) // Init the (currently empty) host domain string with 'esp8266' MDNSv2.begin("esp8266_v2"); /* - if ((!clsMDNSHost::indexDomain(pcHostDomain, 0, "esp8266")) || + if ((!clsLEAMDNSHost::indexDomain(pcHostDomain, 0, "esp8266")) || (!MDNSv2.begin(pcHostDomain))) { Serial.println(" Error setting up MDNS responder!"); while (1) { // STOP diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index ae580fd4b8..4b0721fa42 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -59,12 +59,12 @@ using MDNSResponder = experimental::MDNSImplementation::clsLEAMDNSHost_Legacy; #elif defined(MDNS2_EXPERIMENTAL) #include "LEAmDNS2Host.h" -using clsMDNSHost = esp8266::experimental::clsLEAMDNSHost; -using MDNSResponder = clsMDNSHost; +using esp8266::experimental::clsLEAMDNSHost; +using MDNSResponder = clsLEAMDNSHost; #else // default #include "LEAmDNS.h" -using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; +using esp8266::MDNSImplementation::MDNSResponder; #endif // version selection From 7fdf648f93606041def94b208210c1208d7aa853 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 21 Jun 2020 22:48:32 +0200 Subject: [PATCH 074/152] style --- .../LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 31 +- .../mDNS_ServiceMonitor_v2.ino | 94 +++-- .../mDNS_ServiceMonitor_v2_test.ino | 391 ++++++++---------- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 168 ++++---- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 14 +- .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 34 +- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 10 +- 7 files changed, 351 insertions(+), 391 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index 43c5c6e8b5..2390e6f5c5 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -194,15 +194,13 @@ void setup(void) { WiFi.persistent(false); // useless informative callback - if (!LwipIntf::stateUpCB([](netif* nif) - { - Serial.printf("New interface %c%c(%d) is up(%d)\n", - nif->name[0], - nif->name[1], - netif_get_index(nif), - netif_is_up(nif)); - })) - { + if (!LwipIntf::stateUpCB([](netif * nif) { + Serial.printf("New interface %c%c(%d) is up(%d)\n", + nif->name[0], + nif->name[1], + netif_get_index(nif), + netif_is_up(nif)); + })) { Serial.println("Error: could not add useless informative callback\n"); } @@ -231,9 +229,9 @@ void setup(void) { bool p_bProbeResult)->void { Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); // Unattended added service - hMDNSService = p_rMDNSHost.addService(0, "espclk", "tcp", 80); - hMDNSService->addDynamicServiceTxt("curtime", getTimeString()); - hMDNSService->setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallback); + hMDNSService = p_rMDNSHost.addService(0, "espclk", "tcp", 80); + hMDNSService->addDynamicServiceTxt("curtime", getTimeString()); + hMDNSService->setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallback); })) { Serial.println("mDNS-AP started"); } else { @@ -267,15 +265,14 @@ void loop(void) { } static bool AP_started = false; - if (!AP_started && millis() > START_AP_AFTER_MS) - { + if (!AP_started && millis() > START_AP_AFTER_MS) { AP_started = true; Serial.printf("Starting AP...\n"); WiFi.mode(WIFI_AP_STA); WiFi.softAP(APSSID, APPSK); Serial.printf("AP started...(%s:%s, %s)\n", - WiFi.softAPSSID().c_str(), - WiFi.softAPPSK().c_str(), - WiFi.softAPIP().toString().c_str()); + WiFi.softAPSSID().c_str(), + WiFi.softAPPSK().c_str(), + WiFi.softAPIP().toString().c_str()); } } diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino index 6bb8161a66..fac5d693d6 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino @@ -91,38 +91,37 @@ bool setStationHostname(const char* p_pcHostname) { void MDNSServiceQueryCallback(const MDNSResponder::clsQuery& p_Query, - const MDNSResponder::clsQuery::clsAnswer& p_Answer, - MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, - bool p_bSetContent) -{ - (void)p_Query; - - String answerInfo; - switch (p_QueryAnswerTypeFlags) { - case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain): - answerInfo = "ServiceDomain " + String(p_Answer.m_ServiceDomain.c_str()); - break; - - case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort): - answerInfo = "HostDomainAndPort " + String(p_Answer.m_HostDomain.c_str()) + ":" + String(p_Answer.m_u16Port); - break; - case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address): - answerInfo = "IP4Address "; - for (auto ip : p_Answer.m_IPv4Addresses) { - answerInfo += "- " + ip->m_IPAddress.toString(); - }; - break; - case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::Txts): - answerInfo = "TXT "; - for (auto kv : p_Answer.m_Txts.m_Txts) { - answerInfo += "\nkv : " + String(kv->m_pcKey) + " : " + String(kv->m_pcValue); - } - break; - default : - answerInfo = "Unknown Answertype " + String(p_QueryAnswerTypeFlags); - - } - Serial.printf("Answer %s %s\n", answerInfo.c_str(), p_bSetContent ? "Modified" : "Deleted"); + const MDNSResponder::clsQuery::clsAnswer& p_Answer, + MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, + bool p_bSetContent) { + (void)p_Query; + + String answerInfo; + switch (p_QueryAnswerTypeFlags) { + case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain): + answerInfo = "ServiceDomain " + String(p_Answer.m_ServiceDomain.c_str()); + break; + + case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort): + answerInfo = "HostDomainAndPort " + String(p_Answer.m_HostDomain.c_str()) + ":" + String(p_Answer.m_u16Port); + break; + case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address): + answerInfo = "IP4Address "; + for (auto ip : p_Answer.m_IPv4Addresses) { + answerInfo += "- " + ip->m_IPAddress.toString(); + }; + break; + case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::Txts): + answerInfo = "TXT "; + for (auto kv : p_Answer.m_Txts.m_Txts) { + answerInfo += "\nkv : " + String(kv->m_pcKey) + " : " + String(kv->m_pcValue); + } + break; + default : + answerInfo = "Unknown Answertype " + String(p_QueryAnswerTypeFlags); + + } + Serial.printf("Answer %s %s\n", answerInfo.c_str(), p_bSetContent ? "Modified" : "Deleted"); } /* @@ -131,7 +130,7 @@ void MDNSServiceQueryCallback(const MDNSResponder::clsQuery& p_Query, */ void serviceProbeResult(MDNSResponder::clsService& p_rMDNSService, - const char* p_pcInstanceName, + const char* p_pcInstanceName, bool p_bProbeResult) { (void)p_rMDNSService; Serial.printf("MDNSServiceProbeResultCallback: Service %s probe %s\n", p_pcInstanceName, (p_bProbeResult ? "succeeded." : "failed!")); @@ -165,8 +164,8 @@ void hostProbeResult(clsLEAMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p hMDNSService = MDNS.addService(0, "http", "tcp", SERVICE_PORT, serviceProbeResult); if (hMDNSService) { - hMDNSService->setProbeResultCallback(serviceProbeResult); - // MDNS.setServiceProbeResultCallback(hMDNSService, serviceProbeResult); + hMDNSService->setProbeResultCallback(serviceProbeResult); + // MDNS.setServiceProbeResultCallback(hMDNSService, serviceProbeResult); // Add some '_http._tcp' protocol specific MDNS service TXT items // See: http://www.dns-sd.org/txtrecords.html#http @@ -186,8 +185,7 @@ void hostProbeResult(clsLEAMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p } } } - } - else { + } else { // Change hostname, use '-' as divider between base name and index if (MDNSResponder::indexDomainName(pcHostDomain, "-", 0)) { MDNS.setHostName(pcHostDomain); @@ -211,7 +209,7 @@ void handleHTTPRequest() { s += "<br/><h4>Local HTTP services are :</h4>"; s += "<ol>"; /* - for (auto info : MDNS.answerInfo(hMDNSServiceQuery)) { + for (auto info : MDNS.answerInfo(hMDNSServiceQuery)) { s += "<li>"; s += info.serviceDomain(); if (info.hostDomainAvailable()) { @@ -233,7 +231,7 @@ void handleHTTPRequest() { } s += "</li>"; - } + } */ s += "</ol><br/>"; @@ -270,19 +268,19 @@ void setup(void) { server.on("/", handleHTTPRequest); // Setup MDNS responders - MDNS.setProbeResultCallback(hostProbeResult); + MDNS.setProbeResultCallback(hostProbeResult); // Init the (currently empty) host domain string with 'esp8266' MDNS.begin("esp8266_v2"); -/* - if ((!MDNSResponder::indexDomain(pcHostDomain, 0, "esp8266")) || - (!MDNS.begin(pcHostDomain))) { - Serial.println(" Error setting up MDNS responder!"); - while (1) { // STOP - delay(1000); + /* + if ((!MDNSResponder::indexDomain(pcHostDomain, 0, "esp8266")) || + (!MDNS.begin(pcHostDomain))) { + Serial.println(" Error setting up MDNS responder!"); + while (1) { // STOP + delay(1000); + } } - } -*/ + */ Serial.println("MDNS responder started"); // Start HTTP server diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino index 6a7f483624..b387b80112 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino @@ -91,114 +91,99 @@ ESP8266WebServer server(SERVICE_PORT); /* setStationHostname */ -bool setStationHostname(const char* p_pcHostname) -{ - - if (p_pcHostname) - { - WiFi.hostname(p_pcHostname); - Serial.printf("setStationHostname: Station hostname is set to '%s'\n", p_pcHostname); - return true; - } - return false; +bool setStationHostname(const char* p_pcHostname) { + + if (p_pcHostname) { + WiFi.hostname(p_pcHostname); + Serial.printf("setStationHostname: Station hostname is set to '%s'\n", p_pcHostname); + return true; + } + return false; } void MDNSServiceQueryCallback(const clsLEAMDNSHost::clsQuery& p_Query, const clsLEAMDNSHost::clsQuery::clsAnswer& p_Answer, clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, - bool p_bSetContent) -{ - Serial.printf("CB MDNSServiceQueryCallback\n"); - - String answerInfo; - clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType mask = 0; - if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain) - { - answerInfo += "(ServiceDomain "; - answerInfo += p_Answer.m_ServiceDomain.c_str(); - answerInfo += ")"; - mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain; - } - if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort) - { - answerInfo += "(HostDomainAndPort "; - answerInfo += p_Answer.m_HostDomain.c_str(); - answerInfo += ")"; - mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort; - } - if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address) - { - answerInfo += "(IP4Address "; - for (auto ip : p_Answer.m_IPv4Addresses) - { - answerInfo += "- "; - answerInfo += ip->m_IPAddress.toString(); - } - answerInfo += ")"; - mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address; + bool p_bSetContent) { + Serial.printf("CB MDNSServiceQueryCallback\n"); + + String answerInfo; + clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType mask = 0; + if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain) { + answerInfo += "(ServiceDomain "; + answerInfo += p_Answer.m_ServiceDomain.c_str(); + answerInfo += ")"; + mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain; + } + if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort) { + answerInfo += "(HostDomainAndPort "; + answerInfo += p_Answer.m_HostDomain.c_str(); + answerInfo += ")"; + mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort; + } + if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address) { + answerInfo += "(IP4Address "; + for (auto ip : p_Answer.m_IPv4Addresses) { + answerInfo += "- "; + answerInfo += ip->m_IPAddress.toString(); } + answerInfo += ")"; + mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address; + } #ifdef MDNS_IPV6_SUPPORT - if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address) - { - answerInfo += "(IP6Address "; - for (auto ip : p_Answer.m_IPv6Addresses) - { - answerInfo += "- "; - answerInfo += ip->m_IPAddress.toString(); - } - answerInfo += ")"; - mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address; + if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address) { + answerInfo += "(IP6Address "; + for (auto ip : p_Answer.m_IPv6Addresses) { + answerInfo += "- "; + answerInfo += ip->m_IPAddress.toString(); } + answerInfo += ")"; + mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address; + } #endif // MDNS_IPV6_SUPPORT - if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts) - { - answerInfo += "(TXT "; - for (auto kv : p_Answer.m_Txts.m_Txts) - { - answerInfo += "kv: "; - answerInfo += kv->m_pcKey; - answerInfo += ": "; - answerInfo += kv->m_pcValue; - } - answerInfo += ")"; - mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts; - } - if (p_QueryAnswerTypeFlags & ~mask) - { - answerInfo += "(other flags are set)"; + if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts) { + answerInfo += "(TXT "; + for (auto kv : p_Answer.m_Txts.m_Txts) { + answerInfo += "kv: "; + answerInfo += kv->m_pcKey; + answerInfo += ": "; + answerInfo += kv->m_pcValue; } + answerInfo += ")"; + mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts; + } + if (p_QueryAnswerTypeFlags & ~mask) { + answerInfo += "(other flags are set)"; + } #if 0 - switch (p_QueryAnswerTypeFlags) - { + switch (p_QueryAnswerTypeFlags) { case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain): - answerInfo = "ServiceDomain " + String(p_Answer.m_ServiceDomain.c_str()); - break; + answerInfo = "ServiceDomain " + String(p_Answer.m_ServiceDomain.c_str()); + break; case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort): - answerInfo = "HostDomainAndPort " + String(p_Answer.m_HostDomain.c_str()) + ":" + String(p_Answer.m_u16Port); - break; + answerInfo = "HostDomainAndPort " + String(p_Answer.m_HostDomain.c_str()) + ":" + String(p_Answer.m_u16Port); + break; case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address): - answerInfo = "IP4Address "; - for (auto ip : p_Answer.m_IPv4Addresses) - { - answerInfo += "- " + ip->m_IPAddress.toString(); - }; - break; + answerInfo = "IP4Address "; + for (auto ip : p_Answer.m_IPv4Addresses) { + answerInfo += "- " + ip->m_IPAddress.toString(); + }; + break; case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts): - answerInfo = "TXT "; - for (auto kv : p_Answer.m_Txts.m_Txts) - { - answerInfo += "\nkv : " + String(kv->m_pcKey) + " : " + String(kv->m_pcValue); - } - break; + answerInfo = "TXT "; + for (auto kv : p_Answer.m_Txts.m_Txts) { + answerInfo += "\nkv : " + String(kv->m_pcKey) + " : " + String(kv->m_pcValue); + } + break; default : - answerInfo = "Unknown Answertype " + String(p_QueryAnswerTypeFlags); + answerInfo = "Unknown Answertype " + String(p_QueryAnswerTypeFlags); - } + } #endif - Serial.printf("Answer %s %s\n", answerInfo.c_str(), p_bSetContent ? "Modified" : "Deleted"); + Serial.printf("Answer %s %s\n", answerInfo.c_str(), p_bSetContent ? "Modified" : "Deleted"); } /* @@ -208,9 +193,8 @@ void MDNSServiceQueryCallback(const clsLEAMDNSHost::clsQuery& p_Query, void serviceProbeResult(clsLEAMDNSHost::clsService& p_rMDNSService, const char* p_pcInstanceName, - bool p_bProbeResult) -{ - Serial.printf("MDNSServiceProbeResultCallback: Service %s probe %s\n", p_pcInstanceName, (p_bProbeResult ? "succeeded." : "failed!")); + bool p_bProbeResult) { + Serial.printf("MDNSServiceProbeResultCallback: Service %s probe %s\n", p_pcInstanceName, (p_bProbeResult ? "succeeded." : "failed!")); } /* @@ -224,79 +208,64 @@ void serviceProbeResult(clsLEAMDNSHost::clsService& p_rMDNSService, */ -void hostProbeResult(clsLEAMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bProbeResult) -{ - - Serial.printf("MDNSHostProbeResultCallback: Host domain '%s.local' is %s\n", p_pcDomainName.c_str(), (p_bProbeResult ? "free" : "already USED!")); - - if (true == p_bProbeResult) - { - // Set station hostname - setStationHostname(pcHostDomain); - Serial.printf("setting hostname = '%s'\n", pcHostDomain?: "nullptr"); - - if (!bHostDomainConfirmed) - { - // Hostname free -> setup clock service - bHostDomainConfirmed = true; - - if (!hMDNSService) - { - Serial.printf("adding service tcp.sapuducu port %d\n", SERVICE_PORT); - // Add a 'sapuducu.tcp' service to port 'SERVICE_PORT', using the host domain as instance domain - hMDNSService = MDNSv2.addService(0, "sapuducu", "tcp", SERVICE_PORT, serviceProbeResult); - - if (hMDNSService) - { - Serial.printf("hMDNSService\n"); - hMDNSService->setProbeResultCallback(serviceProbeResult); - // MDNSv2.setServiceProbeResultCallback(hMDNSService, serviceProbeResult); - - // Add some '_sapuducu._tcp' protocol specific MDNS service TXT items - // See: http://www.dns-sd.org/txtrecords.html#http - hMDNSService->addServiceTxt("user", "x"); - hMDNSService->addServiceTxt("password", "y"); - hMDNSService->addServiceTxt("path", "/"); - } - else - Serial.printf("hMDNSService=0 ??\n"); - - // Install dynamic 'espclk.tcp' service query - if (!hMDNSServiceQuery) - { - Serial.printf("installing hMDNSServiceQuery\n"); - hMDNSServiceQuery = MDNSv2.installServiceQuery("espclk", "tcp", MDNSServiceQueryCallback); - if (hMDNSServiceQuery) - { - Serial.printf("MDNSProbeResultCallback: Service query for 'espclk.tcp' services installed.\n"); - } - else - { - Serial.printf("MDNSProbeResultCallback: FAILED to install service query for 'espclk.tcp' services!\n"); - } - } - } - } - } - else - { - // Change hostname, use '-' as divider between base name and index - if (clsLEAMDNSHost::indexDomainName(pcHostDomain, "-", 0)) - { - MDNSv2.setHostName(pcHostDomain); +void hostProbeResult(clsLEAMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bProbeResult) { + + Serial.printf("MDNSHostProbeResultCallback: Host domain '%s.local' is %s\n", p_pcDomainName.c_str(), (p_bProbeResult ? "free" : "already USED!")); + + if (true == p_bProbeResult) { + // Set station hostname + setStationHostname(pcHostDomain); + Serial.printf("setting hostname = '%s'\n", pcHostDomain ? : "nullptr"); + + if (!bHostDomainConfirmed) { + // Hostname free -> setup clock service + bHostDomainConfirmed = true; + + if (!hMDNSService) { + Serial.printf("adding service tcp.sapuducu port %d\n", SERVICE_PORT); + // Add a 'sapuducu.tcp' service to port 'SERVICE_PORT', using the host domain as instance domain + hMDNSService = MDNSv2.addService(0, "sapuducu", "tcp", SERVICE_PORT, serviceProbeResult); + + if (hMDNSService) { + Serial.printf("hMDNSService\n"); + hMDNSService->setProbeResultCallback(serviceProbeResult); + // MDNSv2.setServiceProbeResultCallback(hMDNSService, serviceProbeResult); + + // Add some '_sapuducu._tcp' protocol specific MDNS service TXT items + // See: http://www.dns-sd.org/txtrecords.html#http + hMDNSService->addServiceTxt("user", "x"); + hMDNSService->addServiceTxt("password", "y"); + hMDNSService->addServiceTxt("path", "/"); + } else { + Serial.printf("hMDNSService=0 ??\n"); } - else - { - Serial.println("MDNSProbeResultCallback: FAILED to update hostname!"); + + // Install dynamic 'espclk.tcp' service query + if (!hMDNSServiceQuery) { + Serial.printf("installing hMDNSServiceQuery\n"); + hMDNSServiceQuery = MDNSv2.installServiceQuery("espclk", "tcp", MDNSServiceQueryCallback); + if (hMDNSServiceQuery) { + Serial.printf("MDNSProbeResultCallback: Service query for 'espclk.tcp' services installed.\n"); + } else { + Serial.printf("MDNSProbeResultCallback: FAILED to install service query for 'espclk.tcp' services!\n"); + } } + } + } + } else { + // Change hostname, use '-' as divider between base name and index + if (clsLEAMDNSHost::indexDomainName(pcHostDomain, "-", 0)) { + MDNSv2.setHostName(pcHostDomain); + } else { + Serial.println("MDNSProbeResultCallback: FAILED to update hostname!"); } + } } /* HTTP request function (not found is handled by server) */ -void handleHTTPRequest() -{ +void handleHTTPRequest() { Serial.println(""); Serial.println("HTTP Request"); @@ -306,7 +275,7 @@ void handleHTTPRequest() s += WiFi.hostname() + ".local at " + server.client().localIP().toString() + "</h3></head>"; s += "<br/><h4>Local HTTP services are :</h4>"; s += "<ol>"; - // hMDNSServiceQuery-> + // hMDNSServiceQuery-> if (hMDNSServiceQuery) { @@ -354,73 +323,69 @@ void handleHTTPRequest() /* setup */ -void setup(void) -{ - Serial.begin(115200); - // nd.printDump(Serial, Packet::PacketDetail::NONE, [](const Packet& p){return(p.getInOut() && p.isMDNS());}); - Serial.setDebugOutput(false); - - // Connect to WiFi network - WiFi.mode(WIFI_AP_STA); - WiFi.softAP("Soft1"); - WiFi.begin(STASSID, STAPSK); - Serial.println(""); - - // Wait for connection - while (WiFi.status() != WL_CONNECTED) - { - delay(500); - Serial.print("."); - } - Serial.println(""); - Serial.print("Connected to "); - Serial.println(STASSID); - Serial.print("IP address: "); - Serial.println(WiFi.localIP()); - - // Setup HTTP server - server.on("/", handleHTTPRequest); - - // Setup MDNS responders - MDNSv2.setProbeResultCallback(hostProbeResult); - - // Init the (currently empty) host domain string with 'esp8266' - MDNSv2.begin("esp8266_v2"); - /* - if ((!clsLEAMDNSHost::indexDomain(pcHostDomain, 0, "esp8266")) || - (!MDNSv2.begin(pcHostDomain))) { - Serial.println(" Error setting up MDNS responder!"); - while (1) { // STOP - delay(1000); - } - } - */ - Serial.println("MDNS responder started"); +void setup(void) { + Serial.begin(115200); + // nd.printDump(Serial, Packet::PacketDetail::NONE, [](const Packet& p){return(p.getInOut() && p.isMDNS());}); + Serial.setDebugOutput(false); + + // Connect to WiFi network + WiFi.mode(WIFI_AP_STA); + WiFi.softAP("Soft1"); + WiFi.begin(STASSID, STAPSK); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to "); + Serial.println(STASSID); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + // Setup HTTP server + server.on("/", handleHTTPRequest); + + // Setup MDNS responders + MDNSv2.setProbeResultCallback(hostProbeResult); + + // Init the (currently empty) host domain string with 'esp8266' + MDNSv2.begin("esp8266_v2"); + /* + if ((!clsLEAMDNSHost::indexDomain(pcHostDomain, 0, "esp8266")) || + (!MDNSv2.begin(pcHostDomain))) { + Serial.println(" Error setting up MDNS responder!"); + while (1) { // STOP + delay(1000); + } + } + */ + Serial.println("MDNS responder started"); - // Start HTTP server - server.begin(); - Serial.println("HTTP server started"); + // Start HTTP server + server.begin(); + Serial.println("HTTP server started"); #if END - nd.printDump(Serial, Packet::PacketDetail::FULL); + nd.printDump(Serial, Packet::PacketDetail::FULL); #endif } -void loop(void) -{ - // Check if a request has come in - server.handleClient(); - // Allow MDNS processing - MDNSv2.update(); +void loop(void) { + // Check if a request has come in + server.handleClient(); + // Allow MDNS processing + MDNSv2.update(); - static esp8266::polledTimeout::periodicMs timeout(10000); - if (timeout.expired()) - { - Serial.printf("up=%lumn heap=%u\n", millis() / 1000 / 60, ESP.getFreeHeap()); - } + static esp8266::polledTimeout::periodicMs timeout(10000); + if (timeout.expired()) { + Serial.printf("up=%lumn heap=%u\n", millis() / 1000 / 60, ESP.getFreeHeap()); + } } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 5c439bfb17..f0e33465c6 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -265,24 +265,24 @@ bool clsLEAMDNSHost::begin(const char* p_pcHostName, if (bResult) { - if (!LwipIntf::stateUpCB([this](netif* nif) + if (!LwipIntf::stateUpCB([this](netif * nif) + { + (void)nif; + // This called after a new interface appears: + // resend announces on all available interfaces. + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s a new interface %c%c/%d is up, restarting mDNS\n"), + _DH(), nif->name[0], nif->name[1], netif_get_index(nif));); + if (restart()) { - (void)nif; - // This called after a new interface appears: - // resend announces on all available interfaces. - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s a new interface %c%c/%d is up, restarting mDNS\n"), - _DH(), nif->name[0], nif->name[1], netif_get_index(nif));); - if (restart()) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s restart: success!\n"), _DH())); - } - else - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s restart failed!\n"), _DH())); - } - // No need to react when an interface disappears, - // because mDNS always loop on all available interfaces. - })) + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s restart: success!\n"), _DH())); + } + else + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s restart failed!\n"), _DH())); + } + // No need to react when an interface disappears, + // because mDNS always loop on all available interfaces. + })) { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s begin: could not add netif status callback\n"), _DH())); } @@ -468,15 +468,15 @@ bool clsLEAMDNSHost::removeService(clsLEAMDNSHost::clsService* p_pService) if (p_pService && (m_Services.end() != std::find(m_Services.begin(), m_Services.end(), p_pService))) { - bResult = _announceService(*p_pService, false); - /* - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) - if (netif_is_up(pNetIf) && - (_announceService(pNetIf, *p_pService, false))) - { - bResult = true; - } -*/ + bResult = _announceService(*p_pService, false); + /* + for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + if (netif_is_up(pNetIf) && + (_announceService(pNetIf, *p_pService, false))) + { + bResult = true; + } + */ } if (bResult) @@ -561,20 +561,20 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryService { std::list<clsQuery*> queries; - clsQuery* pQuery = 0; - if (((pQuery = _allocQuery(clsQuery::enuQueryType::Service))) && - (_buildDomainForService(p_pcService, p_pcProtocol, pQuery->m_Domain))) - { - if (((pQuery->m_bStaticQuery = true)) && (_sendQuery(*pQuery))) - { - queries.push_back(pQuery); - } - else - { - // FAILED to send query - _removeQuery(pQuery); - } - } + clsQuery* pQuery = 0; + if (((pQuery = _allocQuery(clsQuery::enuQueryType::Service))) && + (_buildDomainForService(p_pcService, p_pcProtocol, pQuery->m_Domain))) + { + if (((pQuery->m_bStaticQuery = true)) && (_sendQuery(*pQuery))) + { + queries.push_back(pQuery); + } + else + { + // FAILED to send query + _removeQuery(pQuery); + } + } if (queries.size()) { @@ -616,20 +616,20 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryHost(co { std::list<clsQuery*> queries; - clsQuery* pQuery = 0; - if (((pQuery = _allocQuery(clsQuery::enuQueryType::Host))) && - (_buildDomainForHost(p_pcHostName, pQuery->m_Domain))) - { - if (((pQuery->m_bStaticQuery = true)) && (_sendQuery(*pQuery))) - { - queries.push_back(pQuery); - } - else - { - // FAILED to send query - _removeQuery(pQuery); - } - } + clsQuery* pQuery = 0; + if (((pQuery = _allocQuery(clsQuery::enuQueryType::Host))) && + (_buildDomainForHost(p_pcHostName, pQuery->m_Domain))) + { + if (((pQuery->m_bStaticQuery = true)) && (_sendQuery(*pQuery))) + { + queries.push_back(pQuery); + } + else + { + // FAILED to send query + _removeQuery(pQuery); + } + } if (queries.size()) @@ -691,10 +691,10 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcSe clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) { clsQuery* pQuery = 0; - if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) - { - pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; - } + if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) + { + pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; + } return pQuery; } @@ -707,10 +707,10 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcSe clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) { clsQuery* pQuery = 0; - if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) - { - pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; - } + if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) + { + pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; + } return pQuery; } @@ -723,13 +723,13 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostN clsQuery* pQuery = 0; if ((p_pcHostName) && (*p_pcHostName)) { - clsRRDomain domain; - if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) - ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) - : 0))) - { - pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; - } + clsRRDomain domain; + if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) + ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) + : 0))) + { + pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; + } } return pQuery; } @@ -742,15 +742,15 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostN { clsQuery* pQuery = 0; if ((p_pcHostName) && (*p_pcHostName)) - { - clsRRDomain domain; - if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) - ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) - : 0))) - { - pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; - } - } + { + clsRRDomain domain; + if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) + ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) + : 0))) + { + pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; + } + } return pQuery; } @@ -796,7 +796,7 @@ bool clsLEAMDNSHost::update(void) bool clsLEAMDNSHost::announce(bool p_bAnnounce /*= true*/, bool p_bIncludeServices /*= true*/) { - return _announce(p_bAnnounce, p_bIncludeServices); + return _announce(p_bAnnounce, p_bIncludeServices); } /* @@ -807,7 +807,7 @@ bool clsLEAMDNSHost::announceService(clsService * p_pService, bool p_bAnnounce /*= true*/) { - return _announceService(*p_pService, p_bAnnounce); + return _announceService(*p_pService, p_bAnnounce); } @@ -1273,8 +1273,8 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findNextQueryByDomain(const clsLEAMDN */ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery( - const char* p_pcService, - const char* p_pcProtocol) + const char* p_pcService, + const char* p_pcProtocol) { clsQuery* pMDNSQuery = 0; @@ -1304,8 +1304,8 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery( clsLEAmDNS2_Host::_installDomainQuery */ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installDomainQuery( - clsLEAMDNSHost::clsRRDomain & p_Domain, - clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType) + clsLEAMDNSHost::clsRRDomain & p_Domain, + clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType) { clsQuery* pQuery = 0; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 81510e2bb0..43120be709 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -944,7 +944,7 @@ class clsLEAMDNSHost ServiceDomain = 0x01, // Service domain HostDomain = 0x02, // Host domain Port = 0x04, // Port - HostDomainPort = 0x06, + HostDomainPort = 0x06, Txts = 0x08, // TXT items #ifdef MDNS_IPV4_SUPPORT IPv4Address = 0x10, // IPv4 address @@ -1260,15 +1260,15 @@ class clsLEAMDNSHost it no more returns a single query but a boolean until the API is adapted */ clsQuery* installServiceQuery(const char* p_pcServiceType, - const char* p_pcProtocol, - clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); + const char* p_pcProtocol, + clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); clsQuery* installServiceQuery(const char* p_pcServiceType, - const char* p_pcProtocol, - clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); + const char* p_pcProtocol, + clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); clsQuery* installHostQuery(const char* p_pcHostName, - clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); + clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer); clsQuery* installHostQuery(const char* p_pcHostName, - clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); + clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor); // Remove a dynamic service query bool removeQuery(clsQuery* p_pQuery); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index c321551f36..de808bfa96 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1290,21 +1290,21 @@ bool clsLEAMDNSHost::_updateProbeStatus() // // Probe host domain if ((clsProbeInformation_Base::enuProbingStatus::ReadyToStart == m_ProbeInformation.m_ProbingStatus))// && // Ready to get started AND -/* - (( -#ifdef MDNS_IPV4_SUPPORT - _getResponderIPAddress(pNetIf, enuIPProtocolType::V4).isSet() // AND has IPv4 address -#else - true -#endif - ) || ( -#ifdef MDNS_IPV6_SUPPORT - _getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet() // OR has IPv6 address -#else - true -#endif - ))) // Has IP address -*/ + /* + (( + #ifdef MDNS_IPV4_SUPPORT + _getResponderIPAddress(pNetIf, enuIPProtocolType::V4).isSet() // AND has IPv4 address + #else + true + #endif + ) || ( + #ifdef MDNS_IPV6_SUPPORT + _getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet() // OR has IPv6 address + #else + true + #endif + ))) // Has IP address + */ { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Starting host probing...\n"), _DH());); @@ -1683,7 +1683,7 @@ bool clsLEAMDNSHost::_announce(bool p_bAnnounce, Serial.printf("Announce : %d\r\n", m_ProbeInformation.m_ProbingStatus); #if 0 if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == m_ProbeInformation.m_ProbingStatus) || - (clsProbeInformation_Base::enuProbingStatus::DoneFinally == m_ProbeInformation.m_ProbingStatus)) + (clsProbeInformation_Base::enuProbingStatus::DoneFinally == m_ProbeInformation.m_ProbingStatus)) #endif { bResult = true; @@ -1713,7 +1713,7 @@ bool clsLEAMDNSHost::_announce(bool p_bAnnounce, { #if 0 if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == pService->m_ProbeInformation.m_ProbingStatus) || - (clsProbeInformation_Base::enuProbingStatus::DoneFinally == pService->m_ProbeInformation.m_ProbingStatus)) + (clsProbeInformation_Base::enuProbingStatus::DoneFinally == pService->m_ProbeInformation.m_ProbingStatus)) #endif { pService->m_u32ReplyMask = (static_cast<uint32_t>(enuContentFlag::PTR_TYPE) | diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index f54e6fa475..3e4d455b6a 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -52,11 +52,11 @@ namespace experimental */ bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParameter) { - bool bResult = true; + bool bResult = true; for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) if (netif_is_up(pNetIf)) { - bResult = bResult && _sendMessage(pNetIf, p_rSendParameter); + bResult = bResult && _sendMessage(pNetIf, p_rSendParameter); } // Finally clear service reply masks @@ -269,8 +269,8 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam // Two step sequence: 'Count' and 'Send' for (typeSequence sequence = static_cast<typeSequence>(enuSequence::Count); ((bResult) && (sequence <= static_cast<typeSequence>(enuSequence::Send))); ++sequence) { - /* - DEBUG_EX_INFO( + /* + DEBUG_EX_INFO( if (static_cast<typeSequence>(enuSequence::Send) == sequence) DEBUG_OUTPUT.printf_P(PSTR("%s _prepareMDNSMessage: ID:%u QR:%u OP:%u AA:%u TC:%u RD:%u RA:%u R:%u QD:%u AN:%u NS:%u AR:%u\n"), _DH(), @@ -281,7 +281,7 @@ bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParam (unsigned)msgHeader.m_u16ANCount, (unsigned)msgHeader.m_u16NSCount, (unsigned)msgHeader.m_u16ARCount); - ); + ); */ // Count/send // Header From 64abb8c22043ca48096e06714456ae1bc3c5f75f Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Mon, 22 Jun 2020 13:35:03 +0200 Subject: [PATCH 075/152] false alarm #if0defines removed, log messages added --- .../LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 6 +++--- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 1 + .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 16 ++++++++++------ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index 2390e6f5c5..dd4e4840c4 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -195,11 +195,10 @@ void setup(void) { // useless informative callback if (!LwipIntf::stateUpCB([](netif * nif) { - Serial.printf("New interface %c%c(%d) is up(%d)\n", + Serial.printf("New interface %c%c/%d is up\n", nif->name[0], nif->name[1], - netif_get_index(nif), - netif_is_up(nif)); + netif_get_index(nif)); })) { Serial.println("Error: could not add useless informative callback\n"); } @@ -260,6 +259,7 @@ void loop(void) { if (hMDNSService) { // Just trigger a new MDNS announcement, this will lead to a call to // 'MDNSDynamicServiceTxtCallback', which will update the time TXT item + Serial.printf("Announce trigger from user\n"); responder.announce(); } } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index f0e33465c6..2592533212 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -796,6 +796,7 @@ bool clsLEAMDNSHost::update(void) bool clsLEAMDNSHost::announce(bool p_bAnnounce /*= true*/, bool p_bIncludeServices /*= true*/) { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s ::announce() externally called\n"), _DH());); return _announce(p_bAnnounce, p_bIncludeServices); } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index de808bfa96..86dc677d7a 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1343,6 +1343,7 @@ bool clsLEAMDNSHost::_updateProbeStatus() else if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == m_ProbeInformation.m_ProbingStatus) && (m_ProbeInformation.m_Timeout.expired())) { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: ReadyToAnnounce => Announce (without services), now\n"), _DH());); if ((bResult = _announce(true, false))) { // Don't announce services here @@ -1680,11 +1681,16 @@ bool clsLEAMDNSHost::_announce(bool p_bAnnounce, bool bResult = false; clsSendParameter sendParameter; - Serial.printf("Announce : %d\r\n", m_ProbeInformation.m_ProbingStatus); -#if 0 + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s ::announce() status=%d (waiting4data:%d ready2start:%d inprogress:%d ready2announce:%d done:%d\r\n"), + _DH(), m_ProbeInformation.m_ProbingStatus, + clsProbeInformation_Base::enuProbingStatus::WaitingForData, + clsProbeInformation_Base::enuProbingStatus::ReadyToStart, + clsProbeInformation_Base::enuProbingStatus::InProgress, + clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce, + clsProbeInformation_Base::enuProbingStatus::DoneFinally);); + if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == m_ProbeInformation.m_ProbingStatus) || (clsProbeInformation_Base::enuProbingStatus::DoneFinally == m_ProbeInformation.m_ProbingStatus)) -#endif { bResult = true; @@ -1711,10 +1717,8 @@ bool clsLEAMDNSHost::_announce(bool p_bAnnounce, // Announce services (service type, name, SRV (location) and TXTs) for (clsService* pService : m_Services) { -#if 0 if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == pService->m_ProbeInformation.m_ProbingStatus) || (clsProbeInformation_Base::enuProbingStatus::DoneFinally == pService->m_ProbeInformation.m_ProbingStatus)) -#endif { pService->m_u32ReplyMask = (static_cast<uint32_t>(enuContentFlag::PTR_TYPE) | static_cast<uint32_t>(enuContentFlag::PTR_NAME) | @@ -1725,7 +1729,7 @@ bool clsLEAMDNSHost::_announce(bool p_bAnnounce, } } } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _announce: FAILED!\n"), _DH());); + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _announce: FAILED!\n\n"), _DH());); return ((bResult) && (_sendMessage(sendParameter))); } From 166745d7e0950b4c46f2eb5ba38a63f9fb9198d4 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Mon, 22 Jun 2020 18:15:04 +0200 Subject: [PATCH 076/152] style --- .../LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 30 +++++++++++-------- .../mDNS_ServiceMonitor_v2.ino | 7 ++--- .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 12 ++++---- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index dd4e4840c4..f9a6b86e50 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -65,7 +65,7 @@ #define DST_OFFSET 1 // CEST #define UPDATE_CYCLE (1 * 1000) // every second -#define START_AP_AFTER_MS 10000 //60000 // start AP after delay +#define START_AP_AFTER_MS 10000 // start AP after delay #define SERVICE_PORT 80 // HTTP port #ifndef STASSID @@ -81,7 +81,7 @@ const char* ssid = STASSID; const char* password = STAPSK; -clsLEAMDNSHost responder; // MDNS responder +clsLEAMDNSHost MDNS; // MDNS responder bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain clsLEAMDNSHost::clsService* hMDNSService = 0; // The handle of the clock service in the MDNS responder @@ -144,7 +144,7 @@ bool setStationHostname(const char* p_pcHostname) { Add a dynamic MDNS TXT item 'ct' to the clock service. The callback function is called every time, the TXT items for the clock service are needed. - This can be triggered by calling responder.announce(). + This can be triggered by calling MDNS.announce(). */ void MDNSDynamicServiceTxtCallback(const clsLEAMDNSHost::hMDNSService& p_hService) { @@ -223,14 +223,18 @@ void setup(void) { // Setup MDNS responder // Init the (currently empty) host domain string with 'esp8266' - if (responder.begin("leamdnsv2", [](clsLEAMDNSHost & p_rMDNSHost, - const char* p_pcDomainName, - bool p_bProbeResult)->void { - Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); - // Unattended added service - hMDNSService = p_rMDNSHost.addService(0, "espclk", "tcp", 80); - hMDNSService->addDynamicServiceTxt("curtime", getTimeString()); - hMDNSService->setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallback); + if (MDNS.begin("leamdnsv2", + [](clsLEAMDNSHost & p_rMDNSHost, const char* p_pcDomainName, bool p_bProbeResult)->void { + if (p_bProbeResult) { + Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); + // Unattended added service + hMDNSService = p_rMDNSHost.addService(0, "espclk", "tcp", 80); + hMDNSService->addDynamicServiceTxt("curtime", getTimeString()); + hMDNSService->setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallback); + } else { + // Change hostname, use '-' as divider between base name and index + MDNS.setHostName(MDNSResponder::indexDomainName(p_pcDomainName, "-", 0)); + } })) { Serial.println("mDNS-AP started"); } else { @@ -251,7 +255,7 @@ void loop(void) { // Check if a request has come in server.handleClient(); // Allow MDNS processing - responder.update(); + MDNS.update(); static esp8266::polledTimeout::periodicMs timeout(UPDATE_CYCLE); if (timeout.expired()) { @@ -260,7 +264,7 @@ void loop(void) { // Just trigger a new MDNS announcement, this will lead to a call to // 'MDNSDynamicServiceTxtCallback', which will update the time TXT item Serial.printf("Announce trigger from user\n"); - responder.announce(); + MDNS.announce(); } } diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino index fac5d693d6..a1e05b333e 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino @@ -149,6 +149,7 @@ void serviceProbeResult(MDNSResponder::clsService& p_rMDNSService, void hostProbeResult(clsLEAMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bProbeResult) { + (void)p_rMDNSHost; Serial.printf("MDNSHostProbeResultCallback: Host domain '%s.local' is %s\n", p_pcDomainName.c_str(), (p_bProbeResult ? "free" : "already USED!")); if (true == p_bProbeResult) { @@ -187,11 +188,7 @@ void hostProbeResult(clsLEAMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p } } else { // Change hostname, use '-' as divider between base name and index - if (MDNSResponder::indexDomainName(pcHostDomain, "-", 0)) { - MDNS.setHostName(pcHostDomain); - } else { - Serial.println("MDNSProbeResultCallback: FAILED to update hostname!"); - } + MDNS.setHostName(MDNSResponder::indexDomainName(p_pcDomainName.c_str(), "-", 0)); } } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index 86dc677d7a..00e260cd76 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1682,12 +1682,12 @@ bool clsLEAMDNSHost::_announce(bool p_bAnnounce, clsSendParameter sendParameter; DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s ::announce() status=%d (waiting4data:%d ready2start:%d inprogress:%d ready2announce:%d done:%d\r\n"), - _DH(), m_ProbeInformation.m_ProbingStatus, - clsProbeInformation_Base::enuProbingStatus::WaitingForData, - clsProbeInformation_Base::enuProbingStatus::ReadyToStart, - clsProbeInformation_Base::enuProbingStatus::InProgress, - clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce, - clsProbeInformation_Base::enuProbingStatus::DoneFinally);); + _DH(), m_ProbeInformation.m_ProbingStatus, + clsProbeInformation_Base::enuProbingStatus::WaitingForData, + clsProbeInformation_Base::enuProbingStatus::ReadyToStart, + clsProbeInformation_Base::enuProbingStatus::InProgress, + clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce, + clsProbeInformation_Base::enuProbingStatus::DoneFinally);); if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == m_ProbeInformation.m_ProbingStatus) || (clsProbeInformation_Base::enuProbingStatus::DoneFinally == m_ProbeInformation.m_ProbingStatus)) From 7bbd93006255b204f3fb8bad1fe4412e5cc866b4 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Mon, 22 Jun 2020 18:17:20 +0200 Subject: [PATCH 077/152] remove test example --- .../mDNS_ServiceMonitor_v2_test.ino | 392 ------------------ 1 file changed, 392 deletions(-) delete mode 100644 libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino deleted file mode 100644 index b387b80112..0000000000 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2_test/mDNS_ServiceMonitor_v2_test.ino +++ /dev/null @@ -1,392 +0,0 @@ -/* - ESP8266 mDNS Responder Service Monitor - - This example demonstrates two features of the LEA MDNSResponder: - 1. The host and service domain negotiation process that ensures - the uniqueness of the finally choosen host and service domain name. - 2. The dynamic MDNS service lookup/query feature. - - A list of 'HTTP' services in the local network is created and kept up to date. - In addition to this, a (very simple) HTTP server is set up on port 80 - and announced as a service. - - The ESP itself is initially announced to clients as 'esp8266.local', if this host domain - is already used in the local network, another host domain is negociated. Keep an - eye to the serial output to learn the final host domain for the HTTP service. - The service itself is is announced as 'host domain'._sapuducul._tcp.local. - The HTTP server delivers a short greeting and the current list of other 'HTTP' services (not updated). - The web server code is taken nearly 1:1 from the 'mDNS_Web_Server.ino' example. - Point your browser to 'host domain'.local to see this web page. - - Instructions: - - Update WiFi SSID and password as necessary. - - Flash the sketch to the ESP8266 board - - Install host software: - - For Linux, install Avahi (http://avahi.org/). - - For Windows, install Bonjour (http://www.apple.com/support/bonjour/). - - For Mac OSX and iOS support is built in through Bonjour already. - - Use a browser like 'Safari' to see the page at http://'host domain'.local. - -*/ - - -#define END 0 // enable netdump - -#ifndef STASSID -#define STASSID "ssid" -#define STAPSK "psk" -#endif - - -#include <ESP8266WiFi.h> -#include <WiFiClient.h> -#include <ESP8266WebServer.h> - -#if END -#include <Netdump.h> -using namespace NetCapture; -Netdump nd; -#endif - - - -/* - Include the clsLEAMDNSHost (the library needs to be included also) - As LEA clsLEAMDNSHost is experimantal in the ESP8266 environment currently, the - legacy clsLEAMDNSHost is defaulted in th include file. - There are two ways to access LEA clsLEAMDNSHost: - 1. Prepend every declaration and call to global declarations or functions with the namespace, like: - 'LEAmDNS:clsLEAMDNSHost::hMDNSService hMDNSService;' - This way is used in the example. But be careful, if the namespace declaration is missing - somewhere, the call might go to the legacy implementation... - 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. - -*/ - -#define MDNS2_EXPERIMENTAL -#include <ESP8266mDNS.h> -//#include "LocalDefines.h" -//#include "Netdump.h" -//using namespace NetCapture; -/* - Global defines and vars -*/ - -clsLEAMDNSHost MDNSv2; - -#define SERVICE_PORT 80 // HTTP port - -char* pcHostDomain = 0; // Negociated host domain -bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain -clsLEAMDNSHost::clsService* hMDNSService = 0; // The handle of the sapuducu service in the MDNS responder -clsLEAMDNSHost::clsQuery* hMDNSServiceQuery = 0; // The handle of the 'espclk.tcp' service query in the MDNS responder - -const String cstrNoHTTPServices = "Currently no 'http.tcp' services in the local network!<br/>"; -String strHTTPServices = cstrNoHTTPServices; - -// HTTP server at port 'SERVICE_PORT' will respond to HTTP requests -ESP8266WebServer server(SERVICE_PORT); - - -/* - setStationHostname -*/ -bool setStationHostname(const char* p_pcHostname) { - - if (p_pcHostname) { - WiFi.hostname(p_pcHostname); - Serial.printf("setStationHostname: Station hostname is set to '%s'\n", p_pcHostname); - return true; - } - return false; -} - -void MDNSServiceQueryCallback(const clsLEAMDNSHost::clsQuery& p_Query, - const clsLEAMDNSHost::clsQuery::clsAnswer& p_Answer, - clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, - bool p_bSetContent) { - Serial.printf("CB MDNSServiceQueryCallback\n"); - - String answerInfo; - clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType mask = 0; - if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain) { - answerInfo += "(ServiceDomain "; - answerInfo += p_Answer.m_ServiceDomain.c_str(); - answerInfo += ")"; - mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain; - } - if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort) { - answerInfo += "(HostDomainAndPort "; - answerInfo += p_Answer.m_HostDomain.c_str(); - answerInfo += ")"; - mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort; - } - if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address) { - answerInfo += "(IP4Address "; - for (auto ip : p_Answer.m_IPv4Addresses) { - answerInfo += "- "; - answerInfo += ip->m_IPAddress.toString(); - } - answerInfo += ")"; - mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address; - } -#ifdef MDNS_IPV6_SUPPORT - if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address) { - answerInfo += "(IP6Address "; - for (auto ip : p_Answer.m_IPv6Addresses) { - answerInfo += "- "; - answerInfo += ip->m_IPAddress.toString(); - } - answerInfo += ")"; - mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address; - } -#endif // MDNS_IPV6_SUPPORT - if (p_QueryAnswerTypeFlags & (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts) { - answerInfo += "(TXT "; - for (auto kv : p_Answer.m_Txts.m_Txts) { - answerInfo += "kv: "; - answerInfo += kv->m_pcKey; - answerInfo += ": "; - answerInfo += kv->m_pcValue; - } - answerInfo += ")"; - mask |= (uint8_t)clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts; - } - if (p_QueryAnswerTypeFlags & ~mask) { - answerInfo += "(other flags are set)"; - } - -#if 0 - switch (p_QueryAnswerTypeFlags) { - case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain): - answerInfo = "ServiceDomain " + String(p_Answer.m_ServiceDomain.c_str()); - break; - - case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort): - answerInfo = "HostDomainAndPort " + String(p_Answer.m_HostDomain.c_str()) + ":" + String(p_Answer.m_u16Port); - break; - case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address): - answerInfo = "IP4Address "; - for (auto ip : p_Answer.m_IPv4Addresses) { - answerInfo += "- " + ip->m_IPAddress.toString(); - }; - break; - case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts): - answerInfo = "TXT "; - for (auto kv : p_Answer.m_Txts.m_Txts) { - answerInfo += "\nkv : " + String(kv->m_pcKey) + " : " + String(kv->m_pcValue); - } - break; - default : - answerInfo = "Unknown Answertype " + String(p_QueryAnswerTypeFlags); - - } -#endif - - Serial.printf("Answer %s %s\n", answerInfo.c_str(), p_bSetContent ? "Modified" : "Deleted"); -} - -/* - MDNSServiceProbeResultCallback - Probe result callback for Services -*/ - -void serviceProbeResult(clsLEAMDNSHost::clsService& p_rMDNSService, - const char* p_pcInstanceName, - bool p_bProbeResult) { - Serial.printf("MDNSServiceProbeResultCallback: Service %s probe %s\n", p_pcInstanceName, (p_bProbeResult ? "succeeded." : "failed!")); -} - -/* - MDNSHostProbeResultCallback - - Probe result callback for the host domain. - If the domain is free, the host domain is set and the http service is - added. - If the domain is already used, a new name is created and the probing is - restarted via p_pclsLEAMDNSHost->setHostname(). - -*/ - -void hostProbeResult(clsLEAMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bProbeResult) { - - Serial.printf("MDNSHostProbeResultCallback: Host domain '%s.local' is %s\n", p_pcDomainName.c_str(), (p_bProbeResult ? "free" : "already USED!")); - - if (true == p_bProbeResult) { - // Set station hostname - setStationHostname(pcHostDomain); - Serial.printf("setting hostname = '%s'\n", pcHostDomain ? : "nullptr"); - - if (!bHostDomainConfirmed) { - // Hostname free -> setup clock service - bHostDomainConfirmed = true; - - if (!hMDNSService) { - Serial.printf("adding service tcp.sapuducu port %d\n", SERVICE_PORT); - // Add a 'sapuducu.tcp' service to port 'SERVICE_PORT', using the host domain as instance domain - hMDNSService = MDNSv2.addService(0, "sapuducu", "tcp", SERVICE_PORT, serviceProbeResult); - - if (hMDNSService) { - Serial.printf("hMDNSService\n"); - hMDNSService->setProbeResultCallback(serviceProbeResult); - // MDNSv2.setServiceProbeResultCallback(hMDNSService, serviceProbeResult); - - // Add some '_sapuducu._tcp' protocol specific MDNS service TXT items - // See: http://www.dns-sd.org/txtrecords.html#http - hMDNSService->addServiceTxt("user", "x"); - hMDNSService->addServiceTxt("password", "y"); - hMDNSService->addServiceTxt("path", "/"); - } else { - Serial.printf("hMDNSService=0 ??\n"); - } - - // Install dynamic 'espclk.tcp' service query - if (!hMDNSServiceQuery) { - Serial.printf("installing hMDNSServiceQuery\n"); - hMDNSServiceQuery = MDNSv2.installServiceQuery("espclk", "tcp", MDNSServiceQueryCallback); - if (hMDNSServiceQuery) { - Serial.printf("MDNSProbeResultCallback: Service query for 'espclk.tcp' services installed.\n"); - } else { - Serial.printf("MDNSProbeResultCallback: FAILED to install service query for 'espclk.tcp' services!\n"); - } - } - } - } - } else { - // Change hostname, use '-' as divider between base name and index - if (clsLEAMDNSHost::indexDomainName(pcHostDomain, "-", 0)) { - MDNSv2.setHostName(pcHostDomain); - } else { - Serial.println("MDNSProbeResultCallback: FAILED to update hostname!"); - } - } -} - -/* - HTTP request function (not found is handled by server) -*/ -void handleHTTPRequest() { - Serial.println(""); - Serial.println("HTTP Request"); - - IPAddress ip = server.client().localIP(); - String ipStr = ip.toString(); - String s = "<!DOCTYPE HTML>\r\n<html><h3><head>Hello from "; - s += WiFi.hostname() + ".local at " + server.client().localIP().toString() + "</h3></head>"; - s += "<br/><h4>Local HTTP services are :</h4>"; - s += "<ol>"; - // hMDNSServiceQuery-> - - - if (hMDNSServiceQuery) { - for (auto info : hMDNSServiceQuery->answerAccessors()) { - s += "<li>"; - s += info.serviceDomain(); - - if (info.hostDomainAvailable()) { - s += "<br/>Hostname: "; - s += String(info.hostDomain()); - s += (info.hostPortAvailable()) ? (":" + String(info.hostPort())) : ""; - } - if (info.IPv4AddressAvailable()) { - s += "<br/>IPv4:"; - for (auto ip : info.IPv4Addresses()) { - s += " " + ip.toString(); - } - } -#ifdef MDNS_IPV6_SUPPORT - if (info.IPv6AddressAvailable()) { - s += "<br/>IPv6:"; - for (auto ip : info.IPv6Addresses()) { - s += " " + ip.toString(); - } - } -#endif - if (info.txtsAvailable()) { - s += "<br/>TXT:<br/>"; - for (auto kv : info.txtKeyValues()) { - s += "\t" + String(kv.first) + " : " + String(kv.second) + "<br/>"; - } - } - s += "</li>"; - } - } - s += "</ol><br/>"; - - Serial.println("Sending 200"); - server.send(200, "text/html", s); - Serial.println("Done with request"); -} - - - -/* - setup -*/ -void setup(void) { - Serial.begin(115200); - // nd.printDump(Serial, Packet::PacketDetail::NONE, [](const Packet& p){return(p.getInOut() && p.isMDNS());}); - Serial.setDebugOutput(false); - - // Connect to WiFi network - WiFi.mode(WIFI_AP_STA); - WiFi.softAP("Soft1"); - WiFi.begin(STASSID, STAPSK); - Serial.println(""); - - // Wait for connection - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); - } - Serial.println(""); - Serial.print("Connected to "); - Serial.println(STASSID); - Serial.print("IP address: "); - Serial.println(WiFi.localIP()); - - // Setup HTTP server - server.on("/", handleHTTPRequest); - - // Setup MDNS responders - MDNSv2.setProbeResultCallback(hostProbeResult); - - // Init the (currently empty) host domain string with 'esp8266' - MDNSv2.begin("esp8266_v2"); - /* - if ((!clsLEAMDNSHost::indexDomain(pcHostDomain, 0, "esp8266")) || - (!MDNSv2.begin(pcHostDomain))) { - Serial.println(" Error setting up MDNS responder!"); - while (1) { // STOP - delay(1000); - } - } - */ - Serial.println("MDNS responder started"); - - // Start HTTP server - server.begin(); - Serial.println("HTTP server started"); - -#if END - nd.printDump(Serial, Packet::PacketDetail::FULL); -#endif - -} - - - -void loop(void) { - // Check if a request has come in - server.handleClient(); - // Allow MDNS processing - MDNSv2.update(); - - static esp8266::polledTimeout::periodicMs timeout(10000); - if (timeout.expired()) { - Serial.printf("up=%lumn heap=%u\n", millis() / 1000 / 60, ESP.getFreeHeap()); - } -} - - - From 1309974f75ebeb62df7d3be18804b04c6227c445 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 23 Jun 2020 10:29:19 +0200 Subject: [PATCH 078/152] revert/fix ESP8266mDNS.h --- .../ArduinoOTA/examples/BasicOTA/BasicOTA.ino | 4 +- .../ArduinoOTA/examples/OTALeds/OTALeds.ino | 4 +- .../CaptivePortalAdvanced.ino | 4 +- .../Arduino_Wifi_AVRISP.ino | 4 +- .../SecureBearSSLUpdater.ino | 4 +- .../SecureHTTPSUpdater/SecureHTTPSUpdater.ino | 4 +- .../SecureWebUpdater/SecureWebUpdater.ino | 4 +- .../examples/WebUpdater/WebUpdater.ino | 4 +- .../AdvancedWebServer/AdvancedWebServer.ino | 2 - .../examples/FSBrowser/FSBrowser.ino | 4 +- .../ESP8266WebServer/examples/Graph/Graph.ino | 4 +- .../examples/HelloServer/HelloServer.ino | 2 - .../HelloServerBearSSL/HelloServerBearSSL.ino | 2 - .../HelloServerSecure/HelloServerSecure.ino | 2 - .../HttpAdvancedAuth/HttpAdvancedAuth.ino | 4 +- .../examples/HttpBasicAuth/HttpBasicAuth.ino | 4 +- .../examples/PathArgServer/PathArgServer.ino | 2 - .../examples/PostServer/PostServer.ino | 2 - .../ServerSentEvents/ServerSentEvents.ino | 4 +- .../examples/WebUpdate/WebUpdate.ino | 2 - .../OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino | 2 - .../mDNS-SD_Extended/mDNS-SD_Extended.ino | 2 - .../mDNS_Web_Server/mDNS_Web_Server.ino | 4 +- libraries/ESP8266mDNS/src/ESP8266mDNS.h | 38 +++++++------------ 24 files changed, 28 insertions(+), 84 deletions(-) diff --git a/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino index b7973d4517..ddc5629741 100644 --- a/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino +++ b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino @@ -1,10 +1,8 @@ #include <ESP8266WiFi.h> +#include <ESP8266mDNS.h> #include <WiFiUdp.h> #include <ArduinoOTA.h> -//#define MDNS2_EXPERIMENTAL_V1COMPAT -#include <ESP8266mDNS.h> - #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino b/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino index 9fe1a8798e..7d05074e15 100644 --- a/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino +++ b/libraries/ArduinoOTA/examples/OTALeds/OTALeds.ino @@ -1,10 +1,8 @@ #include <ESP8266WiFi.h> +#include <ESP8266mDNS.h> #include <WiFiUdp.h> #include <ArduinoOTA.h> -//#define MDNS2_EXPERIMENTAL_V1COMPAT -#include <ESP8266mDNS.h> - #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino b/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino index 2435ff9cfa..5f1f5020a1 100644 --- a/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino +++ b/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino @@ -2,10 +2,8 @@ #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <DNSServer.h> -#include <EEPROM.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> +#include <EEPROM.h> /* This example serves a "hello world" on a WLAN and a SoftAP at the same time. diff --git a/libraries/ESP8266AVRISP/examples/Arduino_Wifi_AVRISP/Arduino_Wifi_AVRISP.ino b/libraries/ESP8266AVRISP/examples/Arduino_Wifi_AVRISP/Arduino_Wifi_AVRISP.ino index 362e0f1b7b..fdc34cff2b 100644 --- a/libraries/ESP8266AVRISP/examples/Arduino_Wifi_AVRISP/Arduino_Wifi_AVRISP.ino +++ b/libraries/ESP8266AVRISP/examples/Arduino_Wifi_AVRISP/Arduino_Wifi_AVRISP.ino @@ -1,9 +1,7 @@ #include <SPI.h> #include <ESP8266WiFi.h> -#include <ESP8266AVRISP.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> +#include <ESP8266AVRISP.h> #ifndef STASSID #define STASSID "your-ssid" diff --git a/libraries/ESP8266HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino b/libraries/ESP8266HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino index 534643a8e1..a2514e171d 100644 --- a/libraries/ESP8266HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino +++ b/libraries/ESP8266HTTPUpdateServer/examples/SecureBearSSLUpdater/SecureBearSSLUpdater.ino @@ -16,10 +16,8 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServerSecure.h> -#include <ESP8266HTTPUpdateServer.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> +#include <ESP8266HTTPUpdateServer.h> #ifndef STASSID #define STASSID "your-ssid" diff --git a/libraries/ESP8266HTTPUpdateServer/examples/SecureHTTPSUpdater/SecureHTTPSUpdater.ino b/libraries/ESP8266HTTPUpdateServer/examples/SecureHTTPSUpdater/SecureHTTPSUpdater.ino index b0d0d1f70d..a28d48de81 100644 --- a/libraries/ESP8266HTTPUpdateServer/examples/SecureHTTPSUpdater/SecureHTTPSUpdater.ino +++ b/libraries/ESP8266HTTPUpdateServer/examples/SecureHTTPSUpdater/SecureHTTPSUpdater.ino @@ -49,15 +49,13 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServerSecure.h> +#include <ESP8266mDNS.h> #include <ESP8266HTTPUpdateServer.h> #include <WiFiServerSecure.h> #include <WiFiServerSecureAxTLS.h> #include <WiFiClientSecure.h> #include <WiFiClientSecureAxTLS.h> -//#define MDNS2_EXPERIMENTAL_V1COMPAT -#include <ESP8266mDNS.h> - #pragma GCC diagnostic pop #ifndef STASSID diff --git a/libraries/ESP8266HTTPUpdateServer/examples/SecureWebUpdater/SecureWebUpdater.ino b/libraries/ESP8266HTTPUpdateServer/examples/SecureWebUpdater/SecureWebUpdater.ino index 4e73983cf8..11e23a929d 100644 --- a/libraries/ESP8266HTTPUpdateServer/examples/SecureWebUpdater/SecureWebUpdater.ino +++ b/libraries/ESP8266HTTPUpdateServer/examples/SecureWebUpdater/SecureWebUpdater.ino @@ -5,10 +5,8 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> -#include <ESP8266HTTPUpdateServer.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> +#include <ESP8266HTTPUpdateServer.h> #ifndef STASSID #define STASSID "your-ssid" diff --git a/libraries/ESP8266HTTPUpdateServer/examples/WebUpdater/WebUpdater.ino b/libraries/ESP8266HTTPUpdateServer/examples/WebUpdater/WebUpdater.ino index cee1b69c03..fea3c4023a 100644 --- a/libraries/ESP8266HTTPUpdateServer/examples/WebUpdater/WebUpdater.ino +++ b/libraries/ESP8266HTTPUpdateServer/examples/WebUpdater/WebUpdater.ino @@ -5,10 +5,8 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> -#include <ESP8266HTTPUpdateServer.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> +#include <ESP8266HTTPUpdateServer.h> #ifndef STASSID #define STASSID "your-ssid" diff --git a/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino b/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino index 92cc76044d..2fc8508ca0 100644 --- a/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino +++ b/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino @@ -31,8 +31,6 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino b/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino index fe3b50f2c4..f6aff52c7d 100644 --- a/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino +++ b/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino @@ -40,10 +40,8 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> -#include <SPI.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> +#include <SPI.h> #ifdef INCLUDE_FALLBACK_INDEX_HTM #include "extras/index_htm.h" diff --git a/libraries/ESP8266WebServer/examples/Graph/Graph.ino b/libraries/ESP8266WebServer/examples/Graph/Graph.ino index c17b043f18..4f73455676 100644 --- a/libraries/ESP8266WebServer/examples/Graph/Graph.ino +++ b/libraries/ESP8266WebServer/examples/Graph/Graph.ino @@ -33,10 +33,8 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> -#include <SPI.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> +#include <SPI.h> #if defined USE_SPIFFS #include <FS.h> diff --git a/libraries/ESP8266WebServer/examples/HelloServer/HelloServer.ino b/libraries/ESP8266WebServer/examples/HelloServer/HelloServer.ino index 5f902d1d07..1335c347af 100644 --- a/libraries/ESP8266WebServer/examples/HelloServer/HelloServer.ino +++ b/libraries/ESP8266WebServer/examples/HelloServer/HelloServer.ino @@ -1,8 +1,6 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino b/libraries/ESP8266WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino index daa5d8f381..4b786dc1a5 100644 --- a/libraries/ESP8266WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino +++ b/libraries/ESP8266WebServer/examples/HelloServerBearSSL/HelloServerBearSSL.ino @@ -12,8 +12,6 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServerSecure.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266WebServer/examples/HelloServerSecure/HelloServerSecure.ino b/libraries/ESP8266WebServer/examples/HelloServerSecure/HelloServerSecure.ino index a9b21d472d..87c34ccb58 100644 --- a/libraries/ESP8266WebServer/examples/HelloServerSecure/HelloServerSecure.ino +++ b/libraries/ESP8266WebServer/examples/HelloServerSecure/HelloServerSecure.ino @@ -44,8 +44,6 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServerSecure.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266WebServer/examples/HttpAdvancedAuth/HttpAdvancedAuth.ino b/libraries/ESP8266WebServer/examples/HttpAdvancedAuth/HttpAdvancedAuth.ino index 0b175c05bf..857048cf0b 100644 --- a/libraries/ESP8266WebServer/examples/HttpAdvancedAuth/HttpAdvancedAuth.ino +++ b/libraries/ESP8266WebServer/examples/HttpAdvancedAuth/HttpAdvancedAuth.ino @@ -5,12 +5,10 @@ */ #include <ESP8266WiFi.h> +#include <ESP8266mDNS.h> #include <ArduinoOTA.h> #include <ESP8266WebServer.h> -//#define MDNS2_EXPERIMENTAL_V1COMPAT -#include <ESP8266mDNS.h> - #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/ESP8266WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino b/libraries/ESP8266WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino index 26899ea71f..7c06637caf 100644 --- a/libraries/ESP8266WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino +++ b/libraries/ESP8266WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino @@ -1,10 +1,8 @@ #include <ESP8266WiFi.h> +#include <ESP8266mDNS.h> #include <ArduinoOTA.h> #include <ESP8266WebServer.h> -//#define MDNS2_EXPERIMENTAL_V1COMPAT -#include <ESP8266mDNS.h> - #ifndef STASSID #define STASSID "your-ssid" #define STAPSK "your-password" diff --git a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino index 0d37972f51..dc998986e5 100644 --- a/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino +++ b/libraries/ESP8266WebServer/examples/PathArgServer/PathArgServer.ino @@ -1,8 +1,6 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #include <uri/UriBraces.h> diff --git a/libraries/ESP8266WebServer/examples/PostServer/PostServer.ino b/libraries/ESP8266WebServer/examples/PostServer/PostServer.ino index 5a963bd131..da1703807a 100644 --- a/libraries/ESP8266WebServer/examples/PostServer/PostServer.ino +++ b/libraries/ESP8266WebServer/examples/PostServer/PostServer.ino @@ -1,8 +1,6 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266WebServer/examples/ServerSentEvents/ServerSentEvents.ino b/libraries/ESP8266WebServer/examples/ServerSentEvents/ServerSentEvents.ino index 3c35dc3dd9..77ae1e958e 100644 --- a/libraries/ESP8266WebServer/examples/ServerSentEvents/ServerSentEvents.ino +++ b/libraries/ESP8266WebServer/examples/ServerSentEvents/ServerSentEvents.ino @@ -37,10 +37,8 @@ extern "C" { #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> -#include <Ticker.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> +#include <Ticker.h> #ifndef STASSID #define STASSID "your-ssid" diff --git a/libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino b/libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino index e71d771890..17646fd172 100644 --- a/libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino +++ b/libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino @@ -5,8 +5,6 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino b/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino index a39518efa3..5e4a5a0810 100644 --- a/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino +++ b/libraries/ESP8266mDNS/examples/OTA-mDNS-LittleFS/OTA-mDNS-LittleFS.ino @@ -28,8 +28,6 @@ #include <FS.h> #include <LittleFS.h> #include <ArduinoOTA.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> diff --git a/libraries/ESP8266mDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino b/libraries/ESP8266mDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino index 9b180fcc2d..fda2fe6562 100644 --- a/libraries/ESP8266mDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino +++ b/libraries/ESP8266mDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino @@ -10,8 +10,6 @@ */ #include <ESP8266WiFi.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #ifndef STASSID diff --git a/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino b/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino index 66a10b4c5a..7560864ce1 100644 --- a/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino +++ b/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino @@ -17,10 +17,8 @@ #include <ESP8266WiFi.h> -#include <WiFiClient.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> +#include <WiFiClient.h> #ifndef STASSID #define STASSID "your-ssid" diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index 4b0721fa42..55b209f9bd 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -42,32 +42,22 @@ */ -// mDNS on esp8266 Arduino, 4 available versions, select one with a define -// to add before `#include <ESP8266mDNS>`: -// -// - original (default until core-2.4.2): add `#define MDNS_ORIGINAL` -// - LEAmDNS (v1, from core-2.5.0 to core 2.7.2): default -// - LEAmDNSv2, with V1 API compatibility: add `#define MDNS2_EXPERIMENTAL_V1COMPAT` -// - LEAmDNSv2, new API: add `#define MDNS2_EXPERIMENTAL` +enum class MDNSApiVersion { Legacy, LEA, LEAv2Compat, LEAv2 }; -#if defined(MDNS_ORIGINAL) -#include "ESP8266mDNS_Legacy.h" +#include "ESP8266mDNS_Legacy.h" // Legacy +#include "LEAmDNS.h" // LEA +#include "LEAmDNS2_Legacy.h" // LEAv2Compat - replacement for LEA using v2 +#include "LEAmDNS2Host.h" // LEAv2 - API updated -#elif defined(MDNS2_EXPERIMENTAL_V1COMPAT) -#include "LEAmDNS2_Legacy.h" -using MDNSResponder = experimental::MDNSImplementation::clsLEAMDNSHost_Legacy; - -#elif defined(MDNS2_EXPERIMENTAL) -#include "LEAmDNS2Host.h" -using esp8266::experimental::clsLEAMDNSHost; -using MDNSResponder = clsLEAMDNSHost; - -#else // default -#include "LEAmDNS.h" -using esp8266::MDNSImplementation::MDNSResponder; - -#endif // version selection +// clsLEAMDNSHost replaces MDNSResponder in LEAv2 +using clsLEAMDNSHost = esp8266::experimental::clsLEAMDNSHost; #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) +// Maps the implementation to use to the global namespace type +//using MDNSResponder = Legacy_MDNSResponder::MDNSResponder; // Legacy +//using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA +//using MDNSResponder = experimental::MDNSImplementation::clsLEAMDNSHost_Legacy; // LEAv2Compat +using MDNSResponder = clsLEAMDNSHost; // LEAv2 + extern MDNSResponder MDNS; -#endif // global instance +#endif From 2cdc9027971b0cb4181838d6e39a92be89c228ce Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 30 Jun 2020 02:26:45 +0200 Subject: [PATCH 079/152] style --- tests/host/common/user_interface.cpp | 904 +++++++++++++-------------- 1 file changed, 452 insertions(+), 452 deletions(-) diff --git a/tests/host/common/user_interface.cpp b/tests/host/common/user_interface.cpp index 34015e33f9..fccb9dbfa4 100644 --- a/tests/host/common/user_interface.cpp +++ b/tests/host/common/user_interface.cpp @@ -1,32 +1,32 @@ /* - Arduino emulation - espressif sdk host implementation - Copyright (c) 2018 david gauchard. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal with the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimers. - - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimers in the - documentation and/or other materials provided with the distribution. - - - The names of its contributors may not be used to endorse or promote - products derived from this Software without specific prior written - permission. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS WITH THE SOFTWARE. + Arduino emulation - espressif sdk host implementation + Copyright (c) 2018 david gauchard. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal with the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + - The names of its contributors may not be used to endorse or promote + products derived from this Software without specific prior written + permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS WITH THE SOFTWARE. */ #include <lwip/def.h> @@ -44,446 +44,446 @@ extern "C" { -uint8 wifi_get_opmode(void) -{ - return STATION_MODE; -} - -phy_mode_t wifi_get_phy_mode(void) -{ - return PHY_MODE_11N; -} - -uint8 wifi_get_channel (void) -{ - return 1; -} - -uint8 wifi_station_get_current_ap_id (void) -{ - return 0; -} - -station_status_t wifi_station_get_connect_status (void) -{ - return STATION_GOT_IP; -} - -uint8 wifi_station_get_auto_connect (void) -{ - return 1; -} - -bool wifi_station_get_config (struct station_config *config) -{ - strcpy((char*)config->ssid, "emulated-ssid"); - strcpy((char*)config->password, "emulated-ssid-password"); - config->bssid_set = 0; - for (int i = 0; i < 6; i++) - config->bssid[i] = i; - config->threshold.rssi = 1; - config->threshold.authmode = AUTH_WPA_PSK; + uint8 wifi_get_opmode(void) + { + return STATION_MODE; + } + + phy_mode_t wifi_get_phy_mode(void) + { + return PHY_MODE_11N; + } + + uint8 wifi_get_channel(void) + { + return 1; + } + + uint8 wifi_station_get_current_ap_id(void) + { + return 0; + } + + station_status_t wifi_station_get_connect_status(void) + { + return STATION_GOT_IP; + } + + uint8 wifi_station_get_auto_connect(void) + { + return 1; + } + + bool wifi_station_get_config(struct station_config *config) + { + strcpy((char*)config->ssid, "emulated-ssid"); + strcpy((char*)config->password, "emulated-ssid-password"); + config->bssid_set = 0; + for (int i = 0; i < 6; i++) + config->bssid[i] = i; + config->threshold.rssi = 1; + config->threshold.authmode = AUTH_WPA_PSK; #ifdef NONOSDK3V0 - config->open_and_wep_mode_disable = true; + config->open_and_wep_mode_disable = true; #endif - return true; -} - -void wifi_fpm_close(void) -{ -} - -sint8 wifi_fpm_do_sleep (uint32 sleep_time_in_us) -{ - usleep(sleep_time_in_us); - return 1; -} - -void wifi_fpm_do_wakeup (void) -{ -} - -void wifi_fpm_open (void) -{ -} - -void wifi_fpm_set_sleep_type (sleep_type_t type) -{ - (void)type; -} - -uint32_t global_ipv4_netfmt = 0; // global binding - -netif netif0; -uint32_t global_source_address = INADDR_ANY; - -bool wifi_get_ip_info (uint8 if_index, struct ip_info *info) -{ - // emulate wifi_get_ip_info() - // ignore if_index - // use global option -i (host_interface) to select bound interface/address - - struct ifaddrs * ifAddrStruct = NULL, * ifa = NULL; - uint32_t ipv4 = lwip_htonl(0x7f000001); - uint32_t mask = lwip_htonl(0xff000000); - global_source_address = INADDR_ANY; // =0 - - if (getifaddrs(&ifAddrStruct) != 0) - { - perror("getifaddrs"); - exit(EXIT_FAILURE); - } - if (host_interface) - mockverbose("host: looking for interface '%s':\n", host_interface); - else - mockverbose("host: looking the first for non-local IPv4 interface:\n"); - for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) - { - mockverbose("host: interface: %s", ifa->ifa_name); - if ( ifa->ifa_addr - && ifa->ifa_addr->sa_family == AF_INET // ip_info is IPv4 only - ) - { - auto test_ipv4 = lwip_ntohl(*(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr); - mockverbose(" IPV4 (0x%08lx)", test_ipv4); - if ((test_ipv4 & 0xff000000) == 0x7f000000) - // 127./8 - mockverbose(" (local, ignored)"); - else - { - if (!host_interface || (host_interface && strcmp(ifa->ifa_name, host_interface) == 0)) - { - // use the first non-local interface, or, if specified, the one selected by user on cmdline - ipv4 = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr; - mask = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr; - mockverbose(" (selected)\n"); - global_source_address = ntohl(ipv4); - break; - } - } - } - mockverbose("\n"); - } - if (ifAddrStruct != NULL) - freeifaddrs(ifAddrStruct); - - (void)if_index; - //if (if_index != STATION_IF) - // fprintf(stderr, "we are not AP"); - - if (global_ipv4_netfmt == NO_GLOBAL_BINDING) - global_ipv4_netfmt = ipv4; - - if (info) - { - info->ip.addr = ipv4; - info->netmask.addr = mask; - info->gw.addr = ipv4; - - netif0.ip_addr.addr = ipv4; - netif0.netmask.addr = mask; - netif0.gw.addr = ipv4; - netif0.flags = NETIF_FLAG_IGMP | NETIF_FLAG_UP | NETIF_FLAG_LINK_UP; - netif0.next = nullptr; - } - - return true; -} - -uint8 wifi_get_listen_interval (void) -{ - return 1; -} - -bool wifi_get_macaddr(uint8 if_index, uint8 *macaddr) -{ - (void)if_index; - macaddr[0] = 0xde; - macaddr[1] = 0xba; - macaddr[2] = 0x7a; - macaddr[3] = 0xb1; - macaddr[4] = 0xe0; - macaddr[5] = 0x42; - return true; -} - -uint8 wifi_get_opmode_default (void) -{ - return STATION_MODE; -} + return true; + } + + void wifi_fpm_close(void) + { + } + + sint8 wifi_fpm_do_sleep(uint32 sleep_time_in_us) + { + usleep(sleep_time_in_us); + return 1; + } + + void wifi_fpm_do_wakeup(void) + { + } + + void wifi_fpm_open(void) + { + } + + void wifi_fpm_set_sleep_type(sleep_type_t type) + { + (void)type; + } + + uint32_t global_ipv4_netfmt = 0; // global binding + + netif netif0; + uint32_t global_source_address = INADDR_ANY; + + bool wifi_get_ip_info(uint8 if_index, struct ip_info *info) + { + // emulate wifi_get_ip_info() + // ignore if_index + // use global option -i (host_interface) to select bound interface/address + + struct ifaddrs * ifAddrStruct = NULL, * ifa = NULL; + uint32_t ipv4 = lwip_htonl(0x7f000001); + uint32_t mask = lwip_htonl(0xff000000); + global_source_address = INADDR_ANY; // =0 + + if (getifaddrs(&ifAddrStruct) != 0) + { + perror("getifaddrs"); + exit(EXIT_FAILURE); + } + if (host_interface) + mockverbose("host: looking for interface '%s':\n", host_interface); + else + mockverbose("host: looking the first for non-local IPv4 interface:\n"); + for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) + { + mockverbose("host: interface: %s", ifa->ifa_name); + if (ifa->ifa_addr + && ifa->ifa_addr->sa_family == AF_INET // ip_info is IPv4 only + ) + { + auto test_ipv4 = lwip_ntohl(*(uint32_t*) & ((struct sockaddr_in*)ifa->ifa_addr)->sin_addr); + mockverbose(" IPV4 (0x%08lx)", test_ipv4); + if ((test_ipv4 & 0xff000000) == 0x7f000000) + // 127./8 + mockverbose(" (local, ignored)"); + else + { + if (!host_interface || (host_interface && strcmp(ifa->ifa_name, host_interface) == 0)) + { + // use the first non-local interface, or, if specified, the one selected by user on cmdline + ipv4 = *(uint32_t*) & ((struct sockaddr_in*)ifa->ifa_addr)->sin_addr; + mask = *(uint32_t*) & ((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr; + mockverbose(" (selected)\n"); + global_source_address = ntohl(ipv4); + break; + } + } + } + mockverbose("\n"); + } + if (ifAddrStruct != NULL) + freeifaddrs(ifAddrStruct); + + (void)if_index; + //if (if_index != STATION_IF) + // fprintf(stderr, "we are not AP"); + + if (global_ipv4_netfmt == NO_GLOBAL_BINDING) + global_ipv4_netfmt = ipv4; + + if (info) + { + info->ip.addr = ipv4; + info->netmask.addr = mask; + info->gw.addr = ipv4; + + netif0.ip_addr.addr = ipv4; + netif0.netmask.addr = mask; + netif0.gw.addr = ipv4; + netif0.flags = NETIF_FLAG_IGMP | NETIF_FLAG_UP | NETIF_FLAG_LINK_UP; + netif0.next = nullptr; + } + + return true; + } + + uint8 wifi_get_listen_interval(void) + { + return 1; + } + + bool wifi_get_macaddr(uint8 if_index, uint8 *macaddr) + { + (void)if_index; + macaddr[0] = 0xde; + macaddr[1] = 0xba; + macaddr[2] = 0x7a; + macaddr[3] = 0xb1; + macaddr[4] = 0xe0; + macaddr[5] = 0x42; + return true; + } + + uint8 wifi_get_opmode_default(void) + { + return STATION_MODE; + } #ifdef NONOSDK3V0 -sleep_level_t wifi_get_sleep_level (void) -{ - return MIN_SLEEP_T; -} + sleep_level_t wifi_get_sleep_level(void) + { + return MIN_SLEEP_T; + } #endif // nonos-sdk-pre-3 -sleep_type_t wifi_get_sleep_type (void) -{ - return NONE_SLEEP_T; -} - -bool wifi_set_channel (uint8 channel) -{ - (void)channel; - return true; -} - -wifi_event_handler_cb_t wifi_event_handler_cb_emu = nullptr; -void wifi_set_event_handler_cb (wifi_event_handler_cb_t cb) -{ - wifi_event_handler_cb_emu = cb; - mockverbose("TODO: wifi_set_event_handler_cb set\n"); -} - -bool wifi_set_ip_info (uint8 if_index, struct ip_info *info) -{ - (void)if_index; - (void)info; - return false; -} - -bool wifi_set_listen_interval (uint8 interval) -{ - (void)interval; - return true; -} - -bool wifi_set_opmode (uint8 opmode) -{ - return opmode == STATION_MODE || opmode == STATIONAP_MODE; -} - -bool wifi_set_opmode_current (uint8 opmode) -{ - return opmode == STATION_MODE || opmode == STATIONAP_MODE; -} - -bool wifi_set_phy_mode (phy_mode_t mode) -{ - (void)mode; - return true; -} + sleep_type_t wifi_get_sleep_type(void) + { + return NONE_SLEEP_T; + } + + bool wifi_set_channel(uint8 channel) + { + (void)channel; + return true; + } + + wifi_event_handler_cb_t wifi_event_handler_cb_emu = nullptr; + void wifi_set_event_handler_cb(wifi_event_handler_cb_t cb) + { + wifi_event_handler_cb_emu = cb; + mockverbose("TODO: wifi_set_event_handler_cb set\n"); + } + + bool wifi_set_ip_info(uint8 if_index, struct ip_info *info) + { + (void)if_index; + (void)info; + return false; + } + + bool wifi_set_listen_interval(uint8 interval) + { + (void)interval; + return true; + } + + bool wifi_set_opmode(uint8 opmode) + { + return opmode == STATION_MODE || opmode == STATIONAP_MODE; + } + + bool wifi_set_opmode_current(uint8 opmode) + { + return opmode == STATION_MODE || opmode == STATIONAP_MODE; + } + + bool wifi_set_phy_mode(phy_mode_t mode) + { + (void)mode; + return true; + } #ifdef NONOSDK3V0 -bool wifi_set_sleep_level (sleep_level_t level) -{ - (void)level; - return true; -} + bool wifi_set_sleep_level(sleep_level_t level) + { + (void)level; + return true; + } #endif -bool wifi_set_sleep_type (sleep_type_t type) -{ - (void)type; - return true; -} - -bool wifi_station_connect (void) -{ - return true; -} - -bool wifi_station_dhcpc_start (void) -{ - return true; -} - -bool wifi_station_dhcpc_stop (void) -{ - return true; -} - -bool wifi_station_disconnect (void) -{ - return true; -} - -bool wifi_station_get_config_default (struct station_config *config) -{ - return wifi_station_get_config(config); -} - -char wifi_station_get_hostname_str [128]; -const char* wifi_station_get_hostname (void) -{ - return strcpy(wifi_station_get_hostname_str, "esposix"); -} - -bool wifi_station_get_reconnect_policy () -{ - return true; -} - -sint8 wifi_station_get_rssi (void) -{ - return 5; -} - -bool wifi_station_set_auto_connect (uint8 set) -{ - return set != 0; -} - -bool wifi_station_set_config (struct station_config *config) -{ - (void)config; - return true; -} - -bool wifi_station_set_config_current (struct station_config *config) -{ - (void)config; - return true; -} - -bool wifi_station_set_hostname (const char *name) -{ - (void)name; - return true; -} - -bool wifi_station_set_reconnect_policy (bool set) -{ - (void)set; - return true; -} - -void system_phy_set_max_tpw (uint8 max_tpw) -{ - (void)max_tpw; -} - -bool wifi_softap_dhcps_start(void) -{ - return true; -} - -enum dhcp_status wifi_softap_dhcps_status(void) -{ - return DHCP_STARTED; -} - -bool wifi_softap_dhcps_stop(void) -{ - return true; -} - -bool wifi_softap_get_config(struct softap_config *config) -{ - strcpy((char*)config->ssid, "apssid"); - strcpy((char*)config->password, "appasswd"); - config->ssid_len = strlen("appasswd"); - config->channel = 1; - config->authmode = AUTH_WPA2_PSK; - config->ssid_hidden = 0; - config->max_connection = 4; - config->beacon_interval = 100; - return true; -} - -bool wifi_softap_get_config_default(struct softap_config *config) -{ - return wifi_softap_get_config(config); -} - -uint8 wifi_softap_get_station_num(void) -{ - return 2; -} - -bool wifi_softap_set_config(struct softap_config *config) -{ - (void)config; - return true; -} - -bool wifi_softap_set_config_current(struct softap_config *config) -{ - (void)config; - return true; -} - -bool wifi_softap_set_dhcps_lease(struct dhcps_lease *please) -{ - (void)please; - return true; -} - -bool wifi_softap_set_dhcps_lease_time(uint32 minute) -{ - (void)minute; - return true; -} - -bool wifi_softap_set_dhcps_offer_option(uint8 level, void* optarg) -{ - (void)level; - (void)optarg; - return true; -} - -bool wifi_station_scan(struct scan_config *config, scan_done_cb_t cb) -{ - (void)config; - cb(nullptr, FAIL); - return false; -} - -uint32_t core_version = 1; - -/////////////////////////////////////// -// not user_interface - -void ets_isr_mask (int intr) -{ - (void)intr; -} - -void ets_isr_unmask (int intr) -{ - (void)intr; -} - -void esp_schedule (void) -{ -} - -void dns_setserver (u8_t numdns, ip_addr_t *dnsserver) -{ - (void)numdns; - (void)dnsserver; -} - -ip_addr_t dns_getserver (u8_t numdns) -{ - (void)numdns; - ip_addr_t addr = { 0x7f000001 }; - return addr; -} + bool wifi_set_sleep_type(sleep_type_t type) + { + (void)type; + return true; + } + + bool wifi_station_connect(void) + { + return true; + } + + bool wifi_station_dhcpc_start(void) + { + return true; + } + + bool wifi_station_dhcpc_stop(void) + { + return true; + } + + bool wifi_station_disconnect(void) + { + return true; + } + + bool wifi_station_get_config_default(struct station_config *config) + { + return wifi_station_get_config(config); + } + + char wifi_station_get_hostname_str [128]; + const char* wifi_station_get_hostname(void) + { + return strcpy(wifi_station_get_hostname_str, "esposix"); + } + + bool wifi_station_get_reconnect_policy() + { + return true; + } + + sint8 wifi_station_get_rssi(void) + { + return 5; + } + + bool wifi_station_set_auto_connect(uint8 set) + { + return set != 0; + } + + bool wifi_station_set_config(struct station_config *config) + { + (void)config; + return true; + } + + bool wifi_station_set_config_current(struct station_config *config) + { + (void)config; + return true; + } + + bool wifi_station_set_hostname(const char *name) + { + (void)name; + return true; + } + + bool wifi_station_set_reconnect_policy(bool set) + { + (void)set; + return true; + } + + void system_phy_set_max_tpw(uint8 max_tpw) + { + (void)max_tpw; + } + + bool wifi_softap_dhcps_start(void) + { + return true; + } + + enum dhcp_status wifi_softap_dhcps_status(void) + { + return DHCP_STARTED; + } + + bool wifi_softap_dhcps_stop(void) + { + return true; + } + + bool wifi_softap_get_config(struct softap_config *config) + { + strcpy((char*)config->ssid, "apssid"); + strcpy((char*)config->password, "appasswd"); + config->ssid_len = strlen("appasswd"); + config->channel = 1; + config->authmode = AUTH_WPA2_PSK; + config->ssid_hidden = 0; + config->max_connection = 4; + config->beacon_interval = 100; + return true; + } + + bool wifi_softap_get_config_default(struct softap_config *config) + { + return wifi_softap_get_config(config); + } + + uint8 wifi_softap_get_station_num(void) + { + return 2; + } + + bool wifi_softap_set_config(struct softap_config *config) + { + (void)config; + return true; + } + + bool wifi_softap_set_config_current(struct softap_config *config) + { + (void)config; + return true; + } + + bool wifi_softap_set_dhcps_lease(struct dhcps_lease *please) + { + (void)please; + return true; + } + + bool wifi_softap_set_dhcps_lease_time(uint32 minute) + { + (void)minute; + return true; + } + + bool wifi_softap_set_dhcps_offer_option(uint8 level, void* optarg) + { + (void)level; + (void)optarg; + return true; + } + + bool wifi_station_scan(struct scan_config *config, scan_done_cb_t cb) + { + (void)config; + cb(nullptr, FAIL); + return false; + } + + uint32_t core_version = 1; + + /////////////////////////////////////// + // not user_interface + + void ets_isr_mask(int intr) + { + (void)intr; + } + + void ets_isr_unmask(int intr) + { + (void)intr; + } + + void esp_schedule(void) + { + } + + void dns_setserver(u8_t numdns, ip_addr_t *dnsserver) + { + (void)numdns; + (void)dnsserver; + } + + ip_addr_t dns_getserver(u8_t numdns) + { + (void)numdns; + ip_addr_t addr = { 0x7f000001 }; + return addr; + } #include <smartconfig.h> -bool smartconfig_start (sc_callback_t cb, ...) -{ - //XXXFIXME ... -> ptr - cb(SC_STATUS_LINK, NULL); - return true; -} - -bool smartconfig_stop (void) -{ - return true; -} - -sleep_type_t wifi_fpm_get_sleep_type(void) -{ - return NONE_SLEEP_T; -} + bool smartconfig_start(sc_callback_t cb, ...) + { + //XXXFIXME ... -> ptr + cb(SC_STATUS_LINK, NULL); + return true; + } + + bool smartconfig_stop(void) + { + return true; + } + + sleep_type_t wifi_fpm_get_sleep_type(void) + { + return NONE_SLEEP_T; + } } // extern "C" From 3539444d41188fd038ab9d46e43b8ed04f4d9134 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Wed, 12 Aug 2020 19:06:20 +0200 Subject: [PATCH 080/152] fix multiple call to ::begin() --- cores/esp8266/LwipIntfCB.cpp | 1 + libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/cores/esp8266/LwipIntfCB.cpp b/cores/esp8266/LwipIntfCB.cpp index 4eb81cb6b8..c0de24a233 100644 --- a/cores/esp8266/LwipIntfCB.cpp +++ b/cores/esp8266/LwipIntfCB.cpp @@ -1,6 +1,7 @@ #include <LwipIntf.h> #include <Schedule.h> +#include <debug.h> #define NETIF_STATUS_CB_SIZE 3 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 2592533212..d090984232 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -257,6 +257,9 @@ bool clsLEAMDNSHost::begin(const char* p_pcHostName, bool bResult = false; + if (m_pUDPContext) + close(); + bResult = (setHostName(p_pcHostName)) && (_joinMulticastGroups()) && (p_fnCallback ? setProbeResultCallback(p_fnCallback) : true) && From 468fa8c5498e20a75b60749a222f18de03e6c0ba Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Wed, 12 Aug 2020 19:34:02 +0200 Subject: [PATCH 081/152] ditto --- tests/host/common/ArduinoMain.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/host/common/ArduinoMain.cpp b/tests/host/common/ArduinoMain.cpp index bb91e76cd0..6372359681 100644 --- a/tests/host/common/ArduinoMain.cpp +++ b/tests/host/common/ArduinoMain.cpp @@ -145,7 +145,6 @@ void help (const char* argv0, int exitcode) "\t-1 - run loop once then exit (for host testing)\n" "\t-v - verbose\n" , argv0, MOCK_PORT_SHIFTER, argv0, spiffs_kb, littlefs_kb); ->>>>>>> master exit(exitcode); } From 057ceb5673a870f4d85ee932e061f7f8859ed98d Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 20 Aug 2020 15:17:54 +0200 Subject: [PATCH 082/152] enable LEA v1 by default (= no change to arduino master) --- libraries/ESP8266mDNS/src/ESP8266mDNS.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index 55b209f9bd..922a3c5f3f 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -54,10 +54,10 @@ using clsLEAMDNSHost = esp8266::experimental::clsLEAMDNSHost; #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) // Maps the implementation to use to the global namespace type -//using MDNSResponder = Legacy_MDNSResponder::MDNSResponder; // Legacy -//using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA +//using MDNSResponder = Legacy_MDNSResponder::MDNSResponder; // Legacy +using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA //using MDNSResponder = experimental::MDNSImplementation::clsLEAMDNSHost_Legacy; // LEAv2Compat -using MDNSResponder = clsLEAMDNSHost; // LEAv2 +//using MDNSResponder = clsLEAMDNSHost; // LEAv2 extern MDNSResponder MDNS; #endif From bd6b0eb25c01889983605de7a2aaed1e0e91b41f Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 20 Aug 2020 16:29:07 +0200 Subject: [PATCH 083/152] style and fixes for CI --- .../LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 4 +- .../mDNS_ServiceMonitor_v2.ino | 41 ++++++++++--------- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 2 + libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 2 +- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index f9a6b86e50..662cbd0cb8 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -52,7 +52,7 @@ 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. */ -#define MDNS2_EXPERIMENTAL +#define NO_GLOBAL_MDNS // our MDNS is defined below #include <ESP8266mDNS.h> #include <PolledTimeout.h> @@ -233,7 +233,7 @@ void setup(void) { hMDNSService->setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallback); } else { // Change hostname, use '-' as divider between base name and index - MDNS.setHostName(MDNSResponder::indexDomainName(p_pcDomainName, "-", 0)); + MDNS.setHostName(clsLEAMDNSHost::indexDomainName(p_pcDomainName, "-", 0)); } })) { Serial.println("mDNS-AP started"); diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino index a1e05b333e..85c3902f14 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino @@ -1,7 +1,7 @@ /* ESP8266 mDNS Responder Service Monitor - This example demonstrates two features of the LEA MDNSResponder: + This example demonstrates two features of the LEA clsLEAMDNSHost: 1. The host and service domain negotiation process that ensures the uniqueness of the finally choosen host and service domain name. 2. The dynamic MDNS service lookup/query feature. @@ -44,18 +44,18 @@ #include <ESP8266WebServer.h> /* - Include the MDNSResponder (the library needs to be included also) - As LEA MDNSResponder is experimantal in the ESP8266 environment currently, the - legacy MDNSResponder is defaulted in th include file. - There are two ways to access LEA MDNSResponder: + Include the clsLEAMDNSHost (the library needs to be included also) + As LEA clsLEAMDNSHost is experimental in the ESP8266 environment currently, the + legacy clsLEAMDNSHost is defaulted in th include file. + There are two ways to access LEA clsLEAMDNSHost: 1. Prepend every declaration and call to global declarations or functions with the namespace, like: - 'LEAmDNS:MDNSResponder::hMDNSService hMDNSService;' + 'LEAmDNS:clsLEAMDNSHost::hMDNSService hMDNSService;' This way is used in the example. But be careful, if the namespace declaration is missing somewhere, the call might go to the legacy implementation... 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. */ -#define MDNS2_EXPERIMENTAL +#define NO_GLOBAL_MDNS // our MDNS is defined below #include <ESP8266mDNS.h> /* @@ -63,11 +63,12 @@ */ #define SERVICE_PORT 80 // HTTP port +clsLEAMDNSHost MDNS; // MDNS responder char* pcHostDomain = 0; // Negociated host domain bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain -MDNSResponder::clsService* hMDNSService = 0; // The handle of the http service in the MDNS responder -MDNSResponder::clsQuery* hMDNSServiceQuery = 0; // The handle of the 'http.tcp' service query in the MDNS responder +clsLEAMDNSHost::clsService* hMDNSService = 0; // The handle of the http service in the MDNS responder +clsLEAMDNSHost::clsQuery* hMDNSServiceQuery = 0; // The handle of the 'http.tcp' service query in the MDNS responder const String cstrNoHTTPServices = "Currently no 'http.tcp' services in the local network!<br/>"; String strHTTPServices = cstrNoHTTPServices; @@ -90,28 +91,28 @@ bool setStationHostname(const char* p_pcHostname) { } -void MDNSServiceQueryCallback(const MDNSResponder::clsQuery& p_Query, - const MDNSResponder::clsQuery::clsAnswer& p_Answer, - MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, +void MDNSServiceQueryCallback(const clsLEAMDNSHost::clsQuery& p_Query, + const clsLEAMDNSHost::clsQuery::clsAnswer& p_Answer, + clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, bool p_bSetContent) { (void)p_Query; String answerInfo; switch (p_QueryAnswerTypeFlags) { - case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain): + case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain): answerInfo = "ServiceDomain " + String(p_Answer.m_ServiceDomain.c_str()); break; - case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort): + case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort): answerInfo = "HostDomainAndPort " + String(p_Answer.m_HostDomain.c_str()) + ":" + String(p_Answer.m_u16Port); break; - case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address): + case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address): answerInfo = "IP4Address "; for (auto ip : p_Answer.m_IPv4Addresses) { answerInfo += "- " + ip->m_IPAddress.toString(); }; break; - case static_cast<MDNSResponder::clsQuery::clsAnswer::typeQueryAnswerType>(MDNSResponder::clsQuery::clsAnswer::enuQueryAnswerType::Txts): + case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts): answerInfo = "TXT "; for (auto kv : p_Answer.m_Txts.m_Txts) { answerInfo += "\nkv : " + String(kv->m_pcKey) + " : " + String(kv->m_pcValue); @@ -129,7 +130,7 @@ void MDNSServiceQueryCallback(const MDNSResponder::clsQuery& p_Query, Probe result callback for Services */ -void serviceProbeResult(MDNSResponder::clsService& p_rMDNSService, +void serviceProbeResult(clsLEAMDNSHost::clsService& p_rMDNSService, const char* p_pcInstanceName, bool p_bProbeResult) { (void)p_rMDNSService; @@ -143,7 +144,7 @@ void serviceProbeResult(MDNSResponder::clsService& p_rMDNSService, If the domain is free, the host domain is set and the http service is added. If the domain is already used, a new name is created and the probing is - restarted via p_pMDNSResponder->setHostname(). + restarted via p_pclsLEAMDNSHost->setHostname(). */ @@ -188,7 +189,7 @@ void hostProbeResult(clsLEAMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p } } else { // Change hostname, use '-' as divider between base name and index - MDNS.setHostName(MDNSResponder::indexDomainName(p_pcDomainName.c_str(), "-", 0)); + MDNS.setHostName(clsLEAMDNSHost::indexDomainName(p_pcDomainName.c_str(), "-", 0)); } } @@ -270,7 +271,7 @@ void setup(void) { // Init the (currently empty) host domain string with 'esp8266' MDNS.begin("esp8266_v2"); /* - if ((!MDNSResponder::indexDomain(pcHostDomain, 0, "esp8266")) || + if ((!clsLEAMDNSHost::indexDomain(pcHostDomain, 0, "esp8266")) || (!MDNS.begin(pcHostDomain))) { Serial.println(" Error setting up MDNS responder!"); while (1) { // STOP diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index d090984232..5e4409a715 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -258,7 +258,9 @@ bool clsLEAMDNSHost::begin(const char* p_pcHostName, bool bResult = false; if (m_pUDPContext) + { close(); + } bResult = (setHostName(p_pcHostName)) && (_joinMulticastGroups()) && diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 01fe26b33e..af9b48c353 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -525,7 +525,7 @@ bool clsLEAMDNSHost_Legacy::removeServiceTxt(const hMDNSService p_hService, ? 0 : (clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr[p_hService]))) && ((pTxt = pService->findServiceTxt(p_pcKey))) - && (removeServiceTxt(p_hService, (const hMDNSTxt)pTxt))); + && (removeServiceTxt(p_hService, (hMDNSTxt)pTxt))); } /* From fd5d2771c676fcb4e23121d0a2cf65691be949cc Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 20 Aug 2020 16:39:51 +0200 Subject: [PATCH 084/152] remove lwIP-1.4 specifics --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 12 +------ .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 4 --- .../ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 31 ------------------- libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h | 18 ----------- 4 files changed, 1 insertion(+), 64 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 5e4409a715..d2997648d6 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -940,13 +940,7 @@ bool clsLEAMDNSHost::_joinMulticastGroups(void) } } - if ( -#if LWIP_VERSION_MAJOR == 1 - (ERR_OK == igmp_joingroup(&pNetIf->ip_addr, &multicast_addr_V4)) -#else - (ERR_OK == igmp_joingroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4))) -#endif - ) + if ((ERR_OK == igmp_joingroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4)))) { bResult = true; } @@ -987,11 +981,7 @@ bool clsLEAMDNSHost::_leaveMulticastGroups() // Leave multicast group(s) #ifdef MDNS_IPV4_SUPPORT ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; -#if LWIP_VERSION_MAJOR == 1 - if (ERR_OK != igmp_leavegroup(ip_2_ip4(pNetIf->ip_addr), ip_2_ip4(&multicast_addr_V4))) -#else if (ERR_OK != igmp_leavegroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4))) -#endif { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 3e4d455b6a..07bad03583 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -641,11 +641,7 @@ IPAddress clsLEAMDNSHost::_getResponderIPAddress(netif* pNetIf, enuIPProtocolTyp #ifdef MDNS_IPV4_SUPPORT if (enuIPProtocolType::V4 == p_IPProtocolType) { -#if LWIP_VERSION_MAJOR == 1 - ipResponder = ip_2_ip4(pNetIf->ip_addr); -#else ipResponder = netif_ip_addr4(pNetIf); -#endif } #endif #ifdef MDNS_IPV6_SUPPORT diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index d3ae03ad1f..def32bdea7 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -256,37 +256,6 @@ const char* clsLEAMDNSHost::clsBackbone::_DH(void) const #endif -#if LWIP_VERSION_MAJOR == 1 - -/* - netif_get_by_index - - Extracted (and slightly changed) from: https://github.com/yarrick/lwip/blob/master/src/core/netif.c -*/ -extern "C" -struct netif* netif_get_by_index(u8_t idx) -{ - struct netif *netif; - - //LWIP_ASSERT_CORE_LOCKED(); - - if (idx != 0) // <- NETIF_NO_INDEX - { - for ((netif) = netif_list; (netif) != NULL; (netif) = (netif)->next) // <- NETIF_FOREACH(netif) - { - if (idx == netif_get_index(netif)) - { - return netif; /* found! */ - } - } - } - - return NULL; -} - -#endif // LWIP_VERSION_MAJOR == 1 - - } // namespace MDNSImplementation diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h b/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h index 0aa1712a81..a24cf62ba1 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h @@ -26,24 +26,6 @@ #define LEAMDNS2_LWIPDEFS_H #include <lwip/init.h> -#if LWIP_VERSION_MAJOR == 1 - -#include <lwip/mdns.h> // DNS_RRTYPE_xxx - -// cherry pick from lwip1 dns.c/mdns.c source files: -#define DNS_MQUERY_PORT 5353 -#define DNS_MQUERY_IPV4_GROUP_INIT IPAddress(224,0,0,251) /* resolver1.opendns.com */ -#define DNS_RRCLASS_ANY 255 /* any class */ - -#ifdef __cplusplus -extern "C" -#endif -struct netif* netif_get_by_index(u8_t idx); - -#else // lwIP > 1 - #include <lwip/prot/dns.h> // DNS_RRTYPE_xxx, DNS_MQUERY_PORT -#endif - #endif // LEAMDNS2_LWIPDEFS_H From 27225e792f694c6c54f09a8ecb0fb0b580625920 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 15:10:11 +0200 Subject: [PATCH 085/152] _P(PSTR()) --- .../ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp index d638bf209a..b94fb1f80b 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp @@ -171,17 +171,17 @@ const char* clsLEAMDNSHost::_RRType2Name(uint16_t p_u16RRType) const switch (p_u16RRType & (~0x8000)) // Topmost bit might carry 'cache flush' flag { #ifdef MDNS_IPV4_SUPPORT - case DNS_RRTYPE_A: strcpy(acRRName, "A"); break; + case DNS_RRTYPE_A: strcpy_P(acRRName, PSTR("A")); break; #endif - case DNS_RRTYPE_PTR: strcpy(acRRName, "PTR"); break; - case DNS_RRTYPE_TXT: strcpy(acRRName, "TXT"); break; + case DNS_RRTYPE_PTR: strcpy_P(acRRName, PSTR("PTR")); break; + case DNS_RRTYPE_TXT: strcpy_P(acRRName, PSTR("TXT")); break; #ifdef MDNS_IPV6_SUPPORT - case DNS_RRTYPE_AAAA: strcpy(acRRName, "AAAA"); break; + case DNS_RRTYPE_AAAA: strcpy_P(acRRName, PSTR("AAAA")); break; #endif - case DNS_RRTYPE_SRV: strcpy(acRRName, "SRV"); break; - case clsConsts::u8DNS_RRTYPE_NSEC: strcpy(acRRName, "NSEC"); break; - case DNS_RRTYPE_ANY: strcpy(acRRName, "ANY"); break; - default: sprintf(acRRName, "Unknown(0x%04X)", p_u16RRType); // MAX 15! + case DNS_RRTYPE_SRV: strcpy_P(acRRName, PSTR("SRV")); break; + case clsConsts::u8DNS_RRTYPE_NSEC: strcpy_P(acRRName, PSTR("NSEC")); break; + case DNS_RRTYPE_ANY: strcpy_P(acRRName, PSTR("ANY")); break; + default: sprintf_P(acRRName, PSTR("Unknown(0x%04X)", p_u16RRType); // MAX 15! } return acRRName; } @@ -198,11 +198,11 @@ const char* clsLEAMDNSHost::_RRClass2String(uint16_t p_u16RRClass, if (p_u16RRClass & 0x0001) { - strcat(acClassString, "IN "); // 3 + strcat_P(acClassString, PSTR("IN ")); // 3 } if (p_u16RRClass & 0x8000) { - strcat(acClassString, (p_bIsQuery ? "UNICAST " : "FLUSH ")); // 8/6 + strcat_P(acClassString, (p_bIsQuery ? PSTR("UNICAST ") : PSTR("FLUSH "))); // 8/6 } return acClassString; // 11 @@ -219,44 +219,44 @@ const char* clsLEAMDNSHost::_replyFlags2String(uint32_t p_u32ReplyFlags) const *acFlagsString = 0; if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::A)) { - strcat(acFlagsString, "A "); // 2 + strcat_P(acFlagsString, PSTR("A ")); // 2 } if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::PTR_IPv4)) { - strcat(acFlagsString, "PTR_IPv4 "); // 7 + strcat_P(acFlagsString, PSTR("PTR_IPv4 ")); // 7 } if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::PTR_IPv6)) { - strcat(acFlagsString, "PTR_IPv6 "); // 7 + strcat_P(acFlagsString, PSTR("PTR_IPv6 ")); // 7 } if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::AAAA)) { - strcat(acFlagsString, "AAAA "); // 5 + strcat_P(acFlagsString, PSTR("AAAA ")); // 5 } if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::PTR_TYPE)) { - strcat(acFlagsString, "PTR_TYPE "); // 9 + strcat_P(acFlagsString, PSTR("PTR_TYPE ")); // 9 } if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::PTR_NAME)) { - strcat(acFlagsString, "PTR_NAME "); // 9 + strcat_P(acFlagsString, PSTR("PTR_NAME ")); // 9 } if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::TXT)) { - strcat(acFlagsString, "TXT "); // 4 + strcat_P(acFlagsString, PSTR("TXT ")); // 4 } if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::SRV)) { - strcat(acFlagsString, "SRV "); // 4 + strcat_P(acFlagsString, PSTR("SRV ")); // 4 } if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::NSEC)) { - strcat(acFlagsString, "NSEC "); // 5 + strcat_P(acFlagsString, PSTR("NSEC ")); // 5 } if (0 == p_u32ReplyFlags) { - strcpy(acFlagsString, "none"); + strcpy_P(acFlagsString, PSTR("none")); } // Remove trailing spaces @@ -281,35 +281,35 @@ const char* clsLEAMDNSHost::_NSECBitmap2String(const clsNSECBitmap* p_pNSECBitma #ifdef MDNS_IPV4_SUPPORT if (p_pNSECBitmap->getBit(DNS_RRTYPE_A)) { - strcat(acFlagsString, "A "); // 2 + strcat_P(acFlagsString, PSTR("A ")); // 2 } #endif if (p_pNSECBitmap->getBit(DNS_RRTYPE_PTR)) { - strcat(acFlagsString, "PTR "); // 4 + strcat_P(acFlagsString, PSTR("PTR ")); // 4 } #ifdef MDNS_IPV6_SUPPORT if (p_pNSECBitmap->getBit(DNS_RRTYPE_AAAA)) { - strcat(acFlagsString, "AAAA "); // 5 + strcat_P(acFlagsString, PSTR("AAAA ")); // 5 } #endif if (p_pNSECBitmap->getBit(DNS_RRTYPE_TXT)) { - strcat(acFlagsString, "TXT "); // 4 + strcat_P(acFlagsString, PSTR("TXT ")); // 4 } if (p_pNSECBitmap->getBit(DNS_RRTYPE_SRV)) { - strcat(acFlagsString, "SRV "); // 4 + strcat_P(acFlagsString, PSTR("SRV ")); // 4 } if (p_pNSECBitmap->getBit(clsConsts::u8DNS_RRTYPE_NSEC)) { - strcat(acFlagsString, "NSEC "); // 5 + strcat_P(acFlagsString, PSTR("NSEC ")); // 5 } if (!*acFlagsString) { - strcpy(acFlagsString, "none"); + strcpy_P(acFlagsString, PSTR("none")); } return acFlagsString; // 31 From 32cb828143d722658cf384366e4b66bd61be0846 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 15:16:24 +0200 Subject: [PATCH 086/152] sprintf always -> strcpy once --- libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index def32bdea7..852068df19 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -246,11 +246,11 @@ bool clsLEAMDNSHost::clsBackbone::_processUDPInput(void) */ const char* clsLEAMDNSHost::clsBackbone::_DH(void) const { - static char acBuffer[24]; - - *acBuffer = 0; - sprintf_P(acBuffer, PSTR("[mDNS::backbone]")); - + static char acBuffer[20] = { 0, }; + if (!acBuffer[0]) + { + strcpy_P(acBuffer, PSTR("[mDNS::backbone]")); + } return acBuffer; } From 6fede9be325706c0646b24a52a5e0036712e5ca2 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 15:18:02 +0200 Subject: [PATCH 087/152] comment --- .../examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index 662cbd0cb8..4007979fa2 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -41,9 +41,9 @@ // uses API MDNSApiVersion::LEAv2 /* - Include the clsLEAMDNSHost (the library needs to be included also) + Include the clsLEAMDNSHost (the library needs also to be included) As LEA clsLEAMDNSHost is experimantal in the ESP8266 environment currently, the - legacy clsLEAMDNSHost is defaulted in th include file. + legacy clsLEAMDNSHost is defaulted in the include file. There are two ways to access LEA clsLEAMDNSHost: 1. Prepend every declaration and call to global declarations or functions with the namespace, like: 'LEAmDNS::clsLEAMDNSHost::hMDNSService hMDNSService;' From 91166a227906d56fd7dc056fde60e3cd71e4b2f8 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 15:18:50 +0200 Subject: [PATCH 088/152] fix message --- .../examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index 4007979fa2..e71fd014a1 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -200,7 +200,7 @@ void setup(void) { nif->name[1], netif_get_index(nif)); })) { - Serial.println("Error: could not add useless informative callback\n"); + Serial.println("Error: could not add informative callback\n"); } WiFi.mode(WIFI_STA); From 57a2faf8e43408016c600f970f2e27209b52b6b7 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 15:23:13 +0200 Subject: [PATCH 089/152] fix host domain name and comment --- .../examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 2 +- .../LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index e71fd014a1..58b111c4b1 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -222,7 +222,7 @@ void setup(void) { setClock(); // Setup MDNS responder - // Init the (currently empty) host domain string with 'esp8266' + // Init the (currently empty) host domain string with 'leamdnsv2' if (MDNS.begin("leamdnsv2", [](clsLEAMDNSHost & p_rMDNSHost, const char* p_pcDomainName, bool p_bProbeResult)->void { if (p_bProbeResult) { diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino index 85c3902f14..bc061ceced 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino @@ -268,8 +268,8 @@ void setup(void) { // Setup MDNS responders MDNS.setProbeResultCallback(hostProbeResult); - // Init the (currently empty) host domain string with 'esp8266' - MDNS.begin("esp8266_v2"); + // Init the (currently empty) host domain string with 'leamdnsv2' + MDNS.begin("leamdnsv2"); /* if ((!clsLEAMDNSHost::indexDomain(pcHostDomain, 0, "esp8266")) || (!MDNS.begin(pcHostDomain))) { From 4b0f6e7676fc211bd2df4833f59ae9005b3c53e1 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 15:57:26 +0200 Subject: [PATCH 090/152] add TODO --- .../mDNS_ServiceMonitor_v2.ino | 41 ++++--------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino index bc061ceced..b14df03ba2 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino @@ -29,6 +29,8 @@ */ +// THIS IS A WORK IN PROGRESS: some TODOs need completion + #ifndef STASSID #define STASSID "ssid" #define STAPSK "psk" @@ -206,31 +208,9 @@ void handleHTTPRequest() { s += WiFi.hostname() + ".local at " + server.client().localIP().toString() + "</h3></head>"; s += "<br/><h4>Local HTTP services are :</h4>"; s += "<ol>"; - /* - for (auto info : MDNS.answerInfo(hMDNSServiceQuery)) { - s += "<li>"; - s += info.serviceDomain(); - if (info.hostDomainAvailable()) { - s += "<br/>Hostname: "; - s += String(info.hostDomain()); - s += (info.hostPortAvailable()) ? (":" + String(info.hostPort())) : ""; - } - if (info.IP4AddressAvailable()) { - s += "<br/>IP4:"; - for (auto ip : info.IP4Adresses()) { - s += " " + ip.toString(); - } - } - if (info.txtAvailable()) { - s += "<br/>TXT:<br/>"; - for (auto kv : info.keyValues()) { - s += "\t" + String(kv.first) + " : " + String(kv.second) + "<br/>"; - } - } - s += "</li>"; - } - */ + // TODO: list services + s += "</ol><br/>"; Serial.println("Sending 200"); @@ -245,6 +225,10 @@ void setup(void) { Serial.begin(115200); Serial.setDebugOutput(false); + Serial.println(""); + Serial.println("THIS IS A WORK IN PROGRESS: some TODOs need completion"); + Serial.println(""); + // Connect to WiFi network WiFi.mode(WIFI_AP_STA); WiFi.softAP(APSSID); @@ -270,15 +254,6 @@ void setup(void) { // Init the (currently empty) host domain string with 'leamdnsv2' MDNS.begin("leamdnsv2"); - /* - if ((!clsLEAMDNSHost::indexDomain(pcHostDomain, 0, "esp8266")) || - (!MDNS.begin(pcHostDomain))) { - Serial.println(" Error setting up MDNS responder!"); - while (1) { // STOP - delay(1000); - } - } - */ Serial.println("MDNS responder started"); // Start HTTP server From 0b1cbbab27742e0c871f676841d46ee954ab4f02 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 15:59:57 +0200 Subject: [PATCH 091/152] remove comment --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index d2997648d6..a85d495771 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -111,7 +111,6 @@ namespace experimental if no default is given, 'ESP8266' is used. */ -//static clsLEAMDNSHost::fnProbeResultCallback clsLEAMDNSHost::stProbeResultCallback = nullptr; From 07ca39513b9062dcf567633255b129804d61deee Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 16:03:14 +0200 Subject: [PATCH 092/152] use lower case esp8266 --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index a85d495771..fa84a3b18c 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -108,7 +108,7 @@ namespace experimental is incremented. If not, the delimiter and index '2' is added. If 'p_pcDomainName' is empty (==0), the given default name 'p_pcDefaultDomainName' is used, - if no default is given, 'ESP8266' is used. + if no default is given, 'esp8266' is used. */ @@ -161,7 +161,7 @@ const char* clsLEAMDNSHost::indexDomainName(const char* p_pcDomainName, else { // No given domain, use base or default - const char* cpcDefaultName = (p_pcDefaultDomainName ? : "ESP8266"); + const char* cpcDefaultName = (p_pcDefaultDomainName ? : "esp8266"); size_t stLength = strlen(cpcDefaultName) + 1; // '\0' strncpy(acResultDomainName, cpcDefaultName, stLength); } From 2839d592821d98cb3f7961ea63677402d1de585f Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 16:06:35 +0200 Subject: [PATCH 093/152] fix strncpy size --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index fa84a3b18c..2d6ac39f81 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -162,8 +162,7 @@ const char* clsLEAMDNSHost::indexDomainName(const char* p_pcDomainName, { // No given domain, use base or default const char* cpcDefaultName = (p_pcDefaultDomainName ? : "esp8266"); - size_t stLength = strlen(cpcDefaultName) + 1; // '\0' - strncpy(acResultDomainName, cpcDefaultName, stLength); + strncpy(acResultDomainName, cpcDefaultName, sizeof(acResultDomainName) - 1); } DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[mDNS] indexDomainName: From '%s' to '%s'\n"), (p_pcDomainName ? : ""), acResultDomainName);); return acResultDomainName; From eda2e0b333e11c284a4634104e6826c2a55129d9 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 16:16:21 +0200 Subject: [PATCH 094/152] astyle has issues with lambdas: rework logic to hide formatting issue --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 44 +++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 2d6ac39f81..9e3458b245 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -266,35 +266,35 @@ bool clsLEAMDNSHost::begin(const char* p_pcHostName, ((m_pUDPContext = _allocBackbone())) && (restart()); - if (bResult) + if (!bResult) { - if (!LwipIntf::stateUpCB([this](netif * nif) + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s begin: FAILED for '%s'!\n"), _DH(), (p_pcHostName ? : "-"));); + return false; + } + + bResult = LwipIntf::stateUpCB([this](netif * nif) { (void)nif; - // This called after a new interface appears: - // resend announces on all available interfaces. - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s a new interface %c%c/%d is up, restarting mDNS\n"), - _DH(), nif->name[0], nif->name[1], netif_get_index(nif));); - if (restart()) - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s restart: success!\n"), _DH())); - } - else - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s restart failed!\n"), _DH())); - } - // No need to react when an interface disappears, - // because mDNS always loop on all available interfaces. - })) + // This called after a new interface appears: + // resend announces on all available interfaces. + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s a new interface %c%c/%d is up, restarting mDNS\n"), + _DH(), nif->name[0], nif->name[1], netif_get_index(nif));); + if (restart()) { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s begin: could not add netif status callback\n"), _DH())); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s restart: success!\n"), _DH())); } - } - else + else + { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s restart failed!\n"), _DH())); + } + // No need to react when an interface disappears, + // because mDNS always loop on all available interfaces. + }); + + if (!bResult) { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s begin: FAILED for '%s'!\n"), _DH(), (p_pcHostName ? : "-"));); + DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s begin: could not add netif status callback\n"), _DH())); } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s begin: %s to init with hostname %s!\n"), _DH(), (bResult ? "Succeeded" : "FAILED"), (p_pcHostName ? : "-"));); return bResult; } From 3c34fca178fc443a99dea0220c5b5033df2b43de Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 16:24:30 +0200 Subject: [PATCH 095/152] remove old code --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 9e3458b245..0b09181492 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -466,20 +466,12 @@ clsLEAMDNSHost::clsService* clsLEAMDNSHost::addService(const char* p_pcInstanceN */ bool clsLEAMDNSHost::removeService(clsLEAMDNSHost::clsService* p_pService) { - bool bResult = false; + bool bResult = true; if (p_pService && (m_Services.end() != std::find(m_Services.begin(), m_Services.end(), p_pService))) { - bResult = _announceService(*p_pService, false); - /* - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) - if (netif_is_up(pNetIf) && - (_announceService(pNetIf, *p_pService, false))) - { - bResult = true; - } - */ + bResult = bResult && _announceService(*p_pService, false); } if (bResult) From 29a2a88190a373d9cc46e00891f5e3ddc99f604f Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 16:24:45 +0200 Subject: [PATCH 096/152] remove service on request --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 0b09181492..8714f15124 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -474,11 +474,9 @@ bool clsLEAMDNSHost::removeService(clsLEAMDNSHost::clsService* p_pService) bResult = bResult && _announceService(*p_pService, false); } - if (bResult) - { - m_Services.remove(p_pService); - delete p_pService; - } + m_Services.remove(p_pService); + delete p_pService; + DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _removeService: FAILED!\n"), _DH(p_pService));); return bResult; } From 357a3438c09bdbf99083f3f2acd9646d00c3789a Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 16:26:29 +0200 Subject: [PATCH 097/152] remove dead code --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 8714f15124..506e87113c 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -961,10 +961,6 @@ bool clsLEAMDNSHost::_leaveMulticastGroups() if (netif_is_up(pNetIf)) { bResult = true; - /* _resetProbeStatus(false); // Stop probing - _releaseQueries(); - _releaseServices(); - _releaseHostName();*/ // Leave multicast group(s) #ifdef MDNS_IPV4_SUPPORT From 01c1774e93e7a25e9e352c3763a293c00c2a8d2b Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 16:28:34 +0200 Subject: [PATCH 098/152] simplify use of tolower() --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 506e87113c..b690423aeb 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -1026,7 +1026,7 @@ bool clsLEAMDNSHost::_allocDomainName(const char* p_pcNewDomainName, size_t i = 0; for (; i < stLength; ++i) { - p_rpcDomainName[i] = (isupper(p_pcNewDomainName[i]) ? tolower(p_pcNewDomainName[i]) : p_pcNewDomainName[i]); + p_rpcDomainName[i] = tolower(p_pcNewDomainName[i]); } p_rpcDomainName[i] = 0; #else From 3b1447c608556bd1f2d8b9f2d209e952ac79fe35 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 16:31:09 +0200 Subject: [PATCH 099/152] strncpy: fix max len --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index b690423aeb..e0a77e87ba 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -1030,7 +1030,7 @@ bool clsLEAMDNSHost::_allocDomainName(const char* p_pcNewDomainName, } p_rpcDomainName[i] = 0; #else - strncpy(p_rpcDomainName, p_pcNewDomainName, (stLength + 1)); + strncpy(p_rpcDomainName, p_pcNewDomainName, stLength); #endif } } From a296be0c13dc7470141c2788747904dd5e45962d Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 16:40:53 +0200 Subject: [PATCH 100/152] knwon typo --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index 00e260cd76..48083933d3 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1482,7 +1482,7 @@ bool clsLEAMDNSHost::_hasProbesWaitingForAnswers(void) const - (eg. esp8266.local) To allow 'tiebreaking' (see '_parseQuery'), the answers for these questions are delivered in - the 'knwon answers' section of the query. + the 'known answers' section of the query. Host domain: - A/AAAA (eg. esp8266.esp -> 192.168.2.120) @@ -1536,7 +1536,7 @@ bool clsLEAMDNSHost::_sendHostProbe() - (eg. MyESP._http._tcp.local). To allow 'tiebreaking' (see '_parseQuery'), the answers for these questions are delivered in - the 'knwon answers' section of the query. + the 'known answers' section of the query. Service domain: - SRV (eg. MyESP._http._tcp.local -> 5000 esp8266.local) - PTR NAME (eg. _http._tcp.local -> MyESP._http._tcp.local) (TODO: Check if needed, maybe TXT is better) From 174e20ecf3c76527c74aaec3c114b9c4a3becc9b Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 16:42:16 +0200 Subject: [PATCH 101/152] fix bResult logic --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index 48083933d3..4d5404721c 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1585,7 +1585,7 @@ bool clsLEAMDNSHost::_sendServiceProbe(clsService& p_rService) */ bool clsLEAMDNSHost::_cancelProbingForHost(void) { - bool bResult = false; + bool bResult; m_ProbeInformation.clear(false); @@ -1594,7 +1594,7 @@ bool clsLEAMDNSHost::_cancelProbingForHost(void) for (clsService* pService : m_Services) { - bResult = _cancelProbingForService(*pService); + bResult = bResult && _cancelProbingForService(*pService); } return bResult; } From f3655f9cacc76595fe730dae96dfefee0f13cb9b Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 16:49:48 +0200 Subject: [PATCH 102/152] m_u8SentCount -> m_u32SentCount --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 4 +- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 4 +- .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 38 +++++++++---------- .../ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 8 ++-- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index e0a77e87ba..46950cc0ea 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -1267,7 +1267,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery( if (_sendQuery(*pMDNSQuery)) { - pMDNSQuery->m_u8SentCount = 1; + pMDNSQuery->m_u32SentCount = 1; pMDNSQuery->m_ResendTimeout.reset(clsConsts::u32DynamicQueryResendDelay); } else @@ -1296,7 +1296,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installDomainQuery( if (_sendQuery(*pQuery)) { - pQuery->m_u8SentCount = 1; + pQuery->m_u32SentCount = 1; pQuery->m_ResendTimeout.reset(clsConsts::u32DynamicQueryResendDelay); } else diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 43120be709..97de2ff2a3 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -383,7 +383,7 @@ class clsLEAMDNSHost }; enuProbingStatus m_ProbingStatus; - uint8_t m_u8SentCount; // Used for probes and announcements + uint32_t m_u32SentCount; // Used for probes and announcements esp8266::polledTimeout::oneShot m_Timeout; // Used for probes and announcements bool m_bConflict; bool m_bTiebreakNeeded; @@ -1145,7 +1145,7 @@ class clsLEAMDNSHost QueryCallbackAnswerFn m_fnCallbackAnswer; QueryCallbackAccessorFn m_fnCallbackAccessor; bool m_bStaticQuery; - uint8_t m_u8SentCount; + uint32_t m_u32SentCount; esp8266::polledTimeout::oneShot m_ResendTimeout; bool m_bAwaitingAnswers; clsAnswer::list m_Answers; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index 4d5404721c..3177bea50d 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1315,14 +1315,14 @@ bool clsLEAMDNSHost::_updateProbeStatus() else if ((clsProbeInformation_Base::enuProbingStatus::InProgress == m_ProbeInformation.m_ProbingStatus) && // Probing AND (m_ProbeInformation.m_Timeout.expired())) // Time for next probe { - if (clsConsts::u32ProbeCount > m_ProbeInformation.m_u8SentCount) + if (clsConsts::u32ProbeCount > m_ProbeInformation.m_u32SentCount) { // Send next probe if ((bResult = _sendHostProbe())) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Did sent host probe for '%s.local'\n\n"), _DH(), (m_pcHostName ? : ""));); m_ProbeInformation.m_Timeout.reset(clsConsts::u32ProbeDelay); - ++m_ProbeInformation.m_u8SentCount; + ++m_ProbeInformation.m_u32SentCount; } } else @@ -1335,7 +1335,7 @@ bool clsLEAMDNSHost::_updateProbeStatus() _callHostProbeResultCallback(true); // Prepare to announce host - m_ProbeInformation.m_u8SentCount = 0; + m_ProbeInformation.m_u32SentCount = 0; m_ProbeInformation.m_Timeout.reset(clsConsts::u32AnnounceDelay); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Prepared host announcing.\n\n"), _DH());); } @@ -1347,12 +1347,12 @@ bool clsLEAMDNSHost::_updateProbeStatus() if ((bResult = _announce(true, false))) { // Don't announce services here - ++m_ProbeInformation.m_u8SentCount; // 1.. + ++m_ProbeInformation.m_u32SentCount; // 1.. - if (clsConsts::u32AnnounceCount > m_ProbeInformation.m_u8SentCount) + if (clsConsts::u32AnnounceCount > m_ProbeInformation.m_u32SentCount) { - m_ProbeInformation.m_Timeout.reset(clsConsts::u32AnnounceDelay * pow(2, (m_ProbeInformation.m_u8SentCount - 1))); // 2^(0..) -> 1, 2, 4, ... - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Announcing host '%s.local' (%lu).\n\n"), _DH(), (m_pcHostName ? : ""), m_ProbeInformation.m_u8SentCount);); + m_ProbeInformation.m_Timeout.reset(clsConsts::u32AnnounceDelay * pow(2, (m_ProbeInformation.m_u32SentCount - 1))); // 2^(0..) -> 1, 2, 4, ... + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Announcing host '%s.local' (%lu).\n\n"), _DH(), (m_pcHostName ? : ""), m_ProbeInformation.m_u32SentCount);); } else { @@ -1380,14 +1380,14 @@ bool clsLEAMDNSHost::_updateProbeStatus() else if ((clsProbeInformation_Base::enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing AND (pService->m_ProbeInformation.m_Timeout.expired())) // Time for next probe { - if (clsConsts::u32ProbeCount > pService->m_ProbeInformation.m_u8SentCount) + if (clsConsts::u32ProbeCount > pService->m_ProbeInformation.m_u32SentCount) { // Send next probe if ((bResult = _sendServiceProbe(*pService))) { - DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Did sent service probe for '%s' (%u)\n\n"), _DH(), _service2String(pService), (pService->m_ProbeInformation.m_u8SentCount + 1));); + DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Did sent service probe for '%s' (%u)\n\n"), _DH(), _service2String(pService), (pService->m_ProbeInformation.m_u32SentCount + 1));); pService->m_ProbeInformation.m_Timeout.reset(clsConsts::u32ProbeDelay); - ++pService->m_ProbeInformation.m_u8SentCount; + ++pService->m_ProbeInformation.m_u32SentCount; } } else @@ -1400,7 +1400,7 @@ bool clsLEAMDNSHost::_updateProbeStatus() _callServiceProbeResultCallback(*pService, true); // Prepare to announce service - pService->m_ProbeInformation.m_u8SentCount = 0; + pService->m_ProbeInformation.m_u32SentCount = 0; pService->m_ProbeInformation.m_Timeout.reset(clsConsts::u32AnnounceDelay); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Prepared service announcing.\n\n"), _DH());); } @@ -1412,12 +1412,12 @@ bool clsLEAMDNSHost::_updateProbeStatus() if ((bResult = _announceService(*pService))) { // Announce service - ++pService->m_ProbeInformation.m_u8SentCount; // 1.. + ++pService->m_ProbeInformation.m_u32SentCount; // 1.. - if (clsConsts::u32AnnounceCount > pService->m_ProbeInformation.m_u8SentCount) + if (clsConsts::u32AnnounceCount > pService->m_ProbeInformation.m_u32SentCount) { - pService->m_ProbeInformation.m_Timeout.reset(clsConsts::u32AnnounceDelay * pow(2, (pService->m_ProbeInformation.m_u8SentCount - 1))); // 2^(0..) -> 1, 2, 4, ... - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Announcing service '%s' (%lu)\n\n"), _DH(), _service2String(pService), pService->m_ProbeInformation.m_u8SentCount);); + pService->m_ProbeInformation.m_Timeout.reset(clsConsts::u32AnnounceDelay * pow(2, (pService->m_ProbeInformation.m_u32SentCount - 1))); // 2^(0..) -> 1, 2, 4, ... + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: Announcing service '%s' (%lu)\n\n"), _DH(), _service2String(pService), pService->m_ProbeInformation.m_u32SentCount);); } else { @@ -1463,14 +1463,14 @@ bool clsLEAMDNSHost::_resetProbeStatus(bool p_bRestart /*= true*/) bool clsLEAMDNSHost::_hasProbesWaitingForAnswers(void) const { bool bResult = ((clsProbeInformation_Base::enuProbingStatus::InProgress == m_ProbeInformation.m_ProbingStatus) && // Probing - (0 < m_ProbeInformation.m_u8SentCount)); // And really probing + (0 < m_ProbeInformation.m_u32SentCount)); // And really probing for (clsService::list::const_iterator it = m_Services.cbegin(); ((!bResult) && (it != m_Services.cend())); it++) { clsService* pService = *it; bResult = ((clsProbeInformation_Base::enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing - (0 < pService->m_ProbeInformation.m_u8SentCount)); // And really probing + (0 < pService->m_ProbeInformation.m_u32SentCount)); // And really probing } return bResult; } @@ -1801,8 +1801,8 @@ bool clsLEAMDNSHost::_checkQueryCache() if ((bResult = _sendQuery(*pQuery))) { // The re-query rate is increased to more than one hour (RFC 6762 5.2) - ++pQuery->m_u8SentCount; - uint32_t u32NewDelay = (clsConsts::u32DynamicQueryResendDelay * pow(2, std::min((pQuery->m_u8SentCount - 1), 12))); + ++pQuery->m_u32SentCount; + uint32_t u32NewDelay = (clsConsts::u32DynamicQueryResendDelay * pow(2, std::min((pQuery->m_u32SentCount - 1), (uint32_t)12))); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Next query in %u seconds!\n"), _DH(), (u32NewDelay));); pQuery->m_ResendTimeout.reset(u32NewDelay); } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index 3cae0ca3bc..95bc34c322 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -702,7 +702,7 @@ bool clsLEAMDNSHost::clsServiceTxts::operator!=(const clsServiceTxts& p_Other) c */ clsLEAMDNSHost::clsProbeInformation_Base::clsProbeInformation_Base(void) : m_ProbingStatus(enuProbingStatus::WaitingForData), - m_u8SentCount(0), + m_u32SentCount(0), m_Timeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()), m_bConflict(false), m_bTiebreakNeeded(false) @@ -715,7 +715,7 @@ clsLEAMDNSHost::clsProbeInformation_Base::clsProbeInformation_Base(void) bool clsLEAMDNSHost::clsProbeInformation_Base::clear(void) { m_ProbingStatus = enuProbingStatus::WaitingForData; - m_u8SentCount = 0; + m_u32SentCount = 0; m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); m_bConflict = false; m_bTiebreakNeeded = false; @@ -3055,7 +3055,7 @@ clsLEAMDNSHost::clsQuery::clsQuery(const enuQueryType p_QueryType) m_fnCallbackAnswer(0), m_fnCallbackAccessor(0), m_bStaticQuery(false), - m_u8SentCount(0), + m_u32SentCount(0), m_ResendTimeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()), m_bAwaitingAnswers(true) { @@ -3082,7 +3082,7 @@ bool clsLEAMDNSHost::clsQuery::clear(void) m_fnCallbackAnswer = 0; m_fnCallbackAccessor = 0; m_bStaticQuery = false; - m_u8SentCount = 0; + m_u32SentCount = 0; m_ResendTimeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()); m_bAwaitingAnswers = true; for (clsAnswer* pAnswer : m_Answers) From b8383e504145cb8f24b5e623ae1c9bfcb1ba4175 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 16:51:05 +0200 Subject: [PATCH 103/152] relavent -> relevant --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 2 +- libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index 3177bea50d..88356f40e1 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -2062,7 +2062,7 @@ bool clsLEAMDNSHost::_checkQueryCache() /* clsLEAmDNS2_Host::_replyMaskForHost - Determines the relavant host answers for the given question. + Determines the relevant host answers for the given question. - A question for the hostname (eg. esp8266.local) will result in an A/AAAA (eg. 192.168.2.129) reply. - A question for the reverse IP address (eg. 192-168.2.120.inarpa.arpa) will result in an PTR_IPv4 (eg. esp8266.local) reply. diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp index 0e46651d5f..03ade10c78 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp @@ -1983,7 +1983,7 @@ bool MDNSResponder::_checkServiceQueryCache(void) /* MDNSResponder::_replyMaskForHost - Determines the relavant host answers for the given question. + Determines the relevant host answers for the given question. - A question for the hostname (eg. esp8266.local) will result in an A/AAAA (eg. 192.168.2.129) reply. - A question for the reverse IP address (eg. 192-168.2.120.inarpa.arpa) will result in an PTR_IP4 (eg. esp8266.local) reply. From bdcfa73c744689e035799ac3361d08e803538cbb Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 17:16:04 +0200 Subject: [PATCH 104/152] fix strncpy --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index 95bc34c322..06bfa32039 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -547,12 +547,12 @@ bool clsLEAMDNSHost::clsServiceTxts::c_str(char* p_pcBuffer) { *pcCursor++ = ';'; } - strncpy(pcCursor, pTxt->m_pcKey, stLength); pcCursor[stLength] = 0; + strcpy(pcCursor, pTxt->m_pcKey); pcCursor += stLength; *pcCursor++ = '='; if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) { - strncpy(pcCursor, pTxt->m_pcValue, stLength); pcCursor[stLength] = 0; + strcpy(pcCursor, pTxt->m_pcValue); pcCursor += stLength; } } @@ -561,7 +561,6 @@ bool clsLEAMDNSHost::clsServiceTxts::c_str(char* p_pcBuffer) break; } } - *pcCursor++ = 0; } return bResult; } From 69834c1b14b6b041586f22bb3d1610f5ab3b20d4 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 17:20:34 +0200 Subject: [PATCH 105/152] memcpy->strcpy to always have the ending \0 --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index 06bfa32039..640cc09978 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -593,7 +593,7 @@ size_t clsLEAMDNSHost::clsServiceTxts::bufferLength(void) const } /* - clsLEAMDNSHost::clsServiceTxts::toBuffer + clsLEAMDNSHost::clsServiceTxts::buffer */ bool clsLEAMDNSHost::clsServiceTxts::buffer(char* p_pcBuffer) @@ -611,12 +611,12 @@ bool clsLEAMDNSHost::clsServiceTxts::buffer(char* p_pcBuffer) size_t stLength; if ((bResult = (0 != (stLength = (pTxt->m_pcKey ? strlen(pTxt->m_pcKey) : 0))))) { - memcpy(p_pcBuffer, pTxt->m_pcKey, stLength); + strcpy(p_pcBuffer, pTxt->m_pcKey); p_pcBuffer += stLength; *p_pcBuffer++ = '='; if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) { - memcpy(p_pcBuffer, pTxt->m_pcValue, stLength); + strcpy(p_pcBuffer, pTxt->m_pcValue); p_pcBuffer += stLength; } } @@ -625,7 +625,6 @@ bool clsLEAMDNSHost::clsServiceTxts::buffer(char* p_pcBuffer) break; } } - *p_pcBuffer++ = 0; } return bResult; } From 42b05ce04cc5b41b38485b3fce1ca1093593e608 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 17:28:16 +0200 Subject: [PATCH 106/152] remove redundant strcmp --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index 640cc09978..d90b8af28e 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -659,8 +659,8 @@ bool clsLEAMDNSHost::clsServiceTxts::compare(const clsLEAMDNSHost::clsServiceTxt if (!((bResult = ((pTxt) && (pOtherTxt->m_pcValue) && (pTxt->m_pcValue) && - (strlen(pOtherTxt->m_pcValue) == strlen(pTxt->m_pcValue)) && - (0 == strcmp(pOtherTxt->m_pcValue, pTxt->m_pcValue)))))) + (strlen(pOtherTxt->m_pcValue) == strlen(pTxt->m_pcValue)) /* && + redundant: (0 == strcmp(pOtherTxt->m_pcValue, pTxt->m_pcValue)) */ )))) { break; } From ab2d4372576d7dc3de186a0c115927557ff17f1d Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 17:30:19 +0200 Subject: [PATCH 107/152] simplify fix strcpy --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index d90b8af28e..af1b1271fe 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -830,9 +830,7 @@ bool clsLEAMDNSHost::clsService::setInstanceName(const char* p_pcInstanceName) { if ((bResult = (0 != (m_pcInstanceName = new char[stLength + 1])))) { - strncpy(m_pcInstanceName, p_pcInstanceName, stLength); - m_pcInstanceName[stLength] = 0; - + strcpy(m_pcInstanceName, p_pcInstanceName); _resetProbeStatus(); } } From 60f6e157bae15b49fa2e02796c8a349efc063a20 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 17:31:56 +0200 Subject: [PATCH 108/152] ditto --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index af1b1271fe..e8d81a0873 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -890,9 +890,7 @@ bool clsLEAMDNSHost::clsService::setType(const char* p_pcType) { if ((bResult = (0 != (m_pcType = new char[stLength + 1])))) { - strncpy(m_pcType, p_pcType, stLength); - m_pcType[stLength] = 0; - + strcpy(m_pcType, p_pcType); _resetProbeStatus(); } } From 096094f8e8d8e28cde696db9e5aaaecf7128ec1f Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 17:32:38 +0200 Subject: [PATCH 109/152] ditto --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index e8d81a0873..b1cf849563 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -935,9 +935,7 @@ bool clsLEAMDNSHost::clsService::setProtocol(const char* p_pcProtocol) { if ((bResult = (0 != (m_pcProtocol = new char[stLength + 1])))) { - strncpy(m_pcProtocol, p_pcProtocol, stLength); - m_pcProtocol[stLength] = 0; - + strcpy(m_pcProtocol, p_pcProtocol); _resetProbeStatus(); } } From ee087150d84b7d38ad70463efe9e8d7941440bb0 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 17:37:48 +0200 Subject: [PATCH 110/152] remove useless overloads --- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 12 ---- .../ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 61 ------------------- 2 files changed, 73 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 97de2ff2a3..b5cf75b86c 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -477,21 +477,9 @@ class clsLEAMDNSHost clsServiceTxt* _addServiceTxt(const char* p_pcKey, uint32_t p_u32Value, bool p_bTemp); - clsServiceTxt* _addServiceTxt(const char* p_pcKey, - uint16_t p_u16Value, - bool p_bTemp); - clsServiceTxt* _addServiceTxt(const char* p_pcKey, - uint8_t p_u8Value, - bool p_bTemp); clsServiceTxt* _addServiceTxt(const char* p_pcKey, int32_t p_i32Value, bool p_bTemp); - clsServiceTxt* _addServiceTxt(const char* p_pcKey, - int16_t p_i16Value, - bool p_bTemp); - clsServiceTxt* _addServiceTxt(const char* p_pcKey, - int8_t p_i8Value, - bool p_bTemp); public: bool setInstanceName(const char* p_pcInstanceName); diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index b1cf849563..f06882f21e 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -1252,36 +1252,6 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const return _addServiceTxt(p_pcKey, acValueBuffer, p_bTemp); } -/* - clsLEAMDNSHost::clsService::_addServiceTxt (uint16_t) - -*/ -clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, - uint16_t p_u16Value, - bool p_bTemp) -{ - char acValueBuffer[8]; // 16-bit max 5 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%hu", p_u16Value); - - return _addServiceTxt(p_pcKey, acValueBuffer, p_bTemp); -} - -/* - clsLEAMDNSHost::clsService::_addServiceTxt (uint8_t) - -*/ -clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, - uint8_t p_u8Value, - bool p_bTemp) -{ - char acValueBuffer[8]; // 8-bit max 3 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%hhu", p_u8Value); - - return _addServiceTxt(p_pcKey, acValueBuffer, p_bTemp); -} - /* clsLEAMDNSHost::clsService::_addServiceTxt (int32_t) @@ -1297,37 +1267,6 @@ clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const return _addServiceTxt(p_pcKey, acValueBuffer, p_bTemp); } -/* - clsLEAMDNSHost::clsService::_addServiceTxt (int16_t) - -*/ -clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, - int16_t p_i16Value, - bool p_bTemp) -{ - char acValueBuffer[8]; // 16-bit max 5 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%hi", p_i16Value); - - return _addServiceTxt(p_pcKey, acValueBuffer, p_bTemp); -} - -/* - clsLEAMDNSHost::clsService::_addServiceTxt (int8_t) - -*/ -clsLEAMDNSHost::clsServiceTxt* clsLEAMDNSHost::clsService::_addServiceTxt(const char* p_pcKey, - int8_t p_i8Value, - bool p_bTemp) -{ - char acValueBuffer[8]; // 8-bit max 3 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%hhi", p_i8Value); - - return _addServiceTxt(p_pcKey, acValueBuffer, p_bTemp); -} - - /** clsLEAMDNSHost::clsMsgHeader From c86b2d84046e342d79e6902d1e7d32bccd9baa76 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 17:41:12 +0200 Subject: [PATCH 111/152] fix strncpy -> strcpy --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index f06882f21e..b22d9fc5e7 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -1411,7 +1411,7 @@ bool clsLEAMDNSHost::clsRRDomain::addLabel(const char* p_pcLabel, m_acName[m_u16NameLength++] = '_'; --stLength; } - strncpy(&(m_acName[m_u16NameLength]), p_pcLabel, stLength); m_acName[m_u16NameLength + stLength] = 0; + strcpy(&(m_acName[m_u16NameLength]), p_pcLabel); m_u16NameLength += stLength; } bResult = clearNameCache(); From 5c3f74655a27040d0a7bfd0d053f713328a7f4a0 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 17:43:02 +0200 Subject: [PATCH 112/152] lenght typo --- libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp | 6 +++--- libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 2 +- libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp b/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp index f7fe8c9030..be5666df7d 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp @@ -411,11 +411,11 @@ int MDNSResponder::queryService(char *service, char *proto) // Only supports sending one PTR query // Send the Name field (eg. "_http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // lenght of "_" + service + _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_" + service _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_" + service - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // lenght of "_" + proto + _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_" + proto _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_" + proto - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // lenght of "local" + _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length of "local" _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index b22d9fc5e7..5b89c8f895 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -1438,7 +1438,7 @@ bool clsLEAMDNSHost::clsRRDomain::compare(const clsRRDomain& p_Other) const { if (*((unsigned char*)pT)) // Not 0 { - pT += (1 + * ((unsigned char*)pT)); // Shift by length byte and lenght + pT += (1 + * ((unsigned char*)pT)); // Shift by length byte and length pO += (1 + * ((unsigned char*)pO)); } else // Is 0 -> Successfully reached the end diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp index 18c4a95eb3..8f0d2f7cf2 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp @@ -788,7 +788,7 @@ bool MDNSResponder::stcMDNS_RRDomain::compare(const stcMDNS_RRDomain& p_Other) c { if (*((unsigned char*)pT)) // Not 0 { - pT += (1 + * ((unsigned char*)pT)); // Shift by length byte and lenght + pT += (1 + * ((unsigned char*)pT)); // Shift by length byte and length pO += (1 + * ((unsigned char*)pO)); } else // Is 0 -> Successfully reached the end From 2270b839eb8f116c4d94a36bf6c0490367748ae9 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 17:51:02 +0200 Subject: [PATCH 113/152] rework debug macros not nicely dealt by astyle --- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 07bad03583..dbc422f400 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -767,11 +767,10 @@ bool clsLEAMDNSHost::_readRRAnswer(clsLEAMDNSHost::clsRRAnswer*& p_rpRRAnswer) bResult = _readRRAnswerGeneric(*(clsRRAnswerGeneric*&)p_rpRRAnswer, u16RDLength); break; } - DEBUG_EX_INFO( - if ((bResult) && - (p_rpRRAnswer)) - { - DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer: "), _DH()); + + DEBUG_EX_INFO_IF((bResult) && (p_rpRRAnswer), + { + DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer: "), _DH()); _printRRDomain(p_rpRRAnswer->m_Header.m_Domain); DEBUG_OUTPUT.printf_P(PSTR(" Type:%s Class:0x%04X TTL:%u, RDLength:%u "), _RRType2Name(p_rpRRAnswer->m_Header.m_Attributes.m_u16Type), @@ -826,12 +825,12 @@ bool clsLEAMDNSHost::_readRRAnswer(clsLEAMDNSHost::clsRRAnswer*& p_rpRRAnswer) break; } DEBUG_OUTPUT.printf_P(PSTR("\n")); - } - else + }); // DEBUG_EX_INFO + + DEBUG_EX_INFO_IF(!((bResult) && (p_rpRRAnswer)), { DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer: FAILED to read specific answer of type 0x%04X!\n"), _DH(), p_rpRRAnswer->m_Header.m_Attributes.m_u16Type); - } - ); // DEBUG_EX_INFO + }); } DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer: FAILED!\n"), _DH());); return bResult; From 5c7808afecd34d5426ae35d1e31c2144515df95f Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 17:53:57 +0200 Subject: [PATCH 114/152] clarify comment --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index dbc422f400..6bbf16a4f8 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -1073,7 +1073,7 @@ bool clsLEAMDNSHost::_readRRDomain(clsLEAMDNSHost::clsRRDomain& p_rRRDomain) Reads a domain from the UDP input buffer. For every compression level, the functions calls itself recursively. To avoid endless recursion because of malformed MDNS records, - the maximum recursion depth is set by MDNS_DOMAIN_MAX_REDIRCTION. + the maximum recursion depth is set by clsConsts::u8DomainMaxRedirections. */ bool clsLEAMDNSHost::_readRRDomain_Loop(clsLEAMDNSHost::clsRRDomain& p_rRRDomain, From 37d0300c1e6926394071b6cdfe25b5a6ba03a960 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 17:58:21 +0200 Subject: [PATCH 115/152] align comment --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 6bbf16a4f8..5bc115ec53 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -1503,7 +1503,7 @@ bool clsLEAMDNSHost::_udpDump(unsigned p_uOffset, MDNSResponder::_readMDNSMsgHeader Read a MDNS header from the UDP input buffer. - | 8 | 8 | 8 | 8 | + | 8 | 8 | 8 | 8 | 00| Identifier | Flags & Codes | 01| Question count | Answer count | 02| NS answer count | Ad answer count | From 05b1581761af33963944c738a1b349f6a5eb5304 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 17:59:52 +0200 Subject: [PATCH 116/152] typo: form -> from --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 5bc115ec53..7d81762fcb 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -1508,7 +1508,7 @@ bool clsLEAMDNSHost::_udpDump(unsigned p_uOffset, 01| Question count | Answer count | 02| NS answer count | Ad answer count | - All 16-bit and 32-bit elements need to be translated form network coding to host coding (done in _udpRead16 and _udpRead32) + All 16-bit and 32-bit elements need to be translated from network coding to host coding (done in _udpRead16 and _udpRead32) In addition, bitfield memory order is undefined in C standard (GCC doesn't order them in the coded direction...), so they need some mapping here @@ -1591,7 +1591,7 @@ bool clsLEAMDNSHost::_write32(uint32_t p_u32Value, Write MDNS header to the UDP output buffer. - All 16-bit and 32-bit elements need to be translated form host coding to network coding (done in _udpAppend16 and _udpAppend32) + All 16-bit and 32-bit elements need to be translated from host coding to network coding (done in _udpAppend16 and _udpAppend32) In addition, bitfield memory order is undefined in C standard (GCC doesn't order them in the coded direction...), so they need some mapping here From 3431a01ab302e42d925adf25ca88d980b25617d7 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 18:02:18 +0200 Subject: [PATCH 117/152] typo: supportet -> supported --- libraries/ESP8266mDNS/src/ESP8266mDNS.h | 2 +- libraries/ESP8266mDNS/src/LEAmDNS.h | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index 922a3c5f3f..fd09760410 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -10,7 +10,7 @@ - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented - Probing host and service domains for uniqueness in the local network - - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak) + - Tiebreaking while probing is supported in a very minimalistic way (the 'higher' IP address wins the tiebreak) - Announcing available services after successful probing - Using fixed service TXT items or - Using dynamic service TXT items for presented services (via callback) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS.h b/libraries/ESP8266mDNS/src/LEAmDNS.h index e223002abb..6037f0d13f 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS.h @@ -14,7 +14,7 @@ - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented - Probing host and service domains for uniqueness in the local network - - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak) + - Tiebreaking while probing is supported in a very minimalistic way (the 'higher' IP address wins the tiebreak) - Announcing available services after successful probing - Using fixed service TXT items or - Using dynamic service TXT items for presented services (via callback) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index b5cf75b86c..5f1473ffe9 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -10,7 +10,7 @@ - Announcing a DNS-SD service to interested observers, eg. a http server by announcing a esp8266._http._tcp.local. service - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented - Probing host and service domains for uniqueness in the local network - - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak) + - Tiebreaking while probing is supported in a very minimalistic way (the 'higher' IP address wins the tiebreak) - Announcing available services after successful probing - Using fixed service TXT items or - Using dynamic service TXT items for presented services (via callback) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h index b0ace4d371..2967c8a0c8 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h @@ -14,7 +14,7 @@ - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented - Probing host and service domains for uniqueness in the local network - - Tiebreaking while probing is supportet in a very minimalistic way (the 'higher' IP address wins the tiebreak) + - Tiebreaking while probing is supported in a very minimalistic way (the 'higher' IP address wins the tiebreak) - Announcing available services after successful probing - Using fixed service TXT items or - Using dynamic service TXT items for presented services (via callback) From 04a01f0a2079e976518f083b8f67041102702a70 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 18:16:08 +0200 Subject: [PATCH 118/152] style --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index 5b89c8f895..913665deae 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -660,7 +660,7 @@ bool clsLEAMDNSHost::clsServiceTxts::compare(const clsLEAMDNSHost::clsServiceTxt (pOtherTxt->m_pcValue) && (pTxt->m_pcValue) && (strlen(pOtherTxt->m_pcValue) == strlen(pTxt->m_pcValue)) /* && - redundant: (0 == strcmp(pOtherTxt->m_pcValue, pTxt->m_pcValue)) */ )))) + redundant: (0 == strcmp(pOtherTxt->m_pcValue, pTxt->m_pcValue)) */)))) { break; } From 16504b2c339abf4c18babeabc6a96dd3cdd9e2a0 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Sun, 23 Aug 2020 18:31:47 +0200 Subject: [PATCH 119/152] fix typo in debug mode --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp index b94fb1f80b..186d913a38 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp @@ -181,7 +181,7 @@ const char* clsLEAMDNSHost::_RRType2Name(uint16_t p_u16RRType) const case DNS_RRTYPE_SRV: strcpy_P(acRRName, PSTR("SRV")); break; case clsConsts::u8DNS_RRTYPE_NSEC: strcpy_P(acRRName, PSTR("NSEC")); break; case DNS_RRTYPE_ANY: strcpy_P(acRRName, PSTR("ANY")); break; - default: sprintf_P(acRRName, PSTR("Unknown(0x%04X)", p_u16RRType); // MAX 15! + default: sprintf_P(acRRName, PSTR("Unknown(0x%04X"), p_u16RRType); // MAX 15! } return acRRName; } From 21a9096f8f006e5897752e5e2d46da782a2cb0f3 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Wed, 26 Aug 2020 16:41:52 +0200 Subject: [PATCH 120/152] simplification --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp index 88356f40e1..c3b79c02b2 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp @@ -1451,7 +1451,7 @@ bool clsLEAMDNSHost::_resetProbeStatus(bool p_bRestart /*= true*/) for (clsService* pService : m_Services) { pService->m_ProbeInformation.clear(false); - pService->m_ProbeInformation.m_ProbingStatus = (p_bRestart ? clsProbeInformation_Base::enuProbingStatus::ReadyToStart : clsProbeInformation_Base::enuProbingStatus::DoneFinally); + pService->m_ProbeInformation.m_ProbingStatus = m_ProbeInformation.m_ProbingStatus; } return true; } From bae56127f250ea29225479a6045bfa416f867bb7 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Wed, 26 Aug 2020 16:44:48 +0200 Subject: [PATCH 121/152] add missing MIT licenses --- libraries/ESP8266mDNS/src/ESP8266mDNS.cpp | 22 +++++++++++++++++++ libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 18 +++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.cpp b/libraries/ESP8266mDNS/src/ESP8266mDNS.cpp index c784a0d790..b5d7aac277 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.cpp +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.cpp @@ -1,3 +1,25 @@ +/* + + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ #include <ESP8266mDNS.h> /* diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index af9b48c353..1aa900dda3 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -1,6 +1,24 @@ /* LEAmDNS2_Legacy.cpp + License (MIT license): + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. */ From dd4c44f70a6226a84e4f66cd322833f3b60f8978 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Wed, 26 Aug 2020 16:49:30 +0200 Subject: [PATCH 122/152] fix previous fix from review: comparing with strlen is superfluous when strings are strcmp anyway --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index 913665deae..7533b07ec8 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -646,7 +646,6 @@ bool clsLEAMDNSHost::clsServiceTxts::compare(const clsLEAMDNSHost::clsServiceTxt if (!((bResult = ((pOtherTxt) && (pTxt->m_pcValue) && (pOtherTxt->m_pcValue) && - (strlen(pTxt->m_pcValue) == strlen(pOtherTxt->m_pcValue)) && (0 == strcmp(pTxt->m_pcValue, pOtherTxt->m_pcValue)))))) { break; @@ -659,8 +658,7 @@ bool clsLEAMDNSHost::clsServiceTxts::compare(const clsLEAMDNSHost::clsServiceTxt if (!((bResult = ((pTxt) && (pOtherTxt->m_pcValue) && (pTxt->m_pcValue) && - (strlen(pOtherTxt->m_pcValue) == strlen(pTxt->m_pcValue)) /* && - redundant: (0 == strcmp(pOtherTxt->m_pcValue, pTxt->m_pcValue)) */)))) + (0 == strcmp(pOtherTxt->m_pcValue, pTxt->m_pcValue)))))) { break; } From 2741d41f57a12a8126fcf24311f52c30d7e9f867 Mon Sep 17 00:00:00 2001 From: "TAURI20\\Herman" <hreintke@tauri.nl> Date: Sun, 13 Sep 2020 12:33:39 +0200 Subject: [PATCH 123/152] Revert "strncpy: fix max len" This reverts commit 3b1447c608556bd1f2d8b9f2d209e952ac79fe35. --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 46950cc0ea..3906dce484 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -1030,7 +1030,7 @@ bool clsLEAMDNSHost::_allocDomainName(const char* p_pcNewDomainName, } p_rpcDomainName[i] = 0; #else - strncpy(p_rpcDomainName, p_pcNewDomainName, stLength); + strncpy(p_rpcDomainName, p_pcNewDomainName, (stLength + 1)); #endif } } From 79931081b4d4a2ce0c59fe6d9de6f11ba0f6ad4c Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 09:43:25 +0200 Subject: [PATCH 124/152] fix more strncpy --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 4 ++-- libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 6 ++++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 3906dce484..d3bb7a7544 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -162,7 +162,7 @@ const char* clsLEAMDNSHost::indexDomainName(const char* p_pcDomainName, { // No given domain, use base or default const char* cpcDefaultName = (p_pcDefaultDomainName ? : "esp8266"); - strncpy(acResultDomainName, cpcDefaultName, sizeof(acResultDomainName) - 1); + strncpy(acResultDomainName, cpcDefaultName, sizeof(acResultDomainName)); } DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[mDNS] indexDomainName: From '%s' to '%s'\n"), (p_pcDomainName ? : ""), acResultDomainName);); return acResultDomainName; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp index 7533b07ec8..dcf3c4b76e 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp @@ -139,7 +139,7 @@ bool clsLEAMDNSHost::clsServiceTxt::setKey(const char* p_pcKey, { if (allocKey(p_stLength)) { - strncpy(m_pcKey, p_pcKey, p_stLength); + strncpy(m_pcKey, p_pcKey, p_stLength + 1); m_pcKey[p_stLength] = 0; bResult = true; } @@ -198,7 +198,7 @@ bool clsLEAMDNSHost::clsServiceTxt::setValue(const char* p_pcValue, { if (allocValue(p_stLength)) { - strncpy(m_pcValue, p_pcValue, p_stLength); + strncpy(m_pcValue, p_pcValue, p_stLength + 1); m_pcValue[p_stLength] = 0; bResult = true; } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 7d81762fcb..38f10b1db1 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -898,9 +898,11 @@ bool clsLEAMDNSHost::_readRRAnswerTXT(clsLEAMDNSHost::clsRRAnswerTXT& p_rRRAnswe if (ucLength) { DEBUG_EX_INFO( - static char sacBuffer[64]; *sacBuffer = 0; + char sacBuffer[64]; + *sacBuffer = 0; uint8_t u8MaxLength = ((ucLength > (sizeof(sacBuffer) - 1)) ? (sizeof(sacBuffer) - 1) : ucLength); - os_strncpy(sacBuffer, (const char*)pucCursor, u8MaxLength); sacBuffer[u8MaxLength] = 0; + os_strncpy(sacBuffer, (const char*)pucCursor, u8MaxLength + 1); + sacBuffer[u8MaxLength] = 0; DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerTXT: Item(%u): %s\n"), _DH(), ucLength, sacBuffer); ); From 60f74561a475e10f2a3cb0340b84bf77d4f6c944 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 09:53:36 +0200 Subject: [PATCH 125/152] comments for lwIPIntf-callback --- cores/esp8266/LwipIntf.h | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cores/esp8266/LwipIntf.h b/cores/esp8266/LwipIntf.h index cbf2927315..ba31e912e6 100644 --- a/cores/esp8266/LwipIntf.h +++ b/cores/esp8266/LwipIntf.h @@ -10,7 +10,7 @@ class LwipIntf { private: - LwipIntf () { } + LwipIntf () { } // private, cannot be directly allocated protected: diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index d3bb7a7544..971b764643 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -275,7 +275,7 @@ bool clsLEAMDNSHost::begin(const char* p_pcHostName, bResult = LwipIntf::stateUpCB([this](netif * nif) { (void)nif; - // This called after a new interface appears: + // This is called when a new interface appears: // resend announces on all available interfaces. DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s a new interface %c%c/%d is up, restarting mDNS\n"), _DH(), nif->name[0], nif->name[1], netif_get_index(nif));); From 99de12ab3071970fba01ac91bb25c09b6caba60a Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 10:01:01 +0200 Subject: [PATCH 126/152] using type alias LwipIntf::CBType --- cores/esp8266/LwipIntf.h | 13 +++++++------ cores/esp8266/LwipIntfCB.cpp | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/cores/esp8266/LwipIntf.h b/cores/esp8266/LwipIntf.h index ba31e912e6..cb8bb92dcc 100644 --- a/cores/esp8266/LwipIntf.h +++ b/cores/esp8266/LwipIntf.h @@ -8,18 +8,19 @@ class LwipIntf { -private: +public: - LwipIntf () { } // private, cannot be directly allocated + using CBType = std::function <void(netif*)>; -protected: + static bool stateUpCB (LwipIntf::CBType&& cb); - static bool stateChangeSysCB (std::function<void(netif*)>&& cb); +private: -public: + LwipIntf () { } // private, cannot be directly allocated - static bool stateUpCB (std::function<void(netif*)>&& cb); +protected: + static bool stateChangeSysCB (LwipIntf::CBType&& cb); }; #endif // _LWIPINTF_H diff --git a/cores/esp8266/LwipIntfCB.cpp b/cores/esp8266/LwipIntfCB.cpp index c0de24a233..b978918a72 100644 --- a/cores/esp8266/LwipIntfCB.cpp +++ b/cores/esp8266/LwipIntfCB.cpp @@ -6,7 +6,7 @@ #define NETIF_STATUS_CB_SIZE 3 static int netifStatusChangeListLength = 0; -std::function<void(netif*)> netifStatusChangeList [NETIF_STATUS_CB_SIZE]; +LwipIntf::CBType netifStatusChangeList [NETIF_STATUS_CB_SIZE]; extern "C" void netif_status_changed (struct netif* netif) { @@ -15,7 +15,7 @@ extern "C" void netif_status_changed (struct netif* netif) netifStatusChangeList[i](netif); } -bool LwipIntf::stateChangeSysCB (std::function<void(netif*)>&& cb) +bool LwipIntf::stateChangeSysCB (LwipIntf::CBType&& cb) { if (netifStatusChangeListLength >= NETIF_STATUS_CB_SIZE) { @@ -29,7 +29,7 @@ bool LwipIntf::stateChangeSysCB (std::function<void(netif*)>&& cb) return true; } -bool LwipIntf::stateUpCB (std::function<void(netif*)>&& cb) +bool LwipIntf::stateUpCB (LwipIntf::CBType&& cb) { return stateChangeSysCB([cb](netif* nif) { From 3a22818cad69429e4f809c45624f1c936ad7761d Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 10:36:50 +0200 Subject: [PATCH 127/152] udpContext: move trySend to private section --- .../ESP8266WiFi/src/include/UdpContext.h | 67 +++++++++---------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/libraries/ESP8266WiFi/src/include/UdpContext.h b/libraries/ESP8266WiFi/src/include/UdpContext.h index 11d9ae82bb..0c43cd2adb 100644 --- a/libraries/ESP8266WiFi/src/include/UdpContext.h +++ b/libraries/ESP8266WiFi/src/include/UdpContext.h @@ -400,14 +400,30 @@ class UdpContext _tx_buf_offset = 0; } - err_t trySend(const ip_addr_t* addr = 0, uint16_t port = 0, bool keepBuffer = true) + bool send(const ip_addr_t* addr = 0, uint16_t port = 0) + { + return trySend(addr, port, /* don't keep buffer */false) == ERR_OK; + } + + bool sendTimeout(const ip_addr_t* addr, uint16_t port, + esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs) + { + err_t err; + esp8266::polledTimeout::oneShotFastMs timeout(timeoutMs); + while (((err = trySend(addr, port, /* keep buffer on error */true)) != ERR_OK) && !timeout) + delay(0); + if (err != ERR_OK) + cancelBuffer(); // get rid of buffer kept on error after timeout + return err == ERR_OK; + } + +private: + + err_t trySend(const ip_addr_t* addr, uint16_t port, bool keepBufferOnError) { size_t data_size = _tx_buf_offset; pbuf* tx_copy = pbuf_alloc(PBUF_TRANSPORT, data_size, PBUF_RAM); - if(!tx_copy){ - DEBUGV("failed pbuf_alloc"); - } - else{ + if (tx_copy) { uint8_t* dst = reinterpret_cast<uint8_t*>(tx_copy->payload); for (pbuf* p = _tx_buf_head; p; p = p->next) { size_t will_copy = (data_size < p->len) ? data_size : p->len; @@ -416,9 +432,12 @@ class UdpContext data_size -= will_copy; } } - if (!keepBuffer) + + if (!keepBufferOnError) cancelBuffer(); - if(!tx_copy){ + + if (!tx_copy){ + DEBUGV("failed pbuf_alloc"); return ERR_MEM; } @@ -426,44 +445,20 @@ class UdpContext addr = &_pcb->remote_ip; port = _pcb->remote_port; } -#ifdef LWIP_MAYBE_XCC - uint16_t old_ttl = _pcb->ttl; - if (ip_addr_ismulticast(addr)) { - _pcb->ttl = _mcast_ttl; - } -#endif + err_t err = udp_sendto(_pcb, tx_copy, addr, port); if (err != ERR_OK) { DEBUGV(":ust rc=%d\r\n", (int) err); } -#ifdef LWIP_MAYBE_XCC - _pcb->ttl = old_ttl; -#endif + pbuf_free(tx_copy); - if (err == ERR_OK) - cancelBuffer(); - return err; - } - bool send(const ip_addr_t* addr = 0, uint16_t port = 0) - { - return trySend(addr, port, /* don't keep buffer */false) == ERR_OK; - } + if (err == ERR_OK) + cancelBuffer(); // no error: get rid of buffer - bool sendTimeout(const ip_addr_t* addr, uint16_t port, - esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs) - { - err_t err; - esp8266::polledTimeout::oneShotFastMs timeout(timeoutMs); - while (((err = trySend(addr, port)) != ERR_OK) && !timeout) - delay(0); - if (err != ERR_OK) - cancelBuffer(); - return err == ERR_OK; + return err; } -private: - size_t _processSize (const pbuf* pb) { size_t ret = 0; From 9047d2d073685354fa9311bda9b11da563c27581 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 10:53:31 +0200 Subject: [PATCH 128/152] typos in comments --- .../examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index 58b111c4b1..d70e2b2235 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -3,7 +3,7 @@ This example demonstrates two features of the LEA clsLEAMDNSHost: 1. The host and service domain negotiation process that ensures - the uniqueness of the finally choosen host and service domain name. + the uniqueness of the finally chosen host and service domain name. 2. The dynamic MDNS service TXT feature A 'clock' service in announced via the MDNS responder and the current @@ -11,10 +11,10 @@ The time value is updated every second! The ESP is initially announced to clients as 'esp8266.local', if this host domain - is already used in the local network, another host domain is negociated. Keep an - eye to the serial output to learn the final host domain for the clock service. + is already used in the local network, another host domain is negotiated. Keep an + eye on the serial output to learn the final host domain for the clock service. The service itself is is announced as 'host domain'._espclk._tcp.local. - As the service uses port 80, a very simple HTTP server is installed also to deliver + As the service uses port 80, a very simple HTTP server is also installed to deliver a small web page containing a greeting and the current time (not updated). The web server code is taken nearly 1:1 from the 'mDNS_Web_Server.ino' example. Point your browser to 'host domain'.local to see this web page. From cdd0a64b5b427112bcc04eab4fbca4134cd0a377 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 10:53:56 +0200 Subject: [PATCH 129/152] rename local mDNS instance in example --- .../examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index d70e2b2235..5faaae8ff8 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -81,7 +81,7 @@ const char* ssid = STASSID; const char* password = STAPSK; -clsLEAMDNSHost MDNS; // MDNS responder +clsLEAMDNSHost MDNSRESP; // MDNS responder bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain clsLEAMDNSHost::clsService* hMDNSService = 0; // The handle of the clock service in the MDNS responder @@ -144,7 +144,7 @@ bool setStationHostname(const char* p_pcHostname) { Add a dynamic MDNS TXT item 'ct' to the clock service. The callback function is called every time, the TXT items for the clock service are needed. - This can be triggered by calling MDNS.announce(). + This can be triggered by calling MDNSRESP.announce(). */ void MDNSDynamicServiceTxtCallback(const clsLEAMDNSHost::hMDNSService& p_hService) { @@ -223,7 +223,7 @@ void setup(void) { // Setup MDNS responder // Init the (currently empty) host domain string with 'leamdnsv2' - if (MDNS.begin("leamdnsv2", + if (MDNSRESP.begin("leamdnsv2", [](clsLEAMDNSHost & p_rMDNSHost, const char* p_pcDomainName, bool p_bProbeResult)->void { if (p_bProbeResult) { Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!")); @@ -233,7 +233,7 @@ void setup(void) { hMDNSService->setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallback); } else { // Change hostname, use '-' as divider between base name and index - MDNS.setHostName(clsLEAMDNSHost::indexDomainName(p_pcDomainName, "-", 0)); + MDNSRESP.setHostName(clsLEAMDNSHost::indexDomainName(p_pcDomainName, "-", 0)); } })) { Serial.println("mDNS-AP started"); @@ -255,7 +255,7 @@ void loop(void) { // Check if a request has come in server.handleClient(); // Allow MDNS processing - MDNS.update(); + MDNSRESP.update(); static esp8266::polledTimeout::periodicMs timeout(UPDATE_CYCLE); if (timeout.expired()) { @@ -264,7 +264,7 @@ void loop(void) { // Just trigger a new MDNS announcement, this will lead to a call to // 'MDNSDynamicServiceTxtCallback', which will update the time TXT item Serial.printf("Announce trigger from user\n"); - MDNS.announce(); + MDNSRESP.announce(); } } From a71e1c90b29f622c683bb4ba0747dbe9ffc877e1 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 10:55:39 +0200 Subject: [PATCH 130/152] memory reservation for string in example --- .../ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index 5faaae8ff8..6e9e61e467 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -171,6 +171,7 @@ void handleHTTPRequest() { gmtime_r(&now, &timeinfo); String s; + s.reserve(300); s = "<!DOCTYPE HTML>\r\n<html>Hello from "; s += WiFi.hostname() + " at " + WiFi.localIP().toString(); From fcd214bbe3e6984d785129f3350c76335706363c Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 11:04:52 +0200 Subject: [PATCH 131/152] string reservation --- .../LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino index b14df03ba2..59f213fd83 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino @@ -204,7 +204,9 @@ void handleHTTPRequest() { IPAddress ip = server.client().localIP(); String ipStr = ip.toString(); - String s = "<!DOCTYPE HTML>\r\n<html><h3><head>Hello from "; + String s; + s.reserve(200 /* + service listed */); + s = "<!DOCTYPE HTML>\r\n<html><h3><head>Hello from "; s += WiFi.hostname() + ".local at " + server.client().localIP().toString() + "</h3></head>"; s += "<br/><h4>Local HTTP services are :</h4>"; s += "<ol>"; From 6f92ac5ab450e735792a8913de9e5a4bdd7bab0c Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 11:11:25 +0200 Subject: [PATCH 132/152] move strrstr() to stdlib_noniso.h --- cores/esp8266/core_esp8266_noniso.cpp | 32 +++++++++++++ cores/esp8266/stdlib_noniso.h | 3 ++ libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 40 +---------------- libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp | 45 +------------------ 4 files changed, 37 insertions(+), 83 deletions(-) diff --git a/cores/esp8266/core_esp8266_noniso.cpp b/cores/esp8266/core_esp8266_noniso.cpp index c742904d21..b341599b0f 100644 --- a/cores/esp8266/core_esp8266_noniso.cpp +++ b/cores/esp8266/core_esp8266_noniso.cpp @@ -117,4 +117,36 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { return s; } +/* + strrstr (static) + + Backwards search for p_pcPattern in p_pcString + Based on: https://stackoverflow.com/a/1634398/2778898 + +*/ +const char* strrstr(const char*__restrict p_pcString, + const char*__restrict p_pcPattern) +{ + const char* pcResult = 0; + + size_t stStringLength = (p_pcString ? strlen(p_pcString) : 0); + size_t stPatternLength = (p_pcPattern ? strlen(p_pcPattern) : 0); + + if ((stStringLength) && + (stPatternLength) && + (stPatternLength <= stStringLength)) + { + // Pattern is shorter or has the same length than the string + for (const char* s = (p_pcString + stStringLength - stPatternLength); s >= p_pcString; --s) + { + if (0 == strncmp(s, p_pcPattern, stPatternLength)) + { + pcResult = s; + break; + } + } + } + return pcResult; +} + }; diff --git a/cores/esp8266/stdlib_noniso.h b/cores/esp8266/stdlib_noniso.h index 636cbf437d..053ea47948 100644 --- a/cores/esp8266/stdlib_noniso.h +++ b/cores/esp8266/stdlib_noniso.h @@ -44,6 +44,9 @@ char* dtostrf (double val, signed char width, unsigned char prec, char *s); void reverse(char* begin, char* end); +const char* strrstr(const char*__restrict p_pcString, + const char*__restrict p_pcPattern); + #ifdef __cplusplus } // extern "C" #endif diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 971b764643..353cb820a9 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -24,6 +24,7 @@ #include <algorithm> #include <LwipIntf.h> // LwipIntf::stateUpCB() +#include <stdlib_noniso.h> // strrstr() #include "ESP8266mDNS.h" #include "LEAmDNS2Host.h" @@ -46,45 +47,6 @@ #define STRINGIZE_VALUE_OF(x) STRINGIZE(x) #endif -namespace // anonymous -{ - -/* - strrstr (static) - - Backwards search for p_pcPattern in p_pcString - Based on: https://stackoverflow.com/a/1634398/2778898 - -*/ -const char* strrstr(const char*__restrict p_pcString, - const char*__restrict p_pcPattern) -{ - const char* pcResult = 0; - - size_t stStringLength = (p_pcString ? strlen(p_pcString) : 0); - size_t stPatternLength = (p_pcPattern ? strlen(p_pcPattern) : 0); - - if ((stStringLength) && - (stPatternLength) && - (stPatternLength <= stStringLength)) - { - // Pattern is shorter or has the same length than the string - for (const char* s = (p_pcString + stStringLength - stPatternLength); s >= p_pcString; --s) - { - if (0 == strncmp(s, p_pcPattern, stPatternLength)) - { - pcResult = s; - break; - } - } - } - return pcResult; -} - - -} // anonymous - - namespace esp8266 { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp index d5a0ccd762..7dc3773de5 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp @@ -23,55 +23,12 @@ */ #include <lwip/igmp.h> +#include <stdlib_noniso.h> // strrstr() #include "ESP8266mDNS.h" #include "LEAmDNS_lwIPdefs.h" #include "LEAmDNS_Priv.h" - -namespace -{ - -/* - strrstr (static) - - Backwards search for p_pcPattern in p_pcString - Based on: https://stackoverflow.com/a/1634398/2778898 - -*/ -const char* strrstr(const char*__restrict p_pcString, const char*__restrict p_pcPattern) -{ - - const char* pcResult = 0; - - size_t stStringLength = (p_pcString ? strlen(p_pcString) : 0); - size_t stPatternLength = (p_pcPattern ? strlen(p_pcPattern) : 0); - - if ((stStringLength) && - (stPatternLength) && - (stPatternLength <= stStringLength)) - { - // Pattern is shorter or has the same length tham the string - - for (const char* s = (p_pcString + stStringLength - stPatternLength); s >= p_pcString; --s) - { - if (0 == strncmp(s, p_pcPattern, stPatternLength)) - { - pcResult = s; - break; - } - } - } - return pcResult; -} - - -} // anonymous - - - - - namespace esp8266 { From 53d54778bf65d85a705110313ad3d3fd95043240 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 11:25:19 +0200 Subject: [PATCH 133/152] "good practices" --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 353cb820a9..d63086c884 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -920,6 +920,7 @@ bool clsLEAMDNSHost::_leaveMulticastGroups() bool bResult = false; for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + { if (netif_is_up(pNetIf)) { bResult = true; @@ -940,6 +941,7 @@ bool clsLEAMDNSHost::_leaveMulticastGroups() } #endif } + } return bResult; } From 281f67e31c0ac4a8f89778b117138a523845e640 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 11:27:01 +0200 Subject: [PATCH 134/152] "good practices" --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index d63086c884..a4b7fb2371 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -142,11 +142,13 @@ bool clsLEAMDNSHost::setNetIfHostName(const char* p_pcHostName) { if (p_pcHostName) for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + { if (netif_is_up(pNetIf)) { netif_set_hostname(pNetIf, p_pcHostName); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[mDNS] setNetIfHostName host name: %s on " NETIFID_STR "!\n"), p_pcHostName, NETIFID_VAL(pNetIf));); } + } return true; } @@ -875,6 +877,7 @@ bool clsLEAMDNSHost::_joinMulticastGroups(void) // Join multicast group(s) for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) + { if (netif_is_up(pNetIf)) { #ifdef MDNS_IPV4_SUPPORT @@ -909,6 +912,7 @@ bool clsLEAMDNSHost::_joinMulticastGroups(void) _DH(), NETIFID_VAL(pNetIf))); #endif } + } return bResult; } From 9a1ad4beea643d45709adff9815a6ea11e2cab4f Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 11:38:09 +0200 Subject: [PATCH 135/152] _instanceName() return 0 when 0 has to be returned --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 9 ++++----- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 3 +-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index a4b7fb2371..3c25af2f6a 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -419,8 +419,8 @@ clsLEAMDNSHost::clsService* clsLEAMDNSHost::addService(const char* p_pcInstanceN } } } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s addService: %s to add service '%s.%s.%s.local'!\n"), _DH(pService), (pService ? "Succeeded" : "FAILED"), _instanceName(p_pcInstanceName, false), (p_pcType ? : ""), (p_pcProtocol ? : ""));); - DEBUG_EX_ERR(if (!pService) DEBUG_OUTPUT.printf_P(PSTR("%s addService: FAILED to add service '%s.%s.%s.local'!\n"), _DH(pService), _instanceName(p_pcInstanceName, false), (p_pcType ? : ""), (p_pcProtocol ? : ""));); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s addService: %s to add service '%s.%s.%s.local'!\n"), _DH(pService), (pService ? "Succeeded" : "FAILED"), _instanceName(p_pcInstanceName)? : "-", (p_pcType ? : ""), (p_pcProtocol ? : ""));); + DEBUG_EX_ERR(if (!pService) DEBUG_OUTPUT.printf_P(PSTR("%s addService: FAILED to add service '%s.%s.%s.local'!\n"), _DH(pService), _instanceName(p_pcInstanceName)? : "-", (p_pcType ? : ""), (p_pcProtocol ? : ""));); return pService; } @@ -1056,10 +1056,9 @@ bool clsLEAMDNSHost::_releaseDefaultInstanceName(void) /* clsLEAmDNS2_Host::_instanceName */ -const char* clsLEAMDNSHost::_instanceName(const char* p_pcInstanceName, - bool p_bReturnZero /*= true*/) const +const char* clsLEAMDNSHost::_instanceName(const char* p_pcInstanceName) const { - return (p_pcInstanceName ? : (m_pcDefaultInstanceName ? : (m_pcHostName ? : (p_bReturnZero ? 0 : "-")))); + return (p_pcInstanceName ? : (m_pcDefaultInstanceName ? : (m_pcHostName ? : nullptr))); } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 5f1473ffe9..d6516be74f 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -1296,8 +1296,7 @@ class clsLEAMDNSHost bool _allocDefaultInstanceName(const char* p_pcInstanceName); bool _releaseDefaultInstanceName(void); - const char* _instanceName(const char* p_pcInstanceName, - bool p_bReturnZero = true) const; + const char* _instanceName(const char* p_pcInstanceName) const; // SERVICE clsService* _allocService(const char* p_pcName, From 844abbaa9d34db55db6c33ae72a025eb5f708a0e Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 11:45:09 +0200 Subject: [PATCH 136/152] made some 0 into nullptr --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 50 +++++++++++----------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 3c25af2f6a..386a2c3709 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -92,7 +92,7 @@ const char* clsLEAMDNSHost::indexDomainName(const char* p_pcDomainName, const char* pFoundDivider = strrstr(p_pcDomainName, pcDivider); if (pFoundDivider) // maybe already extended { - char* pEnd = 0; + char* pEnd = nullptr; unsigned long ulIndex = strtoul((pFoundDivider + strlen(pcDivider)), &pEnd, 10); if ((ulIndex) && ((pEnd - p_pcDomainName) == (ptrdiff_t)strlen(p_pcDomainName)) && @@ -109,7 +109,7 @@ const char* clsLEAMDNSHost::indexDomainName(const char* p_pcDomainName, } else { - pFoundDivider = 0; // Flag the need to (base) extend the hostname + pFoundDivider = nullptr; // Flag the need to (base) extend the hostname } } @@ -270,7 +270,7 @@ bool clsLEAMDNSHost::close(void) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s close\n"), _DH());); - m_pUDPContext = 0; + m_pUDPContext = nullptr; return ((_leaveMulticastGroups()) && (_releaseBackbone())); } @@ -397,7 +397,7 @@ clsLEAMDNSHost::clsService* clsLEAMDNSHost::addService(const char* p_pcInstanceN uint16_t p_u16Port, clsLEAMDNSHost::clsService::fnProbeResultCallback p_fnCallback /*= 0*/) { - clsService* pService = 0; + clsService* pService = nullptr; if (!((pService = findService(_instanceName(p_pcInstanceName), p_pcType, p_pcProtocol, p_u16Port)))) { @@ -415,7 +415,7 @@ clsLEAMDNSHost::clsService* clsLEAMDNSHost::addService(const char* p_pcInstanceN else { delete pService; - pService = 0; + pService = nullptr; } } } @@ -454,7 +454,7 @@ const clsLEAMDNSHost::clsService* clsLEAMDNSHost::findService(const char* p_pcIn const char* p_pcProtocol, uint16_t p_u16Port/*= (uint16_t)(-1)*/) const { - clsService* pFoundService = 0; + clsService* pFoundService = nullptr; for (clsService* pService : m_Services) { @@ -518,7 +518,7 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryService { std::list<clsQuery*> queries; - clsQuery* pQuery = 0; + clsQuery* pQuery = nullptr; if (((pQuery = _allocQuery(clsQuery::enuQueryType::Service))) && (_buildDomainForService(p_pcService, p_pcProtocol, pQuery->m_Domain))) { @@ -573,7 +573,7 @@ clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector clsLEAMDNSHost::queryHost(co { std::list<clsQuery*> queries; - clsQuery* pQuery = 0; + clsQuery* pQuery = nullptr; if (((pQuery = _allocQuery(clsQuery::enuQueryType::Host))) && (_buildDomainForHost(p_pcHostName, pQuery->m_Domain))) { @@ -647,7 +647,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcSe const char* p_pcProtocol, clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) { - clsQuery* pQuery = 0; + clsQuery* pQuery = nullptr; if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) { pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; @@ -663,7 +663,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcSe const char* p_pcProtocol, clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) { - clsQuery* pQuery = 0; + clsQuery* pQuery = nullptr; if ((pQuery = _installServiceQuery(p_pcService, p_pcProtocol))) { pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; @@ -677,13 +677,13 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installServiceQuery(const char* p_pcSe clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, clsLEAMDNSHost::clsQuery::QueryCallbackAnswerFn p_fnCallbackAnswer) { - clsQuery* pQuery = 0; + clsQuery* pQuery = nullptr; if ((p_pcHostName) && (*p_pcHostName)) { clsRRDomain domain; if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) - : 0))) + : nullptr))) { pQuery->m_fnCallbackAnswer = p_fnCallbackAnswer; } @@ -697,13 +697,13 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostN clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::installHostQuery(const char* p_pcHostName, clsLEAMDNSHost::clsQuery::QueryCallbackAccessorFn p_fnCallbackAccessor) { - clsQuery* pQuery = 0; + clsQuery* pQuery = nullptr; if ((p_pcHostName) && (*p_pcHostName)) { clsRRDomain domain; if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) - : 0))) + : nullptr))) { pQuery->m_fnCallbackAccessor = p_fnCallbackAccessor; } @@ -793,7 +793,7 @@ clsLEAMDNSHost::clsService* clsLEAMDNSHost::enableArduino(uint16_t p_u16Port, || (!svc->addServiceTxt("auth_upload", (p_bAuthUpload) ? "yes" : "no"))) { removeService(svc); - svc = 0; + svc = nullptr; } } return svc; @@ -816,7 +816,7 @@ clsLEAMDNSHost::clsService* clsLEAMDNSHost::enableArduino(uint16_t p_u16Port, */ UdpContext* clsLEAMDNSHost::_allocBackbone(void) { - UdpContext* pUDPContext = 0; + UdpContext* pUDPContext = nullptr; if (!clsBackbone::sm_pBackbone) { @@ -830,7 +830,7 @@ UdpContext* clsLEAMDNSHost::_allocBackbone(void) DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _allocBackbone: FAILED to init backbone!\n"), _DH());); delete clsBackbone::sm_pBackbone; - clsBackbone::sm_pBackbone = 0; + clsBackbone::sm_pBackbone = nullptr; } } if (clsBackbone::sm_pBackbone) @@ -854,7 +854,7 @@ bool clsLEAMDNSHost::_releaseBackbone(void) (0 == clsBackbone::sm_pBackbone->hostCount())) { delete clsBackbone::sm_pBackbone; - clsBackbone::sm_pBackbone = 0; + clsBackbone::sm_pBackbone = nullptr; DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _releaseBackbone: Released backbone."), _DH());); } DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _releaseBackbone: %s to remove host from backbone."), _DH(), (bResult ? "Succeeded" : "FAILED"));); @@ -1011,10 +1011,10 @@ bool clsLEAMDNSHost::_allocDomainName(const char* p_pcNewDomainName, bool clsLEAMDNSHost::_releaseDomainName(char*& p_rpcDomainName) { bool bResult; - if ((bResult = (0 != p_rpcDomainName))) + if ((bResult = (nullptr != p_rpcDomainName))) { delete[] p_rpcDomainName; - p_rpcDomainName = 0; + p_rpcDomainName = nullptr; } return bResult; } @@ -1139,7 +1139,7 @@ bool clsLEAMDNSHost::_removeQuery(clsLEAMDNSHost::clsQuery * p_pQuery) */ bool clsLEAMDNSHost::_removeLegacyQuery(void) { - clsQuery* pLegacyQuery = 0; + clsQuery* pLegacyQuery = nullptr; return (((pLegacyQuery = _findLegacyQuery())) ? _removeQuery(pLegacyQuery) : true); @@ -1151,7 +1151,7 @@ bool clsLEAMDNSHost::_removeLegacyQuery(void) */ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findLegacyQuery(void) { - clsQuery* pLegacyQuery = 0; + clsQuery* pLegacyQuery = nullptr; for (clsQuery* pQuery : m_Queries) { @@ -1186,7 +1186,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findNextQueryByDomain(const clsLEAMDN const clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType, const clsQuery * p_pPrevQuery) { - clsQuery* pMatchingQuery = 0; + clsQuery* pMatchingQuery = nullptr; clsQuery::list::iterator it(m_Queries.begin()); if (p_pPrevQuery) @@ -1223,7 +1223,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installServiceQuery( const char* p_pcService, const char* p_pcProtocol) { - clsQuery* pMDNSQuery = 0; + clsQuery* pMDNSQuery = nullptr; if ((p_pcService) && (*p_pcService) && (p_pcProtocol) && (*p_pcProtocol) && @@ -1254,7 +1254,7 @@ clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_installDomainQuery( clsLEAMDNSHost::clsRRDomain & p_Domain, clsLEAMDNSHost::clsQuery::enuQueryType p_QueryType) { - clsQuery* pQuery = 0; + clsQuery* pQuery = nullptr; if ((pQuery = _allocQuery(p_QueryType))) { From b27c540d48b943daefe628a5811c6d7dda1d7832 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 11:57:17 +0200 Subject: [PATCH 137/152] typo --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 38f10b1db1..e31de4d9b6 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -1530,7 +1530,7 @@ bool clsLEAMDNSHost::_readMDNSMsgHeader(clsLEAMDNSHost::clsMsgHeader& p_rMsgHead (_udpRead16(p_rMsgHeader.m_u16ARCount))) { - p_rMsgHeader.m_1bQR = (u8B1 & 0x80); // Query/Responde flag + p_rMsgHeader.m_1bQR = (u8B1 & 0x80); // Query/Response flag p_rMsgHeader.m_4bOpcode = (u8B1 & 0x78); // Operation code (0: Standard query, others ignored) p_rMsgHeader.m_1bAA = (u8B1 & 0x04); // Authorative answer p_rMsgHeader.m_1bTC = (u8B1 & 0x02); // Truncation flag From a5082020805af12230fba9308aa3cc9756d9eb7b Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 12:05:36 +0200 Subject: [PATCH 138/152] typos --- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index d6516be74f..24cc10b36b 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -8,7 +8,7 @@ Supported mDNS features (in some cases somewhat limited): - Announcing a DNS-SD service to interested observers, eg. a http server by announcing a esp8266._http._tcp.local. service - - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented + - Support for multi-level compressed names in input; in output only a very simple one-level full-name compression is implemented - Probing host and service domains for uniqueness in the local network - Tiebreaking while probing is supported in a very minimalistic way (the 'higher' IP address wins the tiebreak) - Announcing available services after successful probing @@ -27,7 +27,7 @@ In 'setup()': Create an clsLEAMDNSHost instance for every netif you plan to use. Call 'begin' on every instance with the intended hostname and the associated netif (or WiFi mode, WIFI_STA). - The given hostname is the 'probed' for uniqueness in the netifs local link. If domain name conflicts occure, the host name + The given hostname is the 'probed' for uniqueness in the netifs local link. If domain name conflicts occur, the host name will be automatically changed until it is unique in the local link. Optionally a callback can be registered in 'begin', to control the probing process manually. Next you can register DNS-SD services with 'addService("MyESP", "http", "tcp", 5000)' From da72802621207b0f9bc81ad128e6250ee81a1aeb Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 12:09:42 +0200 Subject: [PATCH 139/152] static const -> constexpr --- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 50 ++++++++++++------------ 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 24cc10b36b..b78afe4134 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -134,37 +134,36 @@ class clsLEAMDNSHost { public: #ifdef MDNS_IPV4_SUPPORT - static const uint16_t u16IPv4Size = 4; // IPv4 address size in bytes + static constexpr uint16_t u16IPv4Size = 4; // IPv4 address size in bytes #endif #ifdef MDNS_IPV6_SUPPORT - static const uint16_t u16IPv6Size = 16; // IPv6 address size in bytes + static constexpr uint16_t u16IPv6Size = 16; // IPv6 address size in bytes #endif - static const size_t stServiceTxtMaxLength = 1300; // Maximum length for all service txts for one service - static const size_t stDomainMaxLength = 256; // Maximum length for a full domain name eg. MyESP._http._tcp.local - static const size_t stDomainLabelMaxLength = 63; // Maximum length of on label in a domain name (length info fits into 6 bits) - static const size_t stServiceTypeMaxLength = 15; // Maximum length of a service name eg. http - static const size_t stServiceProtocolMaxLength = 3; // Maximum length of a service protocol name eg. tcp - - static const uint32_t u32LegacyTTL = 10; // Legacy DNS record TTL - static const uint32_t u32HostTTL = 120; // Host level records are set to 2min (120s) - static const uint32_t u32ServiceTTL = 4500; // Service level records are set to 75min (4500s) - - static const uint16_t u16SRVPriority = 0; // Default service priority and weight in SRV answers - static const uint16_t u16SRVWeight = 0; // - static const uint8_t u8DomainCompressMark = 0xC0; // Compressed labels are flaged by the two topmost bits of the length byte being set - static const uint8_t u8DomainMaxRedirections = 6; // Avoid endless recursion because of malformed compressed labels - - static const uint32_t u32ProbeDelay = 1000; // Default 250, but ESP is slow...; delay between and number of probes for host and service domains - static const uint32_t u32ProbeCount = 3; - static const uint32_t u32AnnounceDelay = 1000; // Delay between and number of announces for host and service domains - static const uint32_t u32AnnounceCount = 3; - static const uint32_t u32DynamicQueryResendDelay = 1000; // Delay between and number of queries; the delay is multiplied by the resent number in '_checkQueryCache' + static constexpr size_t stServiceTxtMaxLength = 1300; // Maximum length for all service txts for one service + static constexpr size_t stDomainMaxLength = 256; // Maximum length for a full domain name eg. MyESP._http._tcp.local + static constexpr size_t stDomainLabelMaxLength = 63; // Maximum length of on label in a domain name (length info fits into 6 bits) + static constexpr size_t stServiceTypeMaxLength = 15; // Maximum length of a service name eg. http + static constexpr size_t stServiceProtocolMaxLength = 3; // Maximum length of a service protocol name eg. tcp + + static constexpr uint32_t u32LegacyTTL = 10; // Legacy DNS record TTL + static constexpr uint32_t u32HostTTL = 120; // Host level records are set to 2min (120s) + static constexpr uint32_t u32ServiceTTL = 4500; // Service level records are set to 75min (4500s) + + static constexpr uint16_t u16SRVPriority = 0; // Default service priority and weight in SRV answers + static constexpr uint16_t u16SRVWeight = 0; // + static constexpr uint8_t u8DomainCompressMark = 0xC0; // Compressed labels are flaged by the two topmost bits of the length byte being set + static constexpr uint8_t u8DomainMaxRedirections = 6; // Avoid endless recursion because of malformed compressed labels + + static constexpr uint32_t u32ProbeDelay = 1000; // Default 250, but ESP is slow...; delay between and number of probes for host and service domains + static constexpr uint32_t u32ProbeCount = 3; + static constexpr uint32_t u32AnnounceDelay = 1000; // Delay between and number of announces for host and service domains + static constexpr uint32_t u32AnnounceCount = 3; + static constexpr uint32_t u32DynamicQueryResendDelay = 1000; // Delay between and number of queries; the delay is multiplied by the resent number in '_checkQueryCache' static const char* pcLocal; // "local"; static const char* pcServices; // "services"; static const char* pcDNSSD; // "dns-sd"; static const char* pcUDP; // "udp"; - //static const char* pcTCP; // "tcp"; #ifdef MDNS_IPV4_SUPPORT static const char* pcReverseIPv4Domain; // "in-addr"; @@ -175,11 +174,10 @@ class clsLEAMDNSHost static const char* pcReverseTopDomain; // "arpa"; #ifdef DNS_RRTYPE_NSEC - static const uint8_t u8DNS_RRTYPE_NSEC = DNS_RRTYPE_NSEC; + static constexpr uint8_t u8DNS_RRTYPE_NSEC = DNS_RRTYPE_NSEC; #else - static const uint8_t u8DNS_RRTYPE_NSEC = 0x2F; + static constexpr uint8_t u8DNS_RRTYPE_NSEC = 0x2F; #endif - //static const uint32_t u32SendCooldown = 50; // Delay (ms) between to 'UDPContext->send()' calls static constexpr uint32_t u32SendTimeoutMs = 50; // timeout (ms) for a call to `UDPContext->send()` (12ms=1460B@1Mb/s) }; From 140c45f3311a78af14cac19fe5744fb5b3ac65f0 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 12:13:38 +0200 Subject: [PATCH 140/152] nsec comment --- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index b78afe4134..184a6274fb 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -710,7 +710,7 @@ class clsLEAMDNSHost TXT, AAAA, SRV, - //NSEC, + //NSEC, not used - https://tools.ietf.org/html/rfc6762#section-6.1 Generic }; From fb1224c52fe3eab2da0a88dbc379c524585b58d5 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 12:19:52 +0200 Subject: [PATCH 141/152] typos --- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 2 +- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 184a6274fb..23d009827e 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -1243,7 +1243,7 @@ class clsLEAMDNSHost /* install*Query() creates several queries on the interfaces. - it no more returns a single query but a boolean until the API is adapted + it does not return a single query but a boolean until the API is adapted */ clsQuery* installServiceQuery(const char* p_pcServiceType, const char* p_pcProtocol, diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h index 2967c8a0c8..7052269762 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h @@ -8,11 +8,11 @@ Essentially, this is an rewrite of the original EPS8266 Multicast DNS code (ESP8266mDNS). The target of this rewrite was to keep the existing interface as stable as possible while adding and extending the supported set of mDNS features. - A lot of the additions were basicly taken from Erik Ekman's lwIP mdns app code. + A lot of the additions were basically taken from Erik Ekman's lwIP mdns app code. Supported mDNS features (in some cases somewhat limited): - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service - - Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented + - Support for multi-level compressed names in input; in output only a very simple one-level full-name compression is implemented - Probing host and service domains for uniqueness in the local network - Tiebreaking while probing is supported in a very minimalistic way (the 'higher' IP address wins the tiebreak) - Announcing available services after successful probing From 0a18d0fc522e53c9984b01336b6a987261347d56 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 12:20:06 +0200 Subject: [PATCH 142/152] typedef -> using --- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h | 37 ++++++++++++--------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h index 7052269762..2df7fe4940 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h @@ -167,7 +167,7 @@ class clsLEAMDNSHost_Legacy /** hMDNSService (opaque handle to access the service) */ - typedef const void* hMDNSService; + using hMDNSService = const void*; // Add a new service to the MDNS responder. If no name (instance name) is given (p_pcName = 0) // the current hostname is used. If the hostname is changed later, the instance names for @@ -206,7 +206,7 @@ class clsLEAMDNSHost_Legacy /** hMDNSTxt (opaque handle to access the TXT items) */ - typedef void* hMDNSTxt; + using hMDNSTxt = void*; // Add a (static) MDNS TXT item ('key' = 'value') to the service hMDNSTxt addServiceTxt(const hMDNSService p_hService, @@ -254,7 +254,7 @@ class clsLEAMDNSHost_Legacy MDNSDynamicServiceTxtCallbackFn Callback function for dynamic MDNS TXT items */ - typedef std::function<void(const hMDNSService p_hService)> MDNSDynamicServiceTxtCallbackFn; + using MDNSDynamicServiceTxtCallbackFn = std::function<void(const hMDNSService p_hService)>; // Set a global callback for dynamic MDNS TXT items. The callback function is called // every time, a TXT item is needed for one of the installed services. @@ -314,12 +314,12 @@ class clsLEAMDNSHost_Legacy /** hMDNSServiceQuery (opaque handle to access dynamic service queries) */ - typedef const void* hMDNSServiceQuery; + using hMDNSServiceQuery = const void*; /** enuServiceQueryAnswerType */ - typedef enum _enuServiceQueryAnswerType + using enuServiceQueryAnswerType = enum _enuServiceQueryAnswerType { ServiceQueryAnswerType_Unknown = 0, ServiceQueryAnswerType_ServiceDomain = (1 << 0), // Service instance name @@ -331,7 +331,7 @@ class clsLEAMDNSHost_Legacy #ifdef MDNS_IP6_SUPPORT ServiceQueryAnswerType_IP6Address = (1 << 4), // IP6 address #endif - } enuServiceQueryAnswerType; + }; /** AnswerType (std::map compatible version) @@ -504,10 +504,11 @@ class clsLEAMDNSHost_Legacy Callback function for received answers for dynamic service queries */ - typedef std::function<void(const stcMDNSServiceInfo& p_MDNSServiceInfo, + using MDNSServiceQueryCallbackFn = + std::function<void(const stcMDNSServiceInfo& p_MDNSServiceInfo, AnswerType p_AnswerType, // flags for the updated answer item bool p_bSetContent // true: Answer component set, false: component deleted - )> MDNSServiceQueryCallbackFn; + )>; // Install a dynamic service query. For every received answer (part) the given callback // function is called. The query will be updated every time, the TTL for an answer @@ -566,12 +567,14 @@ class clsLEAMDNSHost_Legacy MDNSHostProbeResultCallbackFn/2 Callback function for host domain probe results */ - typedef std::function<void(const char* p_pcDomainName, - bool p_bProbeResult)> MDNSHostProbeResultCallbackFn; + using MDNSHostProbeResultCallbackFn = + std::function<void(const char* p_pcDomainName, + bool p_bProbeResult)>; - typedef std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, + using MDNSHostProbeResultCallbackFn2 = + std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcDomainName, - bool p_bProbeResult)> MDNSHostProbeResultCallbackFn2; + bool p_bProbeResult)>; // Set a callback function for host probe results // The callback function is called, when the probeing for the host domain @@ -584,14 +587,16 @@ class clsLEAMDNSHost_Legacy MDNSServiceProbeResultCallbackFn/2 Callback function for service domain probe results */ - typedef std::function<void(const char* p_pcServiceName, + using MDNSServiceProbeResultCallbackFn = + std::function<void(const char* p_pcServiceName, const hMDNSService p_hMDNSService, - bool p_bProbeResult)> MDNSServiceProbeResultCallbackFn; + bool p_bProbeResult)>; - typedef std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, + using MDNSServiceProbeResultCallbackFn2 = + std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcServiceName, const hMDNSService p_hMDNSService, - bool p_bProbeResult)> MDNSServiceProbeResultCallbackFn2; + bool p_bProbeResult)>; // Set a service specific probe result callcack bool setServiceProbeResultCallback(const hMDNSService p_hService, From e50ff189d43c8ddb8d7ef61be0df5e431115c0d8 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 12:21:05 +0200 Subject: [PATCH 143/152] cleanup --- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h index 2df7fe4940..92ecb3d95e 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h @@ -484,9 +484,6 @@ class clsLEAMDNSHost_Legacy { m_KeyValueMap.emplace(std::pair<const char*, const char*>(kv.first, kv.second)); } - //for (auto kv=m_rMDNSResponder._answerKeyValue(m_hServiceQuery, m_u32AnswerIndex); kv!=nullptr; kv=kv->m_pNext) { - // m_KeyValueMap.emplace(std::pair<const char*,const char*>(kv->m_pcKey, kv->m_pcValue)); - //} } return m_KeyValueMap; } From 691c083cb353bcb9e8b3caeddbbb20f134fedc77 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 12:27:10 +0200 Subject: [PATCH 144/152] const for some function members --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 4 ++-- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 386a2c3709..d7eb40e02e 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -634,7 +634,7 @@ bool clsLEAMDNSHost::hasQuery(void) clsLEAmDNS2_Host::getQuery */ -clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::getQuery(void) +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::getQuery(void) const { return _findLegacyQuery(); } @@ -1149,7 +1149,7 @@ bool clsLEAMDNSHost::_removeLegacyQuery(void) clsLEAmDNS2_Host::_findLegacyQuery */ -clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findLegacyQuery(void) +clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findLegacyQuery(void) const { clsQuery* pLegacyQuery = nullptr; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h index 23d009827e..ddc5fc1adb 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.h @@ -206,7 +206,7 @@ class clsLEAMDNSHost size_t hostCount(void) const; bool setDelayUDPProcessing(bool p_bDelayProcessing); - clsLEAMDNSHost* getUniqueHost() + clsLEAMDNSHost* getUniqueHost() const { return m_uniqueHost; } @@ -1226,7 +1226,7 @@ class clsLEAMDNSHost const uint16_t p_u16Timeout); bool removeQuery(void); bool hasQuery(void); - clsQuery* getQuery(void); + clsQuery* getQuery(void) const; // - DYNAMIC // Install a dynamic service/host query. For every received answer (part) the given callback @@ -1330,7 +1330,7 @@ class clsLEAMDNSHost clsQuery* _allocQuery(clsQuery::enuQueryType p_QueryType); bool _removeQuery(clsQuery* p_pQuery); bool _removeLegacyQuery(void); - clsQuery* _findLegacyQuery(void); + clsQuery* _findLegacyQuery(void) const; bool _releaseQueries(void); clsQuery* _findNextQueryByDomain(const clsRRDomain& p_Domain, const clsQuery::enuQueryType p_QueryType, From 0dab814fc2e14a8a564ff1d9bb09b3e6f654eb7d Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 12:30:45 +0200 Subject: [PATCH 145/152] 0 -> nullptr --- libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp index 852068df19..87f263eff5 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp @@ -70,7 +70,7 @@ bool clsLEAMDNSHost::clsBackbone::init(void) */ UdpContext* clsLEAMDNSHost::clsBackbone::addHost(clsLEAMDNSHost* p_pHost) { - UdpContext* pUDPContext = 0; + UdpContext* pUDPContext = nullptr; if ((m_pUDPContext) && (p_pHost) && (m_uniqueHost == nullptr)) { @@ -193,7 +193,7 @@ bool clsLEAMDNSHost::clsBackbone::_releaseUDPContext(void) if (m_pUDPContext) { m_pUDPContext->unref(); - m_pUDPContext = 0; + m_pUDPContext = nullptr; } return true; } From d4bf122552645be961ff4ffb917fd567c67f9758 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 12:33:16 +0200 Subject: [PATCH 146/152] (*it). => it-> --- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp index 1aa900dda3..2bfc4f1ab2 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp @@ -120,10 +120,10 @@ bool clsLEAMDNSHost_Legacy::close(void) for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - if ((bResult = (*it).m_pHost->close())) + if ((bResult = it->m_pHost->close())) { - delete (*it).m_pHost; - (*it).m_pHost = 0; + delete it->m_pHost; + it->m_pHost = 0; } } return ((bResult) @@ -177,7 +177,7 @@ bool clsLEAMDNSHost_Legacy::setHostname(const char* p_pcHostname) for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - bResult = (*it).m_pHost->setHostName(p_pcHostname); + bResult = it->m_pHost->setHostName(p_pcHostname); } return bResult; } @@ -275,11 +275,11 @@ bool clsLEAMDNSHost_Legacy::removeService(const hMDNSService p_hService) for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; + clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)it->m_HandleToPtr[p_hService]; if ((bResult = ((pService) - && ((*it).m_pHost->removeService(pService))))) + && (it->m_pHost->removeService(pService))))) { - (*it).m_HandleToPtr.erase(p_hService); + it->m_HandleToPtr.erase(p_hService); } } return bResult; @@ -311,7 +311,7 @@ bool clsLEAMDNSHost_Legacy::setServiceName(const hMDNSService p_hService, for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; + clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)it->m_HandleToPtr[p_hService]; bResult = ((pService) && (pService->setInstanceName(p_pcInstanceName))); } @@ -518,13 +518,13 @@ bool clsLEAMDNSHost_Legacy::removeServiceTxt(const hMDNSService p_hService, for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; - clsLEAMDNSHost::clsServiceTxt* pTxt = (clsLEAMDNSHost::clsServiceTxt*)(*it).m_HandleToPtr[p_hTxt]; + clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)it->m_HandleToPtr[p_hService]; + clsLEAMDNSHost::clsServiceTxt* pTxt = (clsLEAMDNSHost::clsServiceTxt*)it->m_HandleToPtr[p_hTxt]; if ((bResult = ((pService) && (pTxt) && (pService->removeServiceTxt(pTxt))))) { - (*it).m_HandleToPtr.erase(p_hTxt); + it->m_HandleToPtr.erase(p_hTxt); } } return bResult; @@ -595,7 +595,7 @@ bool clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback(const hMDNSService p_hS for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService]; + clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)it->m_HandleToPtr[p_hService]; bResult = pService->setDynamicServiceTxtCallback([p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/)->void { if (p_fnCallback) // void(const hMDNSService p_hService) @@ -720,7 +720,7 @@ bool clsLEAMDNSHost_Legacy::removeQuery(void) for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - bResult = (*it).m_pHost->removeQuery(); + bResult = it->m_pHost->removeQuery(); } return bResult; } @@ -850,9 +850,9 @@ bool clsLEAMDNSHost_Legacy::removeServiceQuery(clsLEAMDNSHost_Legacy::hMDNSServi for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - if ((bResult = (*it).m_pHost->removeQuery((clsLEAMDNSHost::clsQuery*)(*it).m_HandleToPtr[p_hServiceQuery]))) + if ((bResult = it->m_pHost->removeQuery((clsLEAMDNSHost::clsQuery*)it->m_HandleToPtr[p_hServiceQuery]))) { - (*it).m_HandleToPtr.erase(p_hServiceQuery); + it->m_HandleToPtr.erase(p_hServiceQuery); } } return bResult; @@ -1101,7 +1101,7 @@ bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MD for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - bResult = (*it).m_pHost->setProbeResultCallback(clsLEAMDNSHost::stProbeResultCallback); + bResult = it->m_pHost->setProbeResultCallback(clsLEAMDNSHost::stProbeResultCallback); } return bResult; } @@ -1127,7 +1127,7 @@ bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MD for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - bResult = (*it).m_pHost->setProbeResultCallback(clsLEAMDNSHost::stProbeResultCallback); + bResult = it->m_pHost->setProbeResultCallback(clsLEAMDNSHost::stProbeResultCallback); } return bResult; } @@ -1144,7 +1144,7 @@ bool clsLEAMDNSHost_Legacy::setServiceProbeResultCallback(const clsLEAMDNSHost_L for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { clsLEAMDNSHost::clsService* pService = 0; - bResult = (((pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService])) + bResult = (((pService = (clsLEAMDNSHost::clsService*)it->m_HandleToPtr[p_hService])) && (pService->setProbeResultCallback( [this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, @@ -1173,7 +1173,7 @@ bool clsLEAMDNSHost_Legacy::setServiceProbeResultCallback(const clsLEAMDNSHost_L for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { clsLEAMDNSHost::clsService* pService = 0; - bResult = (((pService = (clsLEAMDNSHost::clsService*)(*it).m_HandleToPtr[p_hService])) + bResult = (((pService = (clsLEAMDNSHost::clsService*)it->m_HandleToPtr[p_hService])) && (pService->setProbeResultCallback([this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, const char* p_pcInstanceName, bool p_bProbeResult)->void @@ -1204,7 +1204,7 @@ bool clsLEAMDNSHost_Legacy::notifyAPChange(void) for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - bResult = (*it).m_pHost->restart(); + bResult = it->m_pHost->restart(); } return bResult; } @@ -1219,7 +1219,7 @@ bool clsLEAMDNSHost_Legacy::update(void) for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - bResult = (*it).m_pHost->update(); + bResult = it->m_pHost->update(); } return bResult; } @@ -1234,7 +1234,7 @@ bool clsLEAMDNSHost_Legacy::announce(void) for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) { - bResult = (*it).m_pHost->announce(true, true); + bResult = it->m_pHost->announce(true, true); } return bResult; } From 00453f1c62dee0ed0fbef29043ad3219de1e2f6f Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 12:39:50 +0200 Subject: [PATCH 147/152] cleanup --- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index e31de4d9b6..4f94afff0c 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -116,13 +116,6 @@ bool clsLEAMDNSHost::_sendMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParamete (m_pUDPContext->sendTimeout(ipRemote, m_pUDPContext->getRemotePort(), clsConsts::u32SendTimeoutMs)) /*&& (Serial.println("Did send UC"), true)*/); DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage (V4): FAILED!\n"), _DH());); -#if 0 - if ((clsConsts::u32SendCooldown) && - 1)//(can_yield())) - { - delay(clsConsts::u32SendCooldown); - } -#endif } else { @@ -186,13 +179,6 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe (m_pUDPContext->setMulticastInterface(0), true) /*&& (Serial.println("Did send MC V4"), true)*/); DEBUG_EX_ERR(if (!bIPv4Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (V4): FAILED!\n"), _DH());); -#if 0 - if ((clsConsts::u32SendCooldown) && - 1)//(can_yield())) - { - delay(clsConsts::u32SendCooldown); - } -#endif } #endif @@ -213,13 +199,6 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe (m_pUDPContext->setMulticastInterface(0), true) /*&& (Serial.println("Did send MC V6"), true)*/); DEBUG_EX_ERR(if (!bIPv6Result) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage_Multicast (IPv6): FAILED! (%s, %s, %s)\n"), _DH(), (_getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet() ? "1" : "0"), (bPrepareMessage ? "1" : "0"), (bUDPContextSend ? "1" : "0"));); -#if 0 - if ((clsConsts::u32SendCooldown) && - 1)//(can_yield())) - { - delay(clsConsts::u32SendCooldown); - } -#endif } #endif From 0c98b60dc8b8f32e903bd57588ee6fea6c470a92 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 12:53:00 +0200 Subject: [PATCH 148/152] style --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 4 +-- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h | 32 ++++++++++----------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index d7eb40e02e..7801b64d78 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -419,8 +419,8 @@ clsLEAMDNSHost::clsService* clsLEAMDNSHost::addService(const char* p_pcInstanceN } } } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s addService: %s to add service '%s.%s.%s.local'!\n"), _DH(pService), (pService ? "Succeeded" : "FAILED"), _instanceName(p_pcInstanceName)? : "-", (p_pcType ? : ""), (p_pcProtocol ? : ""));); - DEBUG_EX_ERR(if (!pService) DEBUG_OUTPUT.printf_P(PSTR("%s addService: FAILED to add service '%s.%s.%s.local'!\n"), _DH(pService), _instanceName(p_pcInstanceName)? : "-", (p_pcType ? : ""), (p_pcProtocol ? : ""));); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s addService: %s to add service '%s.%s.%s.local'!\n"), _DH(pService), (pService ? "Succeeded" : "FAILED"), _instanceName(p_pcInstanceName) ? : "-", (p_pcType ? : ""), (p_pcProtocol ? : ""));); + DEBUG_EX_ERR(if (!pService) DEBUG_OUTPUT.printf_P(PSTR("%s addService: FAILED to add service '%s.%s.%s.local'!\n"), _DH(pService), _instanceName(p_pcInstanceName) ? : "-", (p_pcType ? : ""), (p_pcProtocol ? : ""));); return pService; } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h index 92ecb3d95e..33668e11d1 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h @@ -502,10 +502,10 @@ class clsLEAMDNSHost_Legacy Callback function for received answers for dynamic service queries */ using MDNSServiceQueryCallbackFn = - std::function<void(const stcMDNSServiceInfo& p_MDNSServiceInfo, - AnswerType p_AnswerType, // flags for the updated answer item - bool p_bSetContent // true: Answer component set, false: component deleted - )>; + std::function<void(const stcMDNSServiceInfo& p_MDNSServiceInfo, + AnswerType p_AnswerType, // flags for the updated answer item + bool p_bSetContent // true: Answer component set, false: component deleted + )>; // Install a dynamic service query. For every received answer (part) the given callback // function is called. The query will be updated every time, the TTL for an answer @@ -565,13 +565,13 @@ class clsLEAMDNSHost_Legacy Callback function for host domain probe results */ using MDNSHostProbeResultCallbackFn = - std::function<void(const char* p_pcDomainName, - bool p_bProbeResult)>; + std::function<void(const char* p_pcDomainName, + bool p_bProbeResult)>; using MDNSHostProbeResultCallbackFn2 = - std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, - const char* p_pcDomainName, - bool p_bProbeResult)>; + std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, + const char* p_pcDomainName, + bool p_bProbeResult)>; // Set a callback function for host probe results // The callback function is called, when the probeing for the host domain @@ -585,15 +585,15 @@ class clsLEAMDNSHost_Legacy Callback function for service domain probe results */ using MDNSServiceProbeResultCallbackFn = - std::function<void(const char* p_pcServiceName, - const hMDNSService p_hMDNSService, - bool p_bProbeResult)>; + std::function<void(const char* p_pcServiceName, + const hMDNSService p_hMDNSService, + bool p_bProbeResult)>; using MDNSServiceProbeResultCallbackFn2 = - std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, - const char* p_pcServiceName, - const hMDNSService p_hMDNSService, - bool p_bProbeResult)>; + std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, + const char* p_pcServiceName, + const hMDNSService p_hMDNSService, + bool p_bProbeResult)>; // Set a service specific probe result callcack bool setServiceProbeResultCallback(const hMDNSService p_hService, From 15861cae6aaf0f62a34799b9508a4b09c1c6ac72 Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Tue, 22 Sep 2020 12:53:10 +0200 Subject: [PATCH 149/152] typo --- libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp index 4f94afff0c..f77e0a5e12 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp @@ -212,7 +212,7 @@ bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSe The MDNS message is composed in a two-step process. In the first loop 'only' the header informations (mainly number of answers) are collected, - while in the seconds loop, the header and all queries and answers are written to the UDP + while in the second loop, the header and all queries and answers are written to the UDP output buffer. */ From fb1a026ee5990a5d201b7f0f9dae869b30fa0f9b Mon Sep 17 00:00:00 2001 From: "TAURI20\\Herman" <hreintke@tauri.nl> Date: Thu, 24 Sep 2020 16:42:12 +0200 Subject: [PATCH 150/152] OTA service using hostname --- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp index 7801b64d78..f74739ae6f 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp @@ -784,7 +784,7 @@ bool clsLEAMDNSHost::restart(void) clsLEAMDNSHost::clsService* clsLEAMDNSHost::enableArduino(uint16_t p_u16Port, bool p_bAuthUpload /*= false*/) { - clsLEAMDNSHost::clsService* svc = addService("arduino", "arduino", "tcp", p_u16Port); + clsLEAMDNSHost::clsService* svc = addService(nullptr, "arduino", "tcp", p_u16Port); if (svc) { if ((!svc->addServiceTxt("tcp_check", "no")) From df56854110058600aa434fab213cecbdd22e6b0f Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 24 Sep 2020 23:10:49 +0200 Subject: [PATCH 151/152] remove: original mDNS implementation, and v2-to-v1=legacy adaptation implementation --- libraries/ESP8266mDNS/src/ESP8266mDNS.h | 6 +- .../ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp | 1523 ---------------- .../ESP8266mDNS/src/ESP8266mDNS_Legacy.h | 167 -- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp | 1531 ----------------- libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h | 700 -------- 5 files changed, 1 insertion(+), 3926 deletions(-) delete mode 100644 libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp delete mode 100644 libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h delete mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp delete mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index fd09760410..2e0e1fcec0 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -42,11 +42,9 @@ */ -enum class MDNSApiVersion { Legacy, LEA, LEAv2Compat, LEAv2 }; +enum class MDNSApiVersion { LEA, LEAv2 }; -#include "ESP8266mDNS_Legacy.h" // Legacy #include "LEAmDNS.h" // LEA -#include "LEAmDNS2_Legacy.h" // LEAv2Compat - replacement for LEA using v2 #include "LEAmDNS2Host.h" // LEAv2 - API updated // clsLEAMDNSHost replaces MDNSResponder in LEAv2 @@ -54,9 +52,7 @@ using clsLEAMDNSHost = esp8266::experimental::clsLEAMDNSHost; #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) // Maps the implementation to use to the global namespace type -//using MDNSResponder = Legacy_MDNSResponder::MDNSResponder; // Legacy using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA -//using MDNSResponder = experimental::MDNSImplementation::clsLEAMDNSHost_Legacy; // LEAv2Compat //using MDNSResponder = clsLEAMDNSHost; // LEAv2 extern MDNSResponder MDNS; diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp b/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp deleted file mode 100644 index be5666df7d..0000000000 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp +++ /dev/null @@ -1,1523 +0,0 @@ -/* - - ESP8266 Multicast DNS (port of CC3000 Multicast DNS library) - Version 1.1 - Copyright (c) 2013 Tony DiCola (tony@tonydicola.com) - ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com) - MDNS-SD Suport 2015 Hristo Gochkov - Extended MDNS-SD support 2016 Lars Englund (lars.englund@gmail.com) - - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -// Important RFC's for reference: -// - DNS request and response: http://www.ietf.org/rfc/rfc1035.txt -// - Multicast DNS: http://www.ietf.org/rfc/rfc6762.txt -// - MDNS-SD: https://tools.ietf.org/html/rfc6763 - -#ifndef LWIP_OPEN_SRC -#define LWIP_OPEN_SRC -#endif - -#include <ESP8266mDNS_Legacy.h> -#include <functional> - -#include "debug.h" - -extern "C" { -#include "osapi.h" -#include "ets_sys.h" -#include "user_interface.h" -} - -#include "WiFiUdp.h" -#include "lwip/opt.h" -#include "lwip/udp.h" -#include "lwip/inet.h" -#include "lwip/igmp.h" -#include "lwip/mem.h" -#include "include/UdpContext.h" - - - -namespace Legacy_MDNSResponder -{ - - -#ifdef DEBUG_ESP_MDNS -#define DEBUG_ESP_MDNS_ERR -#define DEBUG_ESP_MDNS_TX -#define DEBUG_ESP_MDNS_RX -#endif - -#define MDNS_NAME_REF 0xC000 - -#define MDNS_TYPE_AAAA 0x001C -#define MDNS_TYPE_A 0x0001 -#define MDNS_TYPE_PTR 0x000C -#define MDNS_TYPE_SRV 0x0021 -#define MDNS_TYPE_TXT 0x0010 - -#define MDNS_CLASS_IN 0x0001 -#define MDNS_CLASS_IN_FLUSH_CACHE 0x8001 - -#define MDNS_ANSWERS_ALL 0x0F -#define MDNS_ANSWER_PTR 0x08 -#define MDNS_ANSWER_TXT 0x04 -#define MDNS_ANSWER_SRV 0x02 -#define MDNS_ANSWER_A 0x01 - -#define _conn_read32() (((uint32_t)_conn->read() << 24) | ((uint32_t)_conn->read() << 16) | ((uint32_t)_conn->read() << 8) | _conn->read()) -#define _conn_read16() (((uint16_t)_conn->read() << 8) | _conn->read()) -#define _conn_read8() _conn->read() -#define _conn_readS(b,l) _conn->read((char*)(b),l); - -static const IPAddress MDNS_MULTICAST_ADDR(224, 0, 0, 251); -static const int MDNS_MULTICAST_TTL = 1; -static const int MDNS_PORT = 5353; - -struct MDNSService -{ - MDNSService* _next; - char _name[32]; - char _proto[4]; - uint16_t _port; - uint16_t _txtLen; // length of all txts - struct MDNSTxt * _txts; -}; - -struct MDNSTxt -{ - MDNSTxt * _next; - String _txt; -}; - -struct MDNSAnswer -{ - MDNSAnswer* next; - uint8_t ip[4]; - uint16_t port; - char *hostname; -}; - -struct MDNSQuery -{ - char _service[32]; - char _proto[4]; -}; - - -MDNSResponder::MDNSResponder() : _conn(0) -{ - _services = 0; - _instanceName = ""; - _answers = 0; - _query = 0; - _newQuery = false; - _waitingForAnswers = false; -} -MDNSResponder::~MDNSResponder() -{ - if (_query != 0) - { - os_free(_query); - _query = 0; - } - - // Clear answer list - MDNSAnswer *answer; - int numAnswers = _getNumAnswers(); - for (int n = numAnswers - 1; n >= 0; n--) - { - answer = _getAnswerFromIdx(n); - os_free(answer->hostname); - os_free(answer); - answer = 0; - } - _answers = 0; - - if (_conn) - { - _conn->unref(); - } -} - -bool MDNSResponder::begin(const char* hostname) -{ - size_t n = strlen(hostname); - if (n > 63) // max size for a single label. - { - return false; - } - - // Copy in hostname characters as lowercase - _hostName = hostname; - _hostName.toLowerCase(); - - // If instance name is not already set copy hostname to instance name - if (_instanceName.equals("")) - { - _instanceName = hostname; - } - - _gotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP & event) - { - (void) event; - _restart(); - }); - - _disconnectedHandler = WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected & event) - { - (void) event; - _restart(); - }); - - return _listen(); -} - -void MDNSResponder::notifyAPChange() -{ - _restart(); -} - -void MDNSResponder::_restart() -{ - if (_conn) - { - _conn->unref(); - _conn = nullptr; - } - _listen(); -} - -bool MDNSResponder::_listen() -{ - // Open the MDNS socket if it isn't already open. - if (!_conn) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.println("MDNS listening"); -#endif - - IPAddress mdns(MDNS_MULTICAST_ADDR); - - if (igmp_joingroup(IP4_ADDR_ANY4, mdns) != ERR_OK) - { - return false; - } - - _conn = new UdpContext; - _conn->ref(); - - if (!_conn->listen(IP_ADDR_ANY, MDNS_PORT)) - { - return false; - } - _conn->setMulticastTTL(MDNS_MULTICAST_TTL); - _conn->onRx(std::bind(&MDNSResponder::update, this)); - _conn->connect(mdns, MDNS_PORT); - } - return true; -} - -void MDNSResponder::update() -{ - if (!_conn || !_conn->next()) - { - return; - } - _parsePacket(); -} - - -void MDNSResponder::setInstanceName(String name) -{ - if (name.length() > 63) - { - return; - } - _instanceName = name; -} - - -bool MDNSResponder::addServiceTxt(char *name, char *proto, char *key, char *value) -{ - MDNSService* servicePtr; - - uint8_t txtLen = os_strlen(key) + os_strlen(value) + 1; // Add one for equals sign - txtLen += 1; //accounts for length byte added when building the txt responce - //Find the service - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - //Checking Service names - if (strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) - { - //found a service name match - if (servicePtr->_txtLen + txtLen > 1300) - { - return false; //max txt record size - } - MDNSTxt *newtxt = new MDNSTxt; - newtxt->_txt = String(key) + '=' + String(value); - newtxt->_next = 0; - if (servicePtr->_txts == 0) //no services have been added - { - //Adding First TXT to service - servicePtr->_txts = newtxt; - servicePtr->_txtLen += txtLen; - return true; - } - else - { - MDNSTxt * txtPtr = servicePtr->_txts; - while (txtPtr->_next != 0) - { - txtPtr = txtPtr->_next; - } - //adding another TXT to service - txtPtr->_next = newtxt; - servicePtr->_txtLen += txtLen; - return true; - } - } - } - return false; -} - -void MDNSResponder::addService(char *name, char *proto, uint16_t port) -{ - if (_getServicePort(name, proto) != 0) - { - return; - } - if (os_strlen(name) > 32 || os_strlen(proto) != 3) - { - return; //bad arguments - } - struct MDNSService *srv = (struct MDNSService*)(os_malloc(sizeof(struct MDNSService))); - os_strcpy(srv->_name, name); - os_strcpy(srv->_proto, proto); - srv->_port = port; - srv->_next = 0; - srv->_txts = 0; - srv->_txtLen = 0; - - if (_services == 0) - { - _services = srv; - } - else - { - MDNSService* servicePtr = _services; - while (servicePtr->_next != 0) - { - servicePtr = servicePtr->_next; - } - servicePtr->_next = srv; - } - -} - -int MDNSResponder::queryService(char *service, char *proto) -{ -#ifdef DEBUG_ESP_MDNS_TX - DEBUG_ESP_PORT.printf("queryService %s %s\n", service, proto); -#endif - while (_answers != 0) - { - MDNSAnswer *currAnswer = _answers; - _answers = _answers->next; - os_free(currAnswer->hostname); - os_free(currAnswer); - currAnswer = 0; - } - if (_query != 0) - { - os_free(_query); - _query = 0; - } - _query = (struct MDNSQuery*)(os_malloc(sizeof(struct MDNSQuery))); - os_strcpy(_query->_service, service); - os_strcpy(_query->_proto, proto); - _newQuery = true; - - char underscore[] = "_"; - - // build service name with _ - char serviceName[os_strlen(service) + 2]; - os_strcpy(serviceName, underscore); - os_strcat(serviceName, service); - size_t serviceNameLen = os_strlen(serviceName); - - //build proto name with _ - char protoName[5]; - os_strcpy(protoName, underscore); - os_strcat(protoName, proto); - size_t protoNameLen = 4; - - //local string - char localName[] = "local"; - size_t localNameLen = 5; - - //terminator - char terminator[] = "\0"; - - // Only supports sending one PTR query - uint8_t questionCount = 1; - - _waitingForAnswers = true; - for (int itfn = 0; itfn < 2; itfn++) - { - struct ip_info ip_info; - - wifi_get_ip_info((!itfn) ? SOFTAP_IF : STATION_IF, &ip_info); - if (!ip_info.ip.addr) - { - continue; - } - _conn->setMulticastInterface(IPAddress(ip_info.ip.addr)); - - // Write the header - _conn->flush(); - uint8_t head[12] = - { - 0x00, 0x00, //ID = 0 - 0x00, 0x00, //Flags = response + authoritative answer - 0x00, questionCount, //Question count - 0x00, 0x00, //Answer count - 0x00, 0x00, //Name server records - 0x00, 0x00 //Additional records - }; - _conn->append(reinterpret_cast<const char*>(head), 12); - - // Only supports sending one PTR query - // Send the Name field (eg. "_http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_" + service - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_" + service - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_" + proto - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_" + proto - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length of "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type and class - uint8_t ptrAttrs[4] = - { - 0x00, 0x0c, //PTR record query - 0x00, 0x01 //Class IN - }; - _conn->append(reinterpret_cast<const char*>(ptrAttrs), 4); - _conn->send(); - } - -#ifdef DEBUG_ESP_MDNS_TX - DEBUG_ESP_PORT.println("Waiting for answers.."); -#endif - delay(1000); - - _waitingForAnswers = false; - - return _getNumAnswers(); -} - -String MDNSResponder::hostname(int idx) -{ - MDNSAnswer *answer = _getAnswerFromIdx(idx); - if (answer == 0) - { - return String(); - } - return answer->hostname; -} - -IPAddress MDNSResponder::IP(int idx) -{ - MDNSAnswer *answer = _getAnswerFromIdx(idx); - if (answer == 0) - { - return IPAddress(); - } - return IPAddress(answer->ip); -} - -uint16_t MDNSResponder::port(int idx) -{ - MDNSAnswer *answer = _getAnswerFromIdx(idx); - if (answer == 0) - { - return 0; - } - return answer->port; -} - -MDNSAnswer* MDNSResponder::_getAnswerFromIdx(int idx) -{ - MDNSAnswer *answer = _answers; - while (answer != 0 && idx-- > 0) - { - answer = answer->next; - } - if (idx > 0) - { - return 0; - } - return answer; -} - -int MDNSResponder::_getNumAnswers() -{ - int numAnswers = 0; - MDNSAnswer *answer = _answers; - while (answer != 0) - { - numAnswers++; - answer = answer->next; - } - return numAnswers; -} - -MDNSTxt * MDNSResponder::_getServiceTxt(char *name, char *proto) -{ - MDNSService* servicePtr; - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - if (servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) - { - if (servicePtr->_txts == 0) - { - return nullptr; - } - return servicePtr->_txts; - } - } - return nullptr; -} - -uint16_t MDNSResponder::_getServiceTxtLen(char *name, char *proto) -{ - MDNSService* servicePtr; - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - if (servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) - { - if (servicePtr->_txts == 0) - { - return false; - } - return servicePtr->_txtLen; - } - } - return 0; -} - -uint16_t MDNSResponder::_getServicePort(char *name, char *proto) -{ - MDNSService* servicePtr; - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - if (servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0) - { - return servicePtr->_port; - } - } - return 0; -} - -IPAddress MDNSResponder::_getRequestMulticastInterface() -{ - struct ip_info ip_info; - bool match_ap = false; - if (wifi_get_opmode() & SOFTAP_MODE) - { - const IPAddress& remote_ip = _conn->getRemoteAddress(); - wifi_get_ip_info(SOFTAP_IF, &ip_info); - IPAddress infoIp(ip_info.ip); - IPAddress infoMask(ip_info.netmask); - if (ip_info.ip.addr && ip_addr_netcmp((const ip_addr_t*)remote_ip, (const ip_addr_t*)infoIp, ip_2_ip4((const ip_addr_t*)infoMask))) - { - match_ap = true; - } - } - if (!match_ap) - { - wifi_get_ip_info(STATION_IF, &ip_info); - } - return IPAddress(ip_info.ip.addr); -} - -void MDNSResponder::_parsePacket() -{ - int i; - char tmp; - bool serviceParsed = false; - bool protoParsed = false; - bool localParsed = false; - - char hostName[255]; - uint8_t hostNameLen; - - char serviceName[32]; - uint8_t serviceNameLen; - uint16_t servicePort = 0; - - char protoName[32]; - protoName[0] = 0; - uint8_t protoNameLen = 0; - - uint16_t packetHeader[6]; - - for (i = 0; i < 6; i++) - { - packetHeader[i] = _conn_read16(); - } - - if ((packetHeader[1] & 0x8000) != 0) // Read answers - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("Reading answers RX: REQ, ID:%u, Q:%u, A:%u, NS:%u, ADD:%u\n", packetHeader[0], packetHeader[2], packetHeader[3], packetHeader[4], packetHeader[5]); -#endif - - if (!_waitingForAnswers) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.println("Not expecting any answers right now, returning"); -#endif - _conn->flush(); - return; - } - - int numAnswers = packetHeader[3] + packetHeader[5]; - // Assume that the PTR answer always comes first and that it is always accompanied by a TXT, SRV, AAAA (optional) and A answer in the same packet. - if (numAnswers < 4) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("Expected a packet with 4 or more answers, got %u\n", numAnswers); -#endif - _conn->flush(); - return; - } - - uint8_t tmp8; - uint16_t answerPort = 0; - uint8_t answerIp[4] = { 0, 0, 0, 0 }; - char answerHostName[255]; - bool serviceMatch = false; - MDNSAnswer *answer; - uint8_t partsCollected = 0; - uint8_t stringsRead = 0; - - answerHostName[0] = '\0'; - - // Clear answer list - if (_newQuery) - { - int oldAnswers = _getNumAnswers(); - for (int n = oldAnswers - 1; n >= 0; n--) - { - answer = _getAnswerFromIdx(n); - os_free(answer->hostname); - os_free(answer); - answer = 0; - } - _answers = 0; - _newQuery = false; - } - - while (numAnswers--) - { - // Read name - stringsRead = 0; - size_t last_bufferpos = 0; - do - { - tmp8 = _conn_read8(); - if (tmp8 == 0x00) // End of name - { - break; - } - if (tmp8 & 0xC0) // Compressed pointer - { - uint16_t offset = ((((uint16_t)tmp8) & ~0xC0) << 8) | _conn_read8(); - if (_conn->isValidOffset(offset)) - { - if (0 == last_bufferpos) - { - last_bufferpos = _conn->tell(); - } -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Compressed pointer, jumping from "); - DEBUG_ESP_PORT.print(last_bufferpos); - DEBUG_ESP_PORT.print(" to "); - DEBUG_ESP_PORT.println(offset); -#endif - _conn->seek(offset); - tmp8 = _conn_read8(); - } - else - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Skipping malformed compressed pointer"); -#endif - tmp8 = _conn_read8(); - break; - } - } - if (stringsRead > 3) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.println("failed to read the response name"); -#endif - _conn->flush(); - return; - } - _conn_readS(serviceName, tmp8); - serviceName[tmp8] = '\0'; -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf(" %d ", tmp8); - for (int n = 0; n < tmp8; n++) - { - DEBUG_ESP_PORT.printf("%c", serviceName[n]); - } - DEBUG_ESP_PORT.println(); -#endif - if (serviceName[0] == '_') - { - if (strcmp(&serviceName[1], _query->_service) == 0) - { - serviceMatch = true; -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("found matching service: %s\n", _query->_service); -#endif - } - } - stringsRead++; - } while (true); - if (last_bufferpos > 0) - { - _conn->seek(last_bufferpos); -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Compressed pointer, jumping back to "); - DEBUG_ESP_PORT.println(last_bufferpos); -#endif - } - - uint16_t answerType = _conn_read16(); // Read type - uint16_t answerClass = _conn_read16(); // Read class - uint32_t answerTtl = _conn_read32(); // Read ttl - uint16_t answerRdlength = _conn_read16(); // Read rdlength - - (void) answerClass; - (void) answerTtl; - - if (answerRdlength > 255) - { - if (answerType == MDNS_TYPE_TXT && answerRdlength < 1460) - { - while (--answerRdlength) - { - _conn->read(); - } - } - else - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("Data len too long! %u\n", answerRdlength); -#endif - _conn->flush(); - return; - } - } - -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("type: %04x rdlength: %d\n", answerType, answerRdlength); -#endif - - if (answerType == MDNS_TYPE_PTR) - { - partsCollected |= 0x01; - _conn_readS(hostName, answerRdlength); // Read rdata - if (hostName[answerRdlength - 2] & 0xc0) - { - memcpy(answerHostName, hostName + 1, answerRdlength - 3); - answerHostName[answerRdlength - 3] = '\0'; - } -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("PTR %d ", answerRdlength); - for (int n = 0; n < answerRdlength; n++) - { - DEBUG_ESP_PORT.printf("%c", hostName[n]); - } - DEBUG_ESP_PORT.println(); -#endif - } - - else if (answerType == MDNS_TYPE_TXT) - { - partsCollected |= 0x02; - _conn_readS(hostName, answerRdlength); // Read rdata -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("TXT %d ", answerRdlength); - for (int n = 0; n < answerRdlength; n++) - { - DEBUG_ESP_PORT.printf("%c", hostName[n]); - } - DEBUG_ESP_PORT.println(); -#endif - } - - else if (answerType == MDNS_TYPE_SRV) - { - partsCollected |= 0x04; - uint16_t answerPrio = _conn_read16(); // Read priority - uint16_t answerWeight = _conn_read16(); // Read weight - answerPort = _conn_read16(); // Read port - last_bufferpos = 0; - - (void) answerPrio; - (void) answerWeight; - - // Read hostname - tmp8 = _conn_read8(); - if (tmp8 & 0xC0) // Compressed pointer - { - uint16_t offset = ((((uint16_t)tmp8) & ~0xC0) << 8) | _conn_read8(); - if (_conn->isValidOffset(offset)) - { - last_bufferpos = _conn->tell(); -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Compressed pointer, jumping from "); - DEBUG_ESP_PORT.print(last_bufferpos); - DEBUG_ESP_PORT.print(" to "); - DEBUG_ESP_PORT.println(offset); -#endif - _conn->seek(offset); - tmp8 = _conn_read8(); - } - else - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Skipping malformed compressed pointer"); -#endif - tmp8 = _conn_read8(); - break; - } - } - _conn_readS(answerHostName, tmp8); - answerHostName[tmp8] = '\0'; -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("SRV %d ", tmp8); - for (int n = 0; n < tmp8; n++) - { - DEBUG_ESP_PORT.printf("%02x ", answerHostName[n]); - } - DEBUG_ESP_PORT.printf("\n%s\n", answerHostName); -#endif - if (last_bufferpos > 0) - { - _conn->seek(last_bufferpos); - tmp8 = 2; // Size of compression octets -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.print("Compressed pointer, jumping back to "); - DEBUG_ESP_PORT.println(last_bufferpos); -#endif - } - if (answerRdlength - (6 + 1 + tmp8) > 0) // Skip any remaining rdata - { - _conn_readS(hostName, answerRdlength - (6 + 1 + tmp8)); - } - } - - else if (answerType == MDNS_TYPE_A) - { - partsCollected |= 0x08; - for (int i = 0; i < 4; i++) - { - answerIp[i] = _conn_read8(); - } - } - else - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("Ignoring unsupported type %02x\n", tmp8); -#endif - for (int n = 0; n < answerRdlength; n++) - { - (void)_conn_read8(); - } - } - - if ((partsCollected == 0x0F) && serviceMatch) - { -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.println("All answers parsed, adding to _answers list.."); -#endif - // Add new answer to answer list - if (_answers == 0) - { - _answers = (struct MDNSAnswer*)(os_malloc(sizeof(struct MDNSAnswer))); - answer = _answers; - } - else - { - answer = _answers; - while (answer->next != 0) - { - answer = answer->next; - } - answer->next = (struct MDNSAnswer*)(os_malloc(sizeof(struct MDNSAnswer))); - answer = answer->next; - } - answer->next = 0; - answer->hostname = 0; - - // Populate new answer - answer->port = answerPort; - for (int i = 0; i < 4; i++) - { - answer->ip[i] = answerIp[i]; - } - answer->hostname = (char *)os_malloc(strlen(answerHostName) + 1); - os_strcpy(answer->hostname, answerHostName); - _conn->flush(); - return; - } - } - - _conn->flush(); - return; - } - - // PARSE REQUEST NAME - - hostNameLen = _conn_read8() % 255; - _conn_readS(hostName, hostNameLen); - hostName[hostNameLen] = '\0'; - - if (hostName[0] == '_') - { - serviceParsed = true; - memcpy(serviceName, hostName + 1, hostNameLen); - serviceNameLen = hostNameLen - 1; - hostNameLen = 0; - } - - if (hostNameLen > 0 && !_hostName.equals(hostName) && !_instanceName.equals(hostName)) - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_NO_HOST: %s\n", hostName); - DEBUG_ESP_PORT.printf("hostname: %s\n", _hostName.c_str()); - DEBUG_ESP_PORT.printf("instance: %s\n", _instanceName.c_str()); -#endif - _conn->flush(); - return; - } - - if (!serviceParsed) - { - serviceNameLen = _conn_read8() % 255; - _conn_readS(serviceName, serviceNameLen); - serviceName[serviceNameLen] = '\0'; - - if (serviceName[0] == '_') - { - memmove(serviceName, serviceName + 1, serviceNameLen); - serviceNameLen--; - serviceParsed = true; - } - else if (serviceNameLen == 5 && strcmp("local", serviceName) == 0) - { - tmp = _conn_read8(); - if (tmp == 0) - { - serviceParsed = true; - serviceNameLen = 0; - protoParsed = true; - protoNameLen = 0; - localParsed = true; - } - else - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_FQDN: %s\n", serviceName); -#endif - _conn->flush(); - return; - } - } - else - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_SERVICE: %s\n", serviceName); -#endif - _conn->flush(); - return; - } - } - - if (!protoParsed) - { - protoNameLen = _conn_read8() % 255; - _conn_readS(protoName, protoNameLen); - protoName[protoNameLen] = '\0'; - if (protoNameLen == 4 && protoName[0] == '_') - { - memmove(protoName, protoName + 1, protoNameLen); - protoNameLen--; - protoParsed = true; - } - else if (strcmp("services", serviceName) == 0 && strcmp("_dns-sd", protoName) == 0) - { - _conn->flush(); - IPAddress interface = _getRequestMulticastInterface(); - _replyToTypeEnumRequest(interface); - return; - } - else - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_PROTO: %s\n", protoName); -#endif - _conn->flush(); - return; - } - } - - if (!localParsed) - { - char localName[32]; - uint8_t localNameLen = _conn_read8() % 31; - _conn_readS(localName, localNameLen); - localName[localNameLen] = '\0'; - tmp = _conn_read8(); - if (localNameLen == 5 && strcmp("local", localName) == 0 && tmp == 0) - { - localParsed = true; - } - else - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_FQDN: %s\n", localName); -#endif - _conn->flush(); - return; - } - } - - if (serviceNameLen > 0 && protoNameLen > 0) - { - servicePort = _getServicePort(serviceName, protoName); - if (servicePort == 0) - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_NO_SERVICE: %s\n", serviceName); -#endif - _conn->flush(); - return; - } - } - else if (serviceNameLen > 0 || protoNameLen > 0) - { -#ifdef DEBUG_ESP_MDNS_ERR - DEBUG_ESP_PORT.printf("ERR_SERVICE_PROTO: %s\n", serviceName); -#endif - _conn->flush(); - return; - } - - // RESPOND - -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("RX: REQ, ID:%u, Q:%u, A:%u, NS:%u, ADD:%u\n", packetHeader[0], packetHeader[2], packetHeader[3], packetHeader[4], packetHeader[5]); -#endif - - uint16_t currentType; - uint16_t currentClass; - - int numQuestions = packetHeader[2]; - if (numQuestions > 4) - { - numQuestions = 4; - } - uint16_t questions[4]; - int question = 0; - - while (numQuestions--) - { - currentType = _conn_read16(); - if (currentType & MDNS_NAME_REF) //new header handle it better! - { - currentType = _conn_read16(); - } - currentClass = _conn_read16(); - if (currentClass & MDNS_CLASS_IN) - { - questions[question++] = currentType; - } - - if (numQuestions > 0) - { - if (_conn_read16() != 0xC00C) //new question but for another host/service - { - _conn->flush(); - numQuestions = 0; - } - } - -#ifdef DEBUG_ESP_MDNS_RX - DEBUG_ESP_PORT.printf("REQ: "); - if (hostNameLen > 0) - { - DEBUG_ESP_PORT.printf("%s.", hostName); - } - if (serviceNameLen > 0) - { - DEBUG_ESP_PORT.printf("_%s.", serviceName); - } - if (protoNameLen > 0) - { - DEBUG_ESP_PORT.printf("_%s.", protoName); - } - DEBUG_ESP_PORT.printf("local. "); - - if (currentType == MDNS_TYPE_AAAA) - { - DEBUG_ESP_PORT.printf(" AAAA "); - } - else if (currentType == MDNS_TYPE_A) - { - DEBUG_ESP_PORT.printf(" A "); - } - else if (currentType == MDNS_TYPE_PTR) - { - DEBUG_ESP_PORT.printf(" PTR "); - } - else if (currentType == MDNS_TYPE_SRV) - { - DEBUG_ESP_PORT.printf(" SRV "); - } - else if (currentType == MDNS_TYPE_TXT) - { - DEBUG_ESP_PORT.printf(" TXT "); - } - else - { - DEBUG_ESP_PORT.printf(" 0x%04X ", currentType); - } - - if (currentClass == MDNS_CLASS_IN) - { - DEBUG_ESP_PORT.printf(" IN "); - } - else if (currentClass == MDNS_CLASS_IN_FLUSH_CACHE) - { - DEBUG_ESP_PORT.printf(" IN[F] "); - } - else - { - DEBUG_ESP_PORT.printf(" 0x%04X ", currentClass); - } - - DEBUG_ESP_PORT.printf("\n"); -#endif - } - uint8_t questionMask = 0; - uint8_t responseMask = 0; - for (i = 0; i < question; i++) - { - if (questions[i] == MDNS_TYPE_A) - { - questionMask |= 0x1; - responseMask |= 0x1; - } - else if (questions[i] == MDNS_TYPE_SRV) - { - questionMask |= 0x2; - responseMask |= 0x3; - } - else if (questions[i] == MDNS_TYPE_TXT) - { - questionMask |= 0x4; - responseMask |= 0x4; - } - else if (questions[i] == MDNS_TYPE_PTR) - { - questionMask |= 0x8; - responseMask |= 0xF; - } - } - - IPAddress interface = _getRequestMulticastInterface(); - return _replyToInstanceRequest(questionMask, responseMask, serviceName, protoName, servicePort, interface); -} - - -/** - STRINGIZE -*/ -#ifndef STRINGIZE -#define STRINGIZE(x) #x -#endif -#ifndef STRINGIZE_VALUE_OF -#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) -#endif - - -void MDNSResponder::enableArduino(uint16_t port, bool auth) -{ - - addService("arduino", "tcp", port); - addServiceTxt("arduino", "tcp", "tcp_check", "no"); - addServiceTxt("arduino", "tcp", "ssh_upload", "no"); - addServiceTxt("arduino", "tcp", "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD)); - addServiceTxt("arduino", "tcp", "auth_upload", (auth) ? "yes" : "no"); -} - -void MDNSResponder::_replyToTypeEnumRequest(IPAddress multicastInterface) -{ - MDNSService* servicePtr; - for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) - { - if (servicePtr->_port > 0) - { - char *service = servicePtr->_name; - char *proto = servicePtr->_proto; - //uint16_t port = servicePtr->_port; - -#ifdef DEBUG_ESP_MDNS_TX - DEBUG_ESP_PORT.printf("TX: service:%s, proto:%s\n", service, proto); -#endif - - char sdHostName[] = "_services"; - size_t sdHostNameLen = 9; - char sdServiceName[] = "_dns-sd"; - size_t sdServiceNameLen = 7; - char sdProtoName[] = "_udp"; - size_t sdProtoNameLen = 4; - - char underscore[] = "_"; - - // build service name with _ - char serviceName[os_strlen(service) + 2]; - os_strcpy(serviceName, underscore); - os_strcat(serviceName, service); - size_t serviceNameLen = os_strlen(serviceName); - - //build proto name with _ - char protoName[5]; - os_strcpy(protoName, underscore); - os_strcat(protoName, proto); - size_t protoNameLen = 4; - - //local string - char localName[] = "local"; - size_t localNameLen = 5; - - //terminator - char terminator[] = "\0"; - - //Write the header - _conn->flush(); - uint8_t head[12] = - { - 0x00, 0x00, //ID = 0 - 0x84, 0x00, //Flags = response + authoritative answer - 0x00, 0x00, //Question count - 0x00, 0x01, //Answer count - 0x00, 0x00, //Name server records - 0x00, 0x00, //Additional records - }; - _conn->append(reinterpret_cast<const char*>(head), 12); - - // Send the Name field (ie. "_services._dns-sd._udp.local") - _conn->append(reinterpret_cast<const char*>(&sdHostNameLen), 1); // length of "_services" - _conn->append(reinterpret_cast<const char*>(sdHostName), sdHostNameLen); // "_services" - _conn->append(reinterpret_cast<const char*>(&sdServiceNameLen), 1); // length of "_dns-sd" - _conn->append(reinterpret_cast<const char*>(sdServiceName), sdServiceNameLen);// "_dns-sd" - _conn->append(reinterpret_cast<const char*>(&sdProtoNameLen), 1); // length of "_udp" - _conn->append(reinterpret_cast<const char*>(sdProtoName), sdProtoNameLen); // "_udp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type, class, ttl and rdata length - uint8_t ptrDataLen = serviceNameLen + protoNameLen + localNameLen + 4; // 4 is three label sizes and the terminator - uint8_t ptrAttrs[10] = - { - 0x00, 0x0c, //PTR record query - 0x00, 0x01, //Class IN - 0x00, 0x00, 0x11, 0x94, //TTL 4500 - 0x00, ptrDataLen, //RData length - }; - _conn->append(reinterpret_cast<const char*>(ptrAttrs), 10); - - //Send the RData (ie. "_http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - _conn->setMulticastInterface(multicastInterface); - _conn->send(); - } - } -} - -void MDNSResponder::_replyToInstanceRequest(uint8_t questionMask, uint8_t responseMask, char * service, char *proto, uint16_t port, IPAddress multicastInterface) -{ - int i; - if (questionMask == 0) - { - return; - } - if (responseMask == 0) - { - return; - } - -#ifdef DEBUG_ESP_MDNS_TX - DEBUG_ESP_PORT.printf("TX: qmask:%01X, rmask:%01X, service:%s, proto:%s, port:%u\n", questionMask, responseMask, service, proto, port); -#endif - - - String instanceName = _instanceName; - size_t instanceNameLen = instanceName.length(); - - String hostName = _hostName; - size_t hostNameLen = hostName.length(); - - char underscore[] = "_"; - - // build service name with _ - char serviceName[os_strlen(service) + 2]; - os_strcpy(serviceName, underscore); - os_strcat(serviceName, service); - size_t serviceNameLen = os_strlen(serviceName); - - //build proto name with _ - char protoName[5]; - os_strcpy(protoName, underscore); - os_strcat(protoName, proto); - size_t protoNameLen = 4; - - //local string - char localName[] = "local"; - size_t localNameLen = 5; - - //terminator - char terminator[] = "\0"; - - uint8_t answerMask = responseMask & questionMask; - uint8_t answerCount = 0; - uint8_t additionalMask = responseMask & ~questionMask; - uint8_t additionalCount = 0; - for (i = 0; i < 4; i++) - { - if (answerMask & (1 << i)) - { - answerCount++; - } - if (additionalMask & (1 << i)) - { - additionalCount++; - } - } - - - //Write the header - _conn->flush(); - uint8_t head[12] = - { - 0x00, 0x00, //ID = 0 - 0x84, 0x00, //Flags = response + authoritative answer - 0x00, 0x00, //Question count - 0x00, answerCount, //Answer count - 0x00, 0x00, //Name server records - 0x00, additionalCount, //Additional records - }; - _conn->append(reinterpret_cast<const char*>(head), 12); - - for (int responseSection = 0; responseSection < 2; ++responseSection) - { - - // PTR Response - if ((responseSection == 0 ? answerMask : additionalMask) & 0x8) - { - // Send the Name field (ie. "_http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type, class, ttl and rdata length - uint8_t ptrDataLen = instanceNameLen + serviceNameLen + protoNameLen + localNameLen + 5; // 5 is four label sizes and the terminator - uint8_t ptrAttrs[10] = - { - 0x00, 0x0c, //PTR record query - 0x00, 0x01, //Class IN - 0x00, 0x00, 0x00, 0x78, //TTL 120 - 0x00, ptrDataLen, //RData length - }; - _conn->append(reinterpret_cast<const char*>(ptrAttrs), 10); - - //Send the RData (ie. "My IOT device._http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // length of "My IOT device" - _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - } - - //TXT Responce - if ((responseSection == 0 ? answerMask : additionalMask) & 0x4) - { - //Send the name field (ie. "My IOT device._http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // length of "My IOT device" - _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type, class, ttl and rdata length - uint8_t txtDataLen = _getServiceTxtLen(service, proto); - uint8_t txtAttrs[10] = - { - 0x00, 0x10, //TXT record query - 0x80, 0x01, //Class IN, with cache flush - 0x00, 0x00, 0x11, 0x94, //TTL 4500 - 0x00, txtDataLen, //RData length - }; - _conn->append(reinterpret_cast<const char*>(txtAttrs), 10); - - //Send the RData - MDNSTxt * txtPtr = _getServiceTxt(service, proto); - while (txtPtr != 0) - { - uint8_t txtLen = txtPtr->_txt.length(); - _conn->append(reinterpret_cast<const char*>(&txtLen), 1); // length of txt - _conn->append(reinterpret_cast<const char*>(txtPtr->_txt.c_str()), txtLen);// the txt - txtPtr = txtPtr->_next; - } - } - - - //SRV Responce - if ((responseSection == 0 ? answerMask : additionalMask) & 0x2) - { - //Send the name field (ie. "My IOT device._http._tcp.local") - _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // length of "My IOT device" - _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" - _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // length of "_http" - _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" - _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // length of "_tcp" - _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - //Send the type, class, ttl, rdata length, priority and weight - uint8_t srvDataSize = hostNameLen + localNameLen + 3; // 3 is 2 lable size bytes and the terminator - srvDataSize += 6; // Size of Priority, weight and port - uint8_t srvAttrs[10] = - { - 0x00, 0x21, //Type SRV - 0x80, 0x01, //Class IN, with cache flush - 0x00, 0x00, 0x00, 0x78, //TTL 120 - 0x00, srvDataSize, //RData length - }; - _conn->append(reinterpret_cast<const char*>(srvAttrs), 10); - - //Send the RData Priority weight and port - uint8_t srvRData[6] = - { - 0x00, 0x00, //Priority 0 - 0x00, 0x00, //Weight 0 - (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF) - }; - _conn->append(reinterpret_cast<const char*>(srvRData), 6); - //Send the RData (ie. "esp8266.local") - _conn->append(reinterpret_cast<const char*>(&hostNameLen), 1); // length of "esp8266" - _conn->append(reinterpret_cast<const char*>(hostName.c_str()), hostNameLen);// "esp8266" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - } - - // A Response - if ((responseSection == 0 ? answerMask : additionalMask) & 0x1) - { - //Send the RData (ie. "esp8266.local") - _conn->append(reinterpret_cast<const char*>(&hostNameLen), 1); // length of "esp8266" - _conn->append(reinterpret_cast<const char*>(hostName.c_str()), hostNameLen);// "esp8266" - _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // length "local" - _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" - _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator - - uint8_t aaaAttrs[10] = - { - 0x00, 0x01, //TYPE A - 0x80, 0x01, //Class IN, with cache flush - 0x00, 0x00, 0x00, 0x78, //TTL 120 - 0x00, 0x04, //DATA LEN - }; - _conn->append(reinterpret_cast<const char*>(aaaAttrs), 10); - - // Send RData - uint32_t ip = multicastInterface; - uint8_t aaaRData[4] = - { - (uint8_t)(ip & 0xFF), //IP first octet - (uint8_t)((ip >> 8) & 0xFF), //IP second octet - (uint8_t)((ip >> 16) & 0xFF), //IP third octet - (uint8_t)((ip >> 24) & 0xFF) //IP fourth octet - }; - _conn->append(reinterpret_cast<const char*>(aaaRData), 4); - } - } - - _conn->setMulticastInterface(multicastInterface); - _conn->send(); -} - -#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) -MDNSResponder MDNS; -#endif - -} // namespace Legacy_MDNSResponder - - - - diff --git a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h b/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h deleted file mode 100644 index 70bfd58e23..0000000000 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - ESP8266 Multicast DNS (port of CC3000 Multicast DNS library) - Version 1.1 - Copyright (c) 2013 Tony DiCola (tony@tonydicola.com) - ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com) - Extended MDNS-SD support 2016 Lars Englund (lars.englund@gmail.com) - - This is a simple implementation of multicast DNS query support for an Arduino - running on ESP8266 chip. Only support for resolving address queries is currently - implemented. - - Requirements: - - ESP8266WiFi library - - Usage: - - Include the ESP8266 Multicast DNS library in the sketch. - - Call the begin method in the sketch's setup and provide a domain name (without - the '.local' suffix, i.e. just provide 'foo' to resolve 'foo.local'), and the - Adafruit CC3000 class instance. Optionally provide a time to live (in seconds) - for the DNS record--the default is 1 hour. - - Call the update method in each iteration of the sketch's loop function. - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ -#ifndef ESP8266MDNS_LEGACY_H -#define ESP8266MDNS_LEGACY_H - -#include "LEAmDNS2Host.h" -#include "WiFiUdp.h" - -//this should be defined at build time -#ifndef ARDUINO_BOARD -#define ARDUINO_BOARD "generic" -#endif - -class UdpContext; - - -namespace Legacy_MDNSResponder -{ - - -struct MDNSService; -struct MDNSTxt; -struct MDNSAnswer; - -class MDNSResponder -{ -public: - - MDNSResponder(); - ~MDNSResponder(); - bool begin(const char* hostName); - bool begin(const String& hostName) - { - return begin(hostName.c_str()); - } - //for compatibility - bool begin(const char* hostName, IPAddress ip, uint32_t ttl = 120) - { - (void) ip; - (void) ttl; - return begin(hostName); - } - bool begin(const String& hostName, IPAddress ip, uint32_t ttl = 120) - { - return begin(hostName.c_str(), ip, ttl); - } - /* Application should call this whenever AP is configured/disabled */ - void notifyAPChange(); - void update(); - - void addService(char *service, char *proto, uint16_t port); - void addService(const char *service, const char *proto, uint16_t port) - { - addService((char *)service, (char *)proto, port); - } - void addService(const String& service, const String& proto, uint16_t port) - { - addService(service.c_str(), proto.c_str(), port); - } - - bool addServiceTxt(char *name, char *proto, char * key, char * value); - bool addServiceTxt(const char *name, const char *proto, const char *key, const char * value) - { - return addServiceTxt((char *)name, (char *)proto, (char *)key, (char *)value); - } - bool addServiceTxt(const String& name, const String& proto, const String& key, const String& value) - { - return addServiceTxt(name.c_str(), proto.c_str(), key.c_str(), value.c_str()); - } - - int queryService(char *service, char *proto); - int queryService(const char *service, const char *proto) - { - return queryService((char *)service, (char *)proto); - } - int queryService(const String& service, const String& proto) - { - return queryService(service.c_str(), proto.c_str()); - } - String hostname(int idx); - IPAddress IP(int idx); - uint16_t port(int idx); - - void enableArduino(uint16_t port, bool auth = false); - - void setInstanceName(String name); - void setInstanceName(const char * name) - { - setInstanceName(String(name)); - } - void setInstanceName(char * name) - { - setInstanceName(String(name)); - } - -private: - struct MDNSService * _services; - UdpContext* _conn; - String _hostName; - String _instanceName; - struct MDNSAnswer * _answers; - struct MDNSQuery * _query; - bool _newQuery; - bool _waitingForAnswers; - WiFiEventHandler _disconnectedHandler; - WiFiEventHandler _gotIPHandler; - - - uint16_t _getServicePort(char *service, char *proto); - MDNSTxt * _getServiceTxt(char *name, char *proto); - uint16_t _getServiceTxtLen(char *name, char *proto); - IPAddress _getRequestMulticastInterface(); - void _parsePacket(); - void _replyToTypeEnumRequest(IPAddress multicastInterface); - void _replyToInstanceRequest(uint8_t questionMask, uint8_t responseMask, char * service, char *proto, uint16_t port, IPAddress multicastInterface); - MDNSAnswer* _getAnswerFromIdx(int idx); - int _getNumAnswers(); - bool _listen(); - void _restart(); -}; - -} // namespace Legacy_MDNSResponder - -#endif //ESP8266MDNS_H - - - diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp deleted file mode 100644 index 2bfc4f1ab2..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.cpp +++ /dev/null @@ -1,1531 +0,0 @@ -/* - LEAmDNS2_Legacy.cpp - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#include "ESP8266mDNS.h" -#include "LEAmDNS2_Legacy.h" - - -namespace experimental // esp8266 -{ - -/** - LEAmDNS -*/ -namespace MDNSImplementation -{ - -/** - STRINGIZE -*/ -#ifndef STRINGIZE -#define STRINGIZE(x) #x -#endif -#ifndef STRINGIZE_VALUE_OF -#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) -#endif - - -/* - clsLEAMDNSHost_Legacy::clsLEAMDNSHost_Legacy constructor - -*/ -clsLEAMDNSHost_Legacy::clsLEAMDNSHost_Legacy(void) -{ -} - -/* - clsLEAMDNSHost_Legacy::clsLEAMDNSHost_Legacy destructor - -*/ -clsLEAMDNSHost_Legacy::~clsLEAMDNSHost_Legacy(void) -{ -} - -/* - - HOST SETUP - -*/ - -/* - clsLEAMDNSHost_Legacy::begin - -*/ -bool clsLEAMDNSHost_Legacy::begin(const char* p_pcHostname) -{ - return addHostForNetIf(p_pcHostname) - && (0 != m_HostInformations.size()); -} - - -/* - clsLEAMDNSHost_Legacy::begin (String) - -*/ -bool clsLEAMDNSHost_Legacy::begin(const String& p_strHostname) -{ - return begin(p_strHostname.c_str()); -} - -/* - clsLEAMDNSHost_Legacy::begin (Ignored Options) - -*/ -bool clsLEAMDNSHost_Legacy::begin(const char* p_pcHostname, - IPAddress /*p_IPAddress = INADDR_ANY*/, // ignored - uint32_t /*p_u32TTL = 120*/) // ignored -{ - return begin(p_pcHostname); -} - -/* - clsLEAMDNSHost_Legacy::begin (String & Ignored Options) - -*/ -bool clsLEAMDNSHost_Legacy::begin(const String& p_strHostname, - IPAddress /*p_IPAddress = INADDR_ANY*/, // ignored - uint32_t /*p_u32TTL = 120*/) // ignored -{ - return begin(p_strHostname.c_str()); -} - -/* - clsLEAMDNSHost_Legacy::close - -*/ -bool clsLEAMDNSHost_Legacy::close(void) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - if ((bResult = it->m_pHost->close())) - { - delete it->m_pHost; - it->m_pHost = 0; - } - } - return ((bResult) - && (m_HostInformations.clear(), true)); -} - -/* - clsLEAMDNSHost_Legacy::end - -*/ -bool clsLEAMDNSHost_Legacy::end(void) -{ - return close(); -} - -/* - clsLEAMDNSHost_Legacy::addHostForNetIf - - NEW! - -*/ -bool clsLEAMDNSHost_Legacy::addHostForNetIf(const char* p_pcHostname) -{ - bool bResult = true; - - if (m_HostInformations.size() > 0) - { - //XXXFIXME only one pHost instance, many things can be simplified - bResult = false; - } - else - { - clsLEAMDNSHost* pHost = new esp8266::experimental::clsLEAMDNSHost; - if (pHost - && (!((pHost->begin(p_pcHostname /*, default callback*/)) - && (m_HostInformations.push_back(stcHostInformation(pHost)), true)))) - { - bResult = false; - } - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::setHostname - -*/ -bool clsLEAMDNSHost_Legacy::setHostname(const char* p_pcHostname) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = it->m_pHost->setHostName(p_pcHostname); - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::setHostname - -*/ -bool clsLEAMDNSHost_Legacy::setHostname(String p_strHostname) -{ - return setHostname(p_strHostname.c_str()); -} - -/* - clsLEAMDNSHost_Legacy::hostname - -*/ -const char* clsLEAMDNSHost_Legacy::hostname(void) const -{ - return (m_HostInformations.empty() - ? 0 - : m_HostInformations.front().m_pHost->hostName()); -} - -/* - clsLEAMDNSHost_Legacy::status - -*/ -bool clsLEAMDNSHost_Legacy::status(void) const -{ - bool bStatus = true; - - for (const stcHostInformation& hostInformation : m_HostInformations) - { - if (!((bStatus = hostInformation.m_pHost->probeStatus()))) - { - break; - } - } - return bStatus; -} - - -/* - - SERVICE MANAGEMENT - -*/ - -/* - clsLEAMDNSHost_Legacy::addService - -*/ -clsLEAMDNSHost_Legacy::hMDNSService clsLEAMDNSHost_Legacy::addService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port) -{ - hMDNSService hResult = 0; - - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsService* pService = hostInformation.m_pHost->addService(p_pcName, p_pcService, p_pcProtocol, p_u16Port /*, default callback*/); - if (pService) - { - if (!hResult) - { - // Store first service handle as result and key - hResult = (hMDNSService)pService; - } - hostInformation.m_HandleToPtr[hResult] = pService; - } - } - return hResult; -} - -/* - clsLEAMDNSHost_Legacy::addService (String) - -*/ -bool clsLEAMDNSHost_Legacy::addService(String p_strServiceName, - String p_strProtocol, - uint16_t p_u16Port) -{ - return (0 != addService(0, p_strServiceName.c_str(), p_strProtocol.c_str(), p_u16Port)); -} - -/* - clsLEAMDNSHost_Legacy::removeService (hService) - -*/ -bool clsLEAMDNSHost_Legacy::removeService(const hMDNSService p_hService) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)it->m_HandleToPtr[p_hService]; - if ((bResult = ((pService) - && (it->m_pHost->removeService(pService))))) - { - it->m_HandleToPtr.erase(p_hService); - } - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::removeService (name) - -*/ -bool clsLEAMDNSHost_Legacy::removeService(const char* p_pcInstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol) -{ - hMDNSService hService = 0; - return (((hService = (m_HostInformations.empty() - ? 0 - : (hMDNSService)m_HostInformations.front().m_pHost->findService(p_pcInstanceName, p_pcServiceName, p_pcProtocol)))) - && (removeService(hService))); -} - -/* - clsLEAMDNSHost_Legacy::setServiceName - -*/ -bool clsLEAMDNSHost_Legacy::setServiceName(const hMDNSService p_hService, - const char* p_pcInstanceName) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)it->m_HandleToPtr[p_hService]; - bResult = ((pService) - && (pService->setInstanceName(p_pcInstanceName))); - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::setInstanceName - -*/ -void clsLEAMDNSHost_Legacy::setInstanceName(const char* p_pcInstanceName) -{ - for (stcHostInformation& hostInformation : m_HostInformations) - { - hostInformation.m_pHost->setDefaultInstanceName(p_pcInstanceName); - } -} - -/* - clsLEAMDNSHost_Legacy::setInstanceName (String) - -*/ -void clsLEAMDNSHost_Legacy::setInstanceName(const String& p_strHostname) -{ - setInstanceName(p_strHostname.c_str()); -} - -/* - clsLEAMDNSHost_Legacy::serviceName - -*/ -const char* clsLEAMDNSHost_Legacy::serviceName(const hMDNSService p_hService) const -{ - const clsLEAMDNSHost::clsService* pService = 0; - return (m_HostInformations.empty() - ? 0 - : (((pService = (const clsLEAMDNSHost::clsService*)(m_HostInformations.front().m_HandleToPtr.at(p_hService)))) - ? pService->instanceName() - : 0)); -} - -/* - clsLEAMDNSHost_Legacy::service - -*/ -const char* clsLEAMDNSHost_Legacy::service(const hMDNSService p_hService) const -{ - const clsLEAMDNSHost::clsService* pService = 0; - return (m_HostInformations.empty() - ? 0 - : (((pService = (const clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr.at(p_hService))) - ? pService->type() - : 0)); -} - -/* - clsLEAMDNSHost_Legacy::serviceProtocol - -*/ -const char* clsLEAMDNSHost_Legacy::serviceProtocol(const hMDNSService p_hService) const -{ - const clsLEAMDNSHost::clsService* pService = 0; - return (m_HostInformations.empty() - ? 0 - : (((pService = (const clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr.at(p_hService))) - ? pService->protocol() - : 0)); -} - -/* - clsLEAMDNSHost_Legacy::serviceStatus - -*/ -bool clsLEAMDNSHost_Legacy::serviceStatus(const hMDNSService p_hService) const -{ - const clsLEAMDNSHost::clsService* pService = 0; - return (m_HostInformations.empty() - ? false - : (((pService = (const clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr.at(p_hService))) - ? pService->probeStatus() - : false)); -} - - -/* - - SERVICE TXT MANAGEMENT - -*/ - -/* - clsLEAMDNSHost_Legacy::addServiceTxt (char*) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue) -{ - return _addServiceTxt(p_hService, p_pcKey, p_pcValue, false); -} - -/* - clsLEAMDNSHost_Legacy::addServiceTxt (uint32_t) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_u32Value, false); -} - -/* - clsLEAMDNSHost_Legacy::addServiceTxt (uint16_t) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_u16Value, false); -} - -/* - clsLEAMDNSHost_Legacy::addServiceTxt (uint8_t) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_u8Value, false); -} - -/* - clsLEAMDNSHost_Legacy::addServiceTxt (int32_t) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_i32Value, false); -} - -/* - clsLEAMDNSHost_Legacy::addServiceTxt (int16_t) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_i16Value, false); -} - -/* - clsLEAMDNSHost_Legacy::addServiceTxt (int8_t) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_i8Value, false); -} - -/* - clsLEAMDNSHost_Legacy::addServiceTxt (legacy) - -*/ -bool clsLEAMDNSHost_Legacy::addServiceTxt(const char* p_pcService, - const char* p_pcProtocol, - const char* p_pcKey, - const char* p_pcValue) -{ - hMDNSService hService = 0; - return (((hService = (m_HostInformations.empty() - ? 0 - : (hMDNSService)m_HostInformations.front().m_pHost->findService(0, p_pcService, p_pcProtocol)))) - && (_addServiceTxt(hService, p_pcKey, p_pcValue, false))); -} - -/* - clsLEAMDNSHost_Legacy::addServiceTxt (legacy, String) - -*/ -bool clsLEAMDNSHost_Legacy::addServiceTxt(String p_strService, - String p_strProtocol, - String p_strKey, - String p_strValue) -{ - return addServiceTxt(p_strService.c_str(), p_strProtocol.c_str(), p_strKey.c_str(), p_strValue.c_str()); -} - -/* - clsLEAMDNSHost_Legacy::removeServiceTxt (hTxt) - -*/ -bool clsLEAMDNSHost_Legacy::removeServiceTxt(const hMDNSService p_hService, - const hMDNSTxt p_hTxt) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)it->m_HandleToPtr[p_hService]; - clsLEAMDNSHost::clsServiceTxt* pTxt = (clsLEAMDNSHost::clsServiceTxt*)it->m_HandleToPtr[p_hTxt]; - if ((bResult = ((pService) - && (pTxt) - && (pService->removeServiceTxt(pTxt))))) - { - it->m_HandleToPtr.erase(p_hTxt); - } - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::removeServiceTxt (char*) - -*/ -bool clsLEAMDNSHost_Legacy::removeServiceTxt(const hMDNSService p_hService, - const char* p_pcKey) -{ - clsLEAMDNSHost::clsService* pService = 0; - clsLEAMDNSHost::clsServiceTxt* pTxt = 0; - return (((pService = (m_HostInformations.empty() - ? 0 - : (clsLEAMDNSHost::clsService*)m_HostInformations.front().m_HandleToPtr[p_hService]))) - && ((pTxt = pService->findServiceTxt(p_pcKey))) - && (removeServiceTxt(p_hService, (hMDNSTxt)pTxt))); -} - -/* - clsLEAMDNSHost_Legacy::removeServiceTxt (char*) - -*/ -bool clsLEAMDNSHost_Legacy::removeServiceTxt(const char* p_pcInstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol, - const char* p_pcKey) -{ - hMDNSService hService = 0; - return (((hService = (m_HostInformations.empty() - ? 0 - : (hMDNSService)m_HostInformations.front().m_pHost->findService(p_pcInstanceName, p_pcServiceName, p_pcProtocol)))) - && (removeServiceTxt(hService, p_pcKey))); -} - -/* - clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback (global) - -*/ -bool clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFn p_fnCallback) -{ - bool bResult = true; - - if ((bResult = m_HostInformations.empty())) - { - // The service handles of the first host are the keys in the HostInformations.HandleToPtr map - for (const clsLEAMDNSHost::clsService* pService : m_HostInformations.front().m_pHost->services()) - { - if (!((bResult = setDynamicServiceTxtCallback((hMDNSService)pService, p_fnCallback)))) - { - break; - } - } - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback (service) - -*/ -bool clsLEAMDNSHost_Legacy::setDynamicServiceTxtCallback(const hMDNSService p_hService, - MDNSDynamicServiceTxtCallbackFn p_fnCallback) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - clsLEAMDNSHost::clsService* pService = (clsLEAMDNSHost::clsService*)it->m_HandleToPtr[p_hService]; - bResult = pService->setDynamicServiceTxtCallback([p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/)->void - { - if (p_fnCallback) // void(const hMDNSService p_hService) - { - p_fnCallback(p_hService); - } - }); - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::addDynamicServiceTxt (char*) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue) -{ - return _addServiceTxt(p_hService, p_pcKey, p_pcValue, true); -} - -/* - clsLEAMDNSHost_Legacy::addDynamicServiceTxt (uint32) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_u32Value, true); -} - -/* - clsLEAMDNSHost_Legacy::addDynamicServiceTxt (uint16) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_u16Value, true); -} - -/* - clsLEAMDNSHost_Legacy::addDynamicServiceTxt (uint8) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_u8Value, true); -} - -/* - clsLEAMDNSHost_Legacy::addDynamicServiceTxt (int32) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_i32Value, true); -} - -/* - clsLEAMDNSHost_Legacy::addDynamicServiceTxt (int16) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_i16Value, true); -} - -/* - clsLEAMDNSHost_Legacy::addDynamicServiceTxt (int8) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value) -{ - return _addServiceTxt(p_hService, p_pcKey, p_i8Value, true); -} - - -/* - - STATIC QUERY - -*/ - -/* - clsLEAMDNSHost_Legacy::queryService - - This will take p_u16Timeout millisec for every host! - -*/ -uint32_t clsLEAMDNSHost_Legacy::queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout /*= MDNS_QUERYSERVICES_WAIT_TIME*/) -{ - uint32_t u32Answers = 0; - - for (stcHostInformation& hostInformation : m_HostInformations) - { - u32Answers += (hostInformation.m_pHost->queryService(p_pcService, p_pcProtocol, p_u16Timeout)).size(); - } - return u32Answers; -} - -/* - clsLEAMDNSHost_Legacy::removeQuery - -*/ -bool clsLEAMDNSHost_Legacy::removeQuery(void) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = it->m_pHost->removeQuery(); - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::queryService - -*/ -uint32_t clsLEAMDNSHost_Legacy::queryService(String p_strService, - String p_strProtocol) -{ - return queryService(p_strService.c_str(), p_strProtocol.c_str()); -} - -/* - clsLEAMDNSHost_Legacy::answerHostname - -*/ -const char* clsLEAMDNSHost_Legacy::answerHostname(const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_u32AnswerIndex); - return (answerAccessor.serviceDomainAvailable() - ? answerAccessor.serviceDomain() - : 0); -} - -/* - clsLEAMDNSHost_Legacy::answerIP - -*/ -IPAddress clsLEAMDNSHost_Legacy::answerIP(const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_u32AnswerIndex); - return (answerAccessor.IPv4AddressAvailable() - ? answerAccessor.IPv4Addresses()[0] - : IPAddress()); -} - -/* - clsLEAMDNSHost_Legacy::answerPort - -*/ -uint16_t clsLEAMDNSHost_Legacy::answerPort(const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_u32AnswerIndex); - return (answerAccessor.hostPortAvailable() - ? answerAccessor.hostPort() - : 0); -} - -/* - clsLEAMDNSHost_Legacy::hostname - -*/ -String clsLEAMDNSHost_Legacy::hostname(const uint32_t p_u32AnswerIndex) -{ - return String(answerHostname(p_u32AnswerIndex)); -} - -/* - clsLEAMDNSHost_Legacy::IP - -*/ -IPAddress clsLEAMDNSHost_Legacy::IP(const uint32_t p_u32AnswerIndex) -{ - return answerIP(p_u32AnswerIndex); -} - -/* - clsLEAMDNSHost_Legacy::port - -*/ -uint16_t clsLEAMDNSHost_Legacy::port(const uint32_t p_u32AnswerIndex) -{ - return answerPort(p_u32AnswerIndex); -} - - -/* - - DYNAMIC QUERY - -*/ - -/* - clsLEAMDNSHost_Legacy::installServiceQuery - -*/ -clsLEAMDNSHost_Legacy::hMDNSServiceQuery clsLEAMDNSHost_Legacy::installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - MDNSServiceQueryCallbackFn p_fnCallback) -{ - hMDNSServiceQuery hResult = 0; - - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsQuery* pQuery = hostInformation.m_pHost->installServiceQuery(p_pcService, p_pcProtocol, [this, p_fnCallback](const clsLEAMDNSHost::clsQuery& /*p_Query*/, - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor & p_AnswerAccessor, - clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags, // flags for the updated answer item - bool p_bSetContent)->void - { - if (p_fnCallback) // void(const stcMDNSServiceInfo& p_MDNSServiceInfo, MDNSResponder::AnswerType p_AnswerType, bool p_bSetContent) - { - p_fnCallback(stcMDNSServiceInfo(p_AnswerAccessor), _answerFlagsToAnswerType(p_QueryAnswerTypeFlags), p_bSetContent); - } - }); - if (pQuery) - { - if (!hResult) - { - // Store first query as result and key - hResult = (hMDNSServiceQuery)pQuery; - } - hostInformation.m_HandleToPtr[hResult] = pQuery; - } - } - return hResult; -} - -/* - clsLEAMDNSHost_Legacy::removeServiceQuery - -*/ -bool clsLEAMDNSHost_Legacy::removeServiceQuery(clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - if ((bResult = it->m_pHost->removeQuery((clsLEAMDNSHost::clsQuery*)it->m_HandleToPtr[p_hServiceQuery]))) - { - it->m_HandleToPtr.erase(p_hServiceQuery); - } - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::answerCount - -*/ -uint32_t clsLEAMDNSHost_Legacy::answerCount(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery) -{ - uint32_t u32AnswerCount = 0; - - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; - if (pQuery) - { - u32AnswerCount += pQuery->answerCount(); - } - else - { - u32AnswerCount = 0; - break; - } - } - return u32AnswerCount; -} - -/* - clsLEAMDNSHost_Legacy::answerInfo - -*/ -std::vector<clsLEAMDNSHost_Legacy::stcMDNSServiceInfo> clsLEAMDNSHost_Legacy::answerInfo(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery) -{ - std::vector<stcMDNSServiceInfo> serviceInfos; - - if (p_hServiceQuery) - { - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; - if (pQuery) - { - for (clsLEAMDNSHost::clsQuery::clsAnswerAccessor& answerAccessor : pQuery->answerAccessors()) - { - serviceInfos.push_back(stcMDNSServiceInfo(answerAccessor)); - } - } - else - { - serviceInfos.clear(); - break; - } - } - } - return serviceInfos; -} - -/* - clsLEAMDNSHost_Legacy::answerServiceDomain - -*/ -const char* clsLEAMDNSHost_Legacy::answerServiceDomain(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.serviceDomainAvailable() - ? answerAccessor.serviceDomain() - : 0); -} - -/* - clsLEAMDNSHost_Legacy::hasAnswerHostDomain - -*/ -bool clsLEAMDNSHost_Legacy::hasAnswerHostDomain(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).hostDomainAvailable(); -} - -/* - clsLEAMDNSHost_Legacy::answerHostDomain - -*/ -const char* clsLEAMDNSHost_Legacy::answerHostDomain(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.hostDomainAvailable() - ? answerAccessor.hostDomain() - : 0); -} - -#ifdef MDNS_IP4_SUPPORT -/* - clsLEAMDNSHost_Legacy::hasAnswerIP4Address - -*/ -bool clsLEAMDNSHost_Legacy::hasAnswerIP4Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).IPv4AddressAvailable(); -} - -/* - clsLEAMDNSHost_Legacy::answerIP4AddressCount - -*/ -uint32_t clsLEAMDNSHost_Legacy::answerIP4AddressCount(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.IPv4AddressAvailable() - ? answerAccessor.IPv4Addresses().size() - : 0); -} - -/* - clsLEAMDNSHost_Legacy::answerIP4Address - -*/ -IPAddress clsLEAMDNSHost_Legacy::answerIP4Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.IPv4AddressAvailable() - ? answerAccessor.IPv4Addresses()[p_u32AddressIndex] - : IPAddress()); -} -#endif -#ifdef MDNS_IP6_SUPPORT -/* - clsLEAMDNSHost_Legacy::hasAnswerIP6Address - -*/ -bool clsLEAMDNSHost_Legacy::hasAnswerIP6Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).IPv6AddressAvailable(); -} - -/* - clsLEAMDNSHost_Legacy::answerIP6AddressCount - -*/ -uint32_t clsLEAMDNSHost_Legacy::answerIP6AddressCount(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.IPv6AddressAvailable() - ? answerAccessor.IPv6Addresses().size() - : 0); -} - -/* - clsLEAMDNSHost_Legacy::answerIP6Address - -*/ -IPAddress clsLEAMDNSHost_Legacy::answerIP6Address(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.IPv6AddressAvailable() - ? answerAccessor.IPv6Addresses()[p_u32AddressIndex] - : IPAddress()); -} -#endif - -/* - clsLEAMDNSHost_Legacy::hasAnswerPort - -*/ -bool clsLEAMDNSHost_Legacy::hasAnswerPort(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).hostPortAvailable(); -} - -/* - clsLEAMDNSHost_Legacy::answerPort - -*/ -uint16_t clsLEAMDNSHost_Legacy::answerPort(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.hostPortAvailable() - ? answerAccessor.hostPort() - : 0); -} - -/* - clsLEAMDNSHost_Legacy::hasAnswerTxts - -*/ -bool clsLEAMDNSHost_Legacy::hasAnswerTxts(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - return _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex).txtsAvailable(); -} - -/* - clsLEAMDNSHost_Legacy::answerHostDomain - - Get the TXT items as a ';'-separated string -*/ -const char* clsLEAMDNSHost_Legacy::answerTxts(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor answerAccessor = _getAnswerAccessor(p_hServiceQuery, p_u32AnswerIndex); - return (answerAccessor.txtsAvailable() - ? answerAccessor.txts() - : 0); -} - - -/* - - HOST/SERVICE PROBE CALLBACKS - -*/ - -/* - clsLEAMDNSHost_Legacy::setHostProbeResultCallback - -*/ -bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MDNSHostProbeResultCallbackFn p_fnCallback) -{ - bool bResult = true; - - clsLEAMDNSHost::stProbeResultCallback = - [p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, - const char* p_pcDomainName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void(const char* p_pcDomainName, bool p_bProbeResult) - { - p_fnCallback(p_pcDomainName, p_bProbeResult); - } - }; - - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = it->m_pHost->setProbeResultCallback(clsLEAMDNSHost::stProbeResultCallback); - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::setHostProbeResultCallback - -*/ -bool clsLEAMDNSHost_Legacy::setHostProbeResultCallback(clsLEAMDNSHost_Legacy::MDNSHostProbeResultCallbackFn2 p_fnCallback) -{ - bool bResult = true; - - clsLEAMDNSHost::stProbeResultCallback = - [this, p_fnCallback](clsLEAMDNSHost& /*p_rHost*/, - const char* p_pcDomainName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcDomainName, bool p_bProbeResult) - { - p_fnCallback(this, p_pcDomainName, p_bProbeResult); - } - }; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = it->m_pHost->setProbeResultCallback(clsLEAMDNSHost::stProbeResultCallback); - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::setServiceProbeResultCallback - -*/ -bool clsLEAMDNSHost_Legacy::setServiceProbeResultCallback(const clsLEAMDNSHost_Legacy::hMDNSService p_hService, - clsLEAMDNSHost_Legacy::MDNSServiceProbeResultCallbackFn p_fnCallback) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - clsLEAMDNSHost::clsService* pService = 0; - bResult = (((pService = (clsLEAMDNSHost::clsService*)it->m_HandleToPtr[p_hService])) - && (pService->setProbeResultCallback( - - [this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, - const char* p_pcInstanceName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void(const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) - { - p_fnCallback(p_pcInstanceName, p_hService, p_bProbeResult); - } - } - ))); - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::setServiceProbeResultCallback - -*/ -bool clsLEAMDNSHost_Legacy::setServiceProbeResultCallback(const clsLEAMDNSHost_Legacy::hMDNSService p_hService, - clsLEAMDNSHost_Legacy::MDNSServiceProbeResultCallbackFn2 p_fnCallback) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - clsLEAMDNSHost::clsService* pService = 0; - bResult = (((pService = (clsLEAMDNSHost::clsService*)it->m_HandleToPtr[p_hService])) - && (pService->setProbeResultCallback([this, p_hService, p_fnCallback](clsLEAMDNSHost::clsService& /*p_rMDNSService*/, - const char* p_pcInstanceName, - bool p_bProbeResult)->void - { - if (p_fnCallback) // void((clsLEAMDNSHost_Legacy* p_pMDNSResponder, const char* p_pcServiceName, const hMDNSService p_hMDNSService, bool p_bProbeResult) - { - p_fnCallback(this, p_pcInstanceName, p_hService, p_bProbeResult); - } - }))); - } - return bResult; -} - - -/* - - PROCESS - -*/ - -/* - clsLEAMDNSHost_Legacy::notifyAPChange - -*/ -bool clsLEAMDNSHost_Legacy::notifyAPChange(void) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = it->m_pHost->restart(); - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::update - -*/ -bool clsLEAMDNSHost_Legacy::update(void) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = it->m_pHost->update(); - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::announce - -*/ -bool clsLEAMDNSHost_Legacy::announce(void) -{ - bool bResult = true; - - for (stcHostInformation::list::iterator it = m_HostInformations.begin(); ((bResult) && (it != m_HostInformations.end())); ++it) - { - bResult = it->m_pHost->announce(true, true); - } - return bResult; -} - -/* - clsLEAMDNSHost_Legacy::enableArduino - -*/ -clsLEAMDNSHost_Legacy::hMDNSService clsLEAMDNSHost_Legacy::enableArduino(uint16_t p_u16Port, - bool p_bAuthUpload /*= false*/) -{ - hMDNSService hService = addService(0, "arduino", "tcp", p_u16Port); - if (hService) - { - if ((!addServiceTxt(hService, "tcp_check", "no")) - || (!addServiceTxt(hService, "ssh_upload", "no")) - || (!addServiceTxt(hService, "board", STRINGIZE_VALUE_OF(ARDUINO_BOARD))) - || (!addServiceTxt(hService, "auth_upload", (p_bAuthUpload) ? "yes" : "no"))) - { - removeService(hService); - hService = 0; - } - } - return hService; -} - -/* - clsLEAMDNSHost_Legacy::indexDomain - -*/ -bool clsLEAMDNSHost_Legacy::indexDomain(char*& p_rpcDomain, - const char* p_pcDivider /*= "-"*/, - const char* p_pcDefaultDomain /*= 0*/) -{ - bool bResult = false; - - const char* cpcDomainName = clsLEAMDNSHost::indexDomainName(p_rpcDomain, p_pcDivider, p_pcDefaultDomain); - delete[] p_rpcDomain; - p_rpcDomain = 0; - if ((cpcDomainName) - && ((p_rpcDomain = new char[strlen(cpcDomainName) + 1]))) - { - strcpy(p_rpcDomain, cpcDomainName); - bResult = true; - } - return bResult; -} - - -/* - - INTERNAL HELPERS - -*/ - -/* - clsLEAMDNSHost_Legacy::_addServiceTxt (char*) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bDynamic) -{ - hMDNSTxt hResult = 0; - - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsService* pService = 0; - clsLEAMDNSHost::clsServiceTxt* pTxt = 0; - if (((pService = (clsLEAMDNSHost::clsService*)hostInformation.m_HandleToPtr[p_hService])) - && ((pTxt = (p_bDynamic - ? pService->addDynamicServiceTxt(p_pcKey, p_pcValue) - : pService->addServiceTxt(p_pcKey, p_pcValue))))) - { - if (!hResult) - { - hResult = (hMDNSTxt)pTxt; - } - hostInformation.m_HandleToPtr[hResult] = pTxt; - } - } - return hResult; -} - -/* - clsLEAMDNSHost_Legacy::_addServiceTxt (uint32_t) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value, - bool p_bDynamic) -{ - char acValueBuffer[16]; // 32-bit max 10 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%u", p_u32Value); - - return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); -} - -/* - clsLEAMDNSHost_Legacy::_addServiceTxt (uint16_t) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value, - bool p_bDynamic) -{ - char acValueBuffer[8]; // 16-bit max 5 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%hu", p_u16Value); - - return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); -} - -/* - clsLEAMDNSHost_Legacy::_addServiceTxt (uint8_t) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value, - bool p_bDynamic) -{ - char acValueBuffer[8]; // 8-bit max 3 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%hhu", p_u8Value); - - return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); -} - -/* - clsLEAMDNSHost_Legacy::_addServiceTxt (int32_t) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value, - bool p_bDynamic) -{ - char acValueBuffer[16]; // 32-bit max 11 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%i", p_i32Value); - - return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); -} - -/* - clsLEAMDNSHost_Legacy::_addServiceTxt (int16_t) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value, - bool p_bDynamic) -{ - char acValueBuffer[8]; // 16-bit max 6 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%hi", p_i16Value); - - return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); -} - -/* - clsLEAMDNSHost_Legacy::_addServiceTxt (int8_t) - -*/ -clsLEAMDNSHost_Legacy::hMDNSTxt clsLEAMDNSHost_Legacy::_addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value, - bool p_bDynamic) -{ - char acValueBuffer[8]; // 8-bit max 4 digits - *acValueBuffer = 0; - sprintf(acValueBuffer, "%hhi", p_i8Value); - - return _addServiceTxt(p_hService, p_pcKey, acValueBuffer, p_bDynamic); -} - -/* - clsLEAMDNSHost_Legacy::_answerFlagsToAnswerType - -*/ -clsLEAMDNSHost_Legacy::AnswerType clsLEAMDNSHost_Legacy::_answerFlagsToAnswerType(clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags) const -{ - AnswerType answerType = AnswerType::Unknown; - - if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Unknown) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::Unknown; - } - else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::ServiceDomain; - } - else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomain) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::HostDomainAndPort; - } - else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Port) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::HostDomainAndPort; - } - else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::Txt; - } -#ifdef MDNS_IP4_SUPPORT - else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::IP4Address; - } -#endif -#ifdef MDNS_IP6_SUPPORT - else if (static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address) & p_QueryAnswerTypeFlags) - { - answerType = AnswerType::IP6Address; - } -#endif - return answerType; -} - -/* - clsLEAMDNSHost_Legacy::_getAnswerAccessor - -*/ -clsLEAMDNSHost_Legacy::clsLEAMDNSHost::clsQuery::clsAnswerAccessor clsLEAMDNSHost_Legacy::_getAnswerAccessor(const uint32_t p_u32AnswerIndex) -{ - uint32_t u32AnswerIndexWithoutOffset = p_u32AnswerIndex; - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsQuery* pQuery = hostInformation.m_pHost->getQuery(); - if (pQuery) - { - if (pQuery->answerCount() > u32AnswerIndexWithoutOffset) - { - return pQuery->answerAccessor(u32AnswerIndexWithoutOffset); - } - else - { - u32AnswerIndexWithoutOffset -= pQuery->answerCount(); - } - } - else - { - break; - } - } - return clsLEAMDNSHost::clsQuery::clsAnswerAccessor(0); -} - -/* - clsLEAMDNSHost_Legacy::_getAnswerAccessor - -*/ -clsLEAMDNSHost_Legacy::clsLEAMDNSHost::clsQuery::clsAnswerAccessor clsLEAMDNSHost_Legacy::_getAnswerAccessor(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex) -{ - uint32_t u32AnswerIndexWithoutOffset = p_u32AnswerIndex; - for (stcHostInformation& hostInformation : m_HostInformations) - { - clsLEAMDNSHost::clsQuery* pQuery = (clsLEAMDNSHost::clsQuery*)hostInformation.m_HandleToPtr[p_hServiceQuery]; - if (pQuery) - { - if (pQuery->answerCount() > u32AnswerIndexWithoutOffset) - { - return pQuery->answerAccessor(u32AnswerIndexWithoutOffset); - } - else - { - u32AnswerIndexWithoutOffset -= pQuery->answerCount(); - } - } - else - { - break; - } - } - return clsLEAMDNSHost::clsQuery::clsAnswerAccessor(0); -} - - -} // namespace MDNSImplementation - - -} // namespace experimental // esp8266 - - - - - - diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h deleted file mode 100644 index 33668e11d1..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Legacy.h +++ /dev/null @@ -1,700 +0,0 @@ -/* - LEAmDNS2_Legacy.h - (c) 2020, LaborEtArs - - Version 0.9 beta - - Some notes (from LaborEtArs, 2018): - Essentially, this is an rewrite of the original EPS8266 Multicast DNS code (ESP8266mDNS). - The target of this rewrite was to keep the existing interface as stable as possible while - adding and extending the supported set of mDNS features. - A lot of the additions were basically taken from Erik Ekman's lwIP mdns app code. - - Supported mDNS features (in some cases somewhat limited): - - Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service - - Support for multi-level compressed names in input; in output only a very simple one-level full-name compression is implemented - - Probing host and service domains for uniqueness in the local network - - Tiebreaking while probing is supported in a very minimalistic way (the 'higher' IP address wins the tiebreak) - - Announcing available services after successful probing - - Using fixed service TXT items or - - Using dynamic service TXT items for presented services (via callback) - - Remove services (and un-announcing them to the observers by sending goodbye-messages) - - Static queries for DNS-SD services (creating a fixed answer set after a certain timeout period) - - Dynamic queries for DNS-SD services with cached and updated answers and user notifications - - - Usage: - In most cases, this implementation should work as a 'drop-in' replacement for the original - ESP8266 Multicast DNS code. Adjustments to the existing code would only be needed, if some - of the new features should be used. - - For presenting services: - In 'setup()': - Install a callback for the probing of host (and service) domains via 'MDNS.setProbeResultCallback(probeResultCallback, &userData);' - Register DNS-SD services with 'clsLEAMDNSHost_Legacy::hMDNSService hService = MDNS.addService("MyESP", "http", "tcp", 5000);' - (Install additional callbacks for the probing of these service domains via 'MDNS.setServiceProbeResultCallback(hService, probeResultCallback, &userData);') - Add service TXT items with 'MDNS.addServiceTxt(hService, "c#", "1");' or by installing a service TXT callback - using 'MDNS.setDynamicServiceTxtCallback(dynamicServiceTxtCallback, &userData);' or service specific - 'MDNS.setDynamicServiceTxtCallback(hService, dynamicServiceTxtCallback, &userData);' - Call MDNS.begin("MyHostname"); - - In 'probeResultCallback(clsLEAMDNSHost_Legacy* p_MDNSResponder, const char* p_pcDomain, clsLEAMDNSHost_Legacy:hMDNSService p_hService, bool p_bProbeResult, void* p_pUserdata)': - Check the probe result and update the host or service domain name if the probe failed - - In 'dynamicServiceTxtCallback(clsLEAMDNSHost_Legacy* p_MDNSResponder, const hMDNSService p_hService, void* p_pUserdata)': - Add dynamic TXT items by calling 'MDNS.addDynamicServiceTxt(p_hService, "c#", "1");' - - In loop(): - Call 'MDNS.update();' - - - For querying services: - Static: - Call 'uint32_t u32AnswerCount = MDNS.queryService("http", "tcp");' - Iterate answers by: 'for (uint32_t u=0; u<u32AnswerCount; ++u) { const char* pHostname = MDNS.answerHostname(u); }' - You should call MDNS.removeQuery() sometimes later (when the answers are nott needed anymore) - - Dynamic: - Install a dynamic query by calling 'DNSResponder::hMDNSServiceQuery hServiceQuery = MDNS.installServiceQuery("http", "tcp", serviceQueryCallback, &userData);' - The callback 'serviceQueryCallback(clsLEAMDNSHost_Legacy* p_MDNSResponder, const hMDNSServiceQuery p_hServiceQuery, uint32_t p_u32AnswerIndex, - enuServiceQueryAnswerType p_ServiceQueryAnswerType, bool p_bSetContent, void* p_pUserdata)' - is called for any change in the answer set. - Call 'MDNS.removeServiceQuery(hServiceQuery);' when the answers are not needed anymore - - - Reference: - Used mDNS messages: - A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 - AAAA (0x1C): eg. esp8266.local AAAA OP TTL 1234:5678::90 - PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local - PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local - PTR (0x0C, IP4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local - PTR (0x0C, IP6): eg. 90.0.0.0.0.0.0.0.0.0.0.0.78.56.34.12.ip6.arpa PTR OP TTL esp8266.local - SRV (0x21): eg. MyESP._http._tcp.local SRV OP TTL PRIORITY WEIGHT PORT esp8266.local - TXT (0x10): eg. MyESP._http._tcp.local TXT OP TTL c#=1 - NSEC (0x2F): eg. esp8266.local ... (DNSSEC) - - Some NOT used message types: - OPT (0x29): eDNS - - - License (MIT license): - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -#ifndef __LEAMDNS2HOST_LEGACY_H__ -#define __LEAMDNS2HOST_LEGACY_H__ - -#include "LEAmDNS2Host.h" - - -namespace experimental -{ - -namespace MDNSImplementation -{ - -/** - clsLEAMDNSHost_Legacy -*/ -class clsLEAMDNSHost_Legacy -{ - using clsLEAMDNSHost = esp8266::experimental::clsLEAMDNSHost; - - /** - clsConsts - */ - class clsConsts - { - public: - static const uint16_t u16StaticQueryWaitTime = 1000; // Default wait time for query responses - }; - -public: - - /* INTERFACE */ - clsLEAMDNSHost_Legacy(void); - virtual ~clsLEAMDNSHost_Legacy(void); - - // Start the MDNS responder by setting the default hostname - // Later call MDNS::update() in every 'loop' to run the process loop - // (probing, announcing, responding, ...) - bool begin(const char* p_pcHostname); - bool begin(const String& p_strHostname); - // for compatibility - bool begin(const char* p_pcHostname, - IPAddress p_IPAddress /*= INADDR_ANY*/, // ignored - uint32_t p_u32TTL /*= 120*/); // ignored - bool begin(const String& p_strHostname, - IPAddress p_IPAddress /*= INADDR_ANY*/, // ignored - uint32_t p_u32TTL /*= 120*/); // ignored - // Finish MDNS processing - bool close(void); - // for ESP32 compatibility - bool end(void); - // NEW! The ESP-default network interfaces are 'auto-added' via 'begin' when active - // Additional netifs may be added, but if done so after calling 'update' for the - // first time, 'notifyAPChange' should be called to restart the probing/announcing process - bool addHostForNetIf(const char* p_pcHostname); - - // Change hostname (probing is restarted) - // Caution! The final hostname (after probing) may be different for every host - bool setHostname(const char* p_pcHostname); - // for compatibility... - bool setHostname(String p_strHostname); - - const char* hostname(void) const; - - bool status(void) const; - - /** - hMDNSService (opaque handle to access the service) - */ - using hMDNSService = const void*; - - // Add a new service to the MDNS responder. If no name (instance name) is given (p_pcName = 0) - // the current hostname is used. If the hostname is changed later, the instance names for - // these 'auto-named' services are changed to the new name also (and probing is restarted). - // The usual '_' before p_pcService (eg. http) and protocol (eg. tcp) may be given. - hMDNSService addService(const char* p_pcName, - const char* p_pcService, - const char* p_pcProtocol, - uint16_t p_u16Port); - // Removes a service from the MDNS responder - bool removeService(const hMDNSService p_hService); - bool removeService(const char* p_pcInstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol); - // for compatibility... - bool addService(String p_strServiceName, - String p_strProtocol, - uint16_t p_u16Port); - - - // Change the services instance name (and restart probing). - bool setServiceName(const hMDNSService p_hService, - const char* p_pcInstanceName); - //for compatibility - void setInstanceName(const char* p_pcHostname); - - // for ESP32 compatibility - void setInstanceName(const String& p_strHostname); - - const char* serviceName(const hMDNSService p_hService) const; - const char* service(const hMDNSService p_hService) const; - const char* serviceProtocol(const hMDNSService p_hService) const; - - bool serviceStatus(const hMDNSService p_hService) const; - - /** - hMDNSTxt (opaque handle to access the TXT items) - */ - using hMDNSTxt = void*; - - // 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); - - // Remove an existing (static) MDNS TXT item from the service - bool removeServiceTxt(const hMDNSService p_hService, - const hMDNSTxt p_hTxt); - bool removeServiceTxt(const hMDNSService p_hService, - const char* p_pcKey); - bool removeServiceTxt(const char* p_pcinstanceName, - const char* p_pcServiceName, - const char* p_pcProtocol, - const char* p_pcKey); - // for compatibility... - bool addServiceTxt(const char* p_pcService, - const char* p_pcProtocol, - const char* p_pcKey, - const char* p_pcValue); - bool addServiceTxt(String p_strService, - String p_strProtocol, - String p_strKey, - String p_strValue); - - /** - MDNSDynamicServiceTxtCallbackFn - Callback function for dynamic MDNS TXT items - */ - using MDNSDynamicServiceTxtCallbackFn = std::function<void(const hMDNSService p_hService)>; - - // Set a global callback for dynamic MDNS TXT items. The callback function is called - // every time, a TXT item is needed for one of the installed services. - bool setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallbackFn p_fnCallback); - - // Set a service specific callback for dynamic MDNS TXT items. The callback function - // is called every time, a TXT item is needed for the given service. - bool setDynamicServiceTxtCallback(const hMDNSService p_hService, - MDNSDynamicServiceTxtCallbackFn p_fnCallback); - - // Add a (dynamic) MDNS TXT item ('key' = 'value') to the service - // Dynamic TXT items are removed right after one-time use. So they need to be added - // every time the value s needed (via callback). - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value); - hMDNSTxt addDynamicServiceTxt(hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value); - - // Perform a (static) service query. The function returns after p_u16Timeout milliseconds - // The answers (the number of received answers is returned) can be retrieved by calling - // - answerHostname (or hostname) - // - answerIP (or IP) - // - answerPort (or port) - uint32_t queryService(const char* p_pcService, - const char* p_pcProtocol, - const uint16_t p_u16Timeout = clsConsts::u16StaticQueryWaitTime); - bool removeQuery(void); - // for compatibility... - uint32_t queryService(String p_strService, - String p_strProtocol); - - const char* answerHostname(const uint32_t p_u32AnswerIndex); - IPAddress answerIP(const uint32_t p_u32AnswerIndex); - uint16_t answerPort(const uint32_t p_u32AnswerIndex); - // for compatibility... - String hostname(const uint32_t p_u32AnswerIndex); - IPAddress IP(const uint32_t p_u32AnswerIndex); - uint16_t port(const uint32_t p_u32AnswerIndex); - - /** - hMDNSServiceQuery (opaque handle to access dynamic service queries) - */ - using hMDNSServiceQuery = const void*; - - /** - enuServiceQueryAnswerType - */ - using enuServiceQueryAnswerType = enum _enuServiceQueryAnswerType - { - ServiceQueryAnswerType_Unknown = 0, - ServiceQueryAnswerType_ServiceDomain = (1 << 0), // Service instance name - ServiceQueryAnswerType_HostDomainAndPort = (1 << 1), // Host domain and service port - ServiceQueryAnswerType_Txts = (1 << 2), // TXT items -#ifdef MDNS_IP4_SUPPORT - ServiceQueryAnswerType_IP4Address = (1 << 3), // IP4 address -#endif -#ifdef MDNS_IP6_SUPPORT - ServiceQueryAnswerType_IP6Address = (1 << 4), // IP6 address -#endif - }; - - /** - AnswerType (std::map compatible version) - */ - enum class AnswerType : uint32_t - { - Unknown = ServiceQueryAnswerType_Unknown, - ServiceDomain = ServiceQueryAnswerType_ServiceDomain, - HostDomainAndPort = ServiceQueryAnswerType_HostDomainAndPort, - Txt = ServiceQueryAnswerType_Txts, -#ifdef MDNS_IP4_SUPPORT - IP4Address = ServiceQueryAnswerType_IP4Address, -#endif -#ifdef MDNS_IP6_SUPPORT - IP6Address = ServiceQueryAnswerType_IP6Address -#endif - }; - - /** - stcMDNSServiceInfo - */ - struct stcMDNSServiceInfo - { - stcMDNSServiceInfo(const clsLEAMDNSHost::clsQuery::clsAnswerAccessor& p_rAnswerAccessor) - : m_rAnswerAccessor(p_rAnswerAccessor) {}; - /** - stcCompareKey - */ - struct stcCompareKey - { - /* - operator () - */ - bool operator()(char const* p_pA, char const* p_pB) const - { - return (0 > strcmp(p_pA, p_pB)); - } - }; - /** - clsKeyValueMap - */ - using clsKeyValueMap = std::map<const char*, const char*, stcCompareKey>; - - protected: - const clsLEAMDNSHost::clsQuery::clsAnswerAccessor& m_rAnswerAccessor; - clsKeyValueMap m_KeyValueMap; - - public: - /* - serviceDomain - */ - const char* serviceDomain(void) const - { - return (m_rAnswerAccessor.serviceDomainAvailable() - ? m_rAnswerAccessor.serviceDomain() - : nullptr); - } - /* - hostDomainAvailable - */ - bool hostDomainAvailable(void) const - { - return m_rAnswerAccessor.hostDomainAvailable(); - } - /* - hostDomain - */ - const char* hostDomain(void) const - { - return (hostDomainAvailable() - ? m_rAnswerAccessor.hostDomain() - : nullptr); - } - /* - hostPortAvailable - */ - bool hostPortAvailable(void) const - { - return m_rAnswerAccessor.hostPortAvailable(); - } - /* - hostPort - */ - uint16_t hostPort(void) const - { - return (hostPortAvailable() - ? m_rAnswerAccessor.hostPort() - : 0); - } -#ifdef MDNS_IP4_SUPPORT - /* - IP4AddressAvailable - */ - bool IP4AddressAvailable(void) const - { - return m_rAnswerAccessor.IPv4AddressAvailable(); - } - /* - IP4Addresses - */ - std::vector<IPAddress> IP4Adresses(void) const - { - return (IP4AddressAvailable() - ? m_rAnswerAccessor.IPv4Addresses() - : std::vector<IPAddress>()); - } -#endif -#ifdef MDNS_IP6_SUPPORT - /* - IP6AddressAvailable - */ - bool IP6AddressAvailable(void) const - { - return m_rAnswerAccessor.IPv6AddressAvailable(); - } - /* - IP6Addresses - */ - std::vector<IPAddress> IP6Adresses(void) const - { - return (IP6AddressAvailable() - ? m_rAnswerAccessor.IPv6Addresses() - : std::vector<IPAddress>()); - } -#endif - /* - txtAvailable - */ - bool txtAvailable(void) const - { - return m_rAnswerAccessor.txtsAvailable(); - } - /* - strKeyValue -> abc=def;hij=klm; - */ - const char* strKeyValue(void) const - { - // TODO - return nullptr; - } - /* - keyValues -> abc=def hij=klm ... - */ - const clsKeyValueMap& keyValues(void) - { - if ((txtAvailable()) && - (0 == m_KeyValueMap.size())) - { - for (auto kv : m_rAnswerAccessor.txtKeyValues()) - { - m_KeyValueMap.emplace(std::pair<const char*, const char*>(kv.first, kv.second)); - } - } - return m_KeyValueMap; - } - /* - value (abc)->def - */ - const char* value(const char* p_pcKey) const - { - return m_rAnswerAccessor.txtValue(p_pcKey); - } - }; - - /** - MDNSServiceQueryCallbackFn - - Callback function for received answers for dynamic service queries - */ - using MDNSServiceQueryCallbackFn = - std::function<void(const stcMDNSServiceInfo& p_MDNSServiceInfo, - AnswerType p_AnswerType, // flags for the updated answer item - bool p_bSetContent // true: Answer component set, false: component deleted - )>; - - // Install a dynamic service query. For every received answer (part) the given callback - // function is called. The query will be updated every time, the TTL for an answer - // has timed-out. - // The answers can also be retrieved by calling - // - answerCount - // - answerServiceDomain - // - hasAnswerHostDomain/answerHostDomain - // - hasAnswerIP4Address/answerIP4Address - // - hasAnswerIP6Address/answerIP6Address - // - hasAnswerPort/answerPort - // - hasAnswerTxts/answerTxts - hMDNSServiceQuery installServiceQuery(const char* p_pcService, - const char* p_pcProtocol, - MDNSServiceQueryCallbackFn p_fnCallback); - // Remove a dynamic service query - bool removeServiceQuery(hMDNSServiceQuery p_hServiceQuery); - - uint32_t answerCount(const hMDNSServiceQuery p_hServiceQuery); - std::vector<stcMDNSServiceInfo> answerInfo(const clsLEAMDNSHost_Legacy::hMDNSServiceQuery p_hServiceQuery); - const char* answerServiceDomain(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerHostDomain(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - const char* answerHostDomain(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); -#ifdef MDNS_IP4_SUPPORT - bool hasAnswerIP4Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIP4AddressCount(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIP4Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); -#endif -#ifdef MDNS_IP6_SUPPORT - bool hasAnswerIP6Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - uint32_t answerIP6AddressCount(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - IPAddress answerIP6Address(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex, - const uint32_t p_u32AddressIndex); -#endif - bool hasAnswerPort(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - uint16_t answerPort(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - bool hasAnswerTxts(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - // Get the TXT items as a ';'-separated string - const char* answerTxts(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - - /** - MDNSHostProbeResultCallbackFn/2 - Callback function for host domain probe results - */ - using MDNSHostProbeResultCallbackFn = - std::function<void(const char* p_pcDomainName, - bool p_bProbeResult)>; - - using MDNSHostProbeResultCallbackFn2 = - std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, - const char* p_pcDomainName, - bool p_bProbeResult)>; - - // Set a callback function for host probe results - // The callback function is called, when the probeing for the host domain - // succeededs or fails. - // In case of failure, the failed domain name should be changed. - bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn p_fnCallback); - bool setHostProbeResultCallback(MDNSHostProbeResultCallbackFn2 p_fnCallback); - - /** - MDNSServiceProbeResultCallbackFn/2 - Callback function for service domain probe results - */ - using MDNSServiceProbeResultCallbackFn = - std::function<void(const char* p_pcServiceName, - const hMDNSService p_hMDNSService, - bool p_bProbeResult)>; - - using MDNSServiceProbeResultCallbackFn2 = - std::function<void(clsLEAMDNSHost_Legacy* p_pMDNSResponder, - const char* p_pcServiceName, - const hMDNSService p_hMDNSService, - bool p_bProbeResult)>; - - // Set a service specific probe result callcack - bool setServiceProbeResultCallback(const hMDNSService p_hService, - MDNSServiceProbeResultCallbackFn p_fnCallback); - bool setServiceProbeResultCallback(const hMDNSService p_hService, - MDNSServiceProbeResultCallbackFn2 p_fnCallback); - - // Application should call this whenever AP is configured/disabled - bool notifyAPChange(void); - - // 'update' should be called in every 'loop' to run the MDNS processing - bool update(void); - - // 'announce' can be called every time, the configuration of some service - // changes. Mainly, this would be changed content of TXT items. - bool announce(void); - - // Enable OTA update - hMDNSService enableArduino(uint16_t p_u16Port, - bool p_bAuthUpload = false); - - // Domain name helper - static bool indexDomain(char*& p_rpcDomain, - const char* p_pcDivider = "-", - const char* p_pcDefaultDomain = 0); - -protected: - /** - stcHostInformation - */ - struct stcHostInformation - { - /** - clsHandleToPtrMap - */ - using clsHandleToPtrMap = std::map<const void*, const void*>; - - clsLEAMDNSHost* m_pHost; - clsHandleToPtrMap m_HandleToPtr; - - stcHostInformation(clsLEAMDNSHost* p_pHost) - : m_pHost(p_pHost) - {} - - /** - list - */ - using list = std::list<stcHostInformation>; - }; - - stcHostInformation::list m_HostInformations; - - // HELPERS - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - const char* p_pcValue, - bool p_bDynamic); - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint32_t p_u32Value, - bool p_bDynamic); - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint16_t p_u16Value, - bool p_bDynamic); - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - uint8_t p_u8Value, - bool p_bDynamic); - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int32_t p_i32Value, - bool p_bDynamic); - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int16_t p_i16Value, - bool p_bDynamic); - hMDNSTxt _addServiceTxt(const hMDNSService p_hService, - const char* p_pcKey, - int8_t p_i8Value, - bool p_bDynamic); - - AnswerType _answerFlagsToAnswerType(clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags) const; - - clsLEAMDNSHost::clsQuery::clsAnswerAccessor _getAnswerAccessor(const uint32_t p_u32AnswerIndex); - clsLEAMDNSHost::clsQuery::clsAnswerAccessor _getAnswerAccessor(const hMDNSServiceQuery p_hServiceQuery, - const uint32_t p_u32AnswerIndex); - -}; - - -} // namespace MDNSImplementation - - -} // namespace experimental - - -#endif // __LEAMDNS2HOST_LEGACY_H__ - - - - - - From 4e97d1e864f9908cfe85d99c2f25b2cbcb1d95db Mon Sep 17 00:00:00 2001 From: david gauchard <gauchard@laas.fr> Date: Thu, 24 Sep 2020 23:47:05 +0200 Subject: [PATCH 152/152] remove obsolete comments --- libraries/ArduinoOTA/ArduinoOTA.cpp | 1 - .../examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino | 15 --------------- .../LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 16 +--------------- .../mDNS_ServiceMonitor/mDNS_ServiceMonitor.ino | 13 ------------- .../mDNS_ServiceMonitor_v2.ino | 12 ------------ 5 files changed, 1 insertion(+), 56 deletions(-) diff --git a/libraries/ArduinoOTA/ArduinoOTA.cpp b/libraries/ArduinoOTA/ArduinoOTA.cpp index 00a60f214f..83cc5c7905 100644 --- a/libraries/ArduinoOTA/ArduinoOTA.cpp +++ b/libraries/ArduinoOTA/ArduinoOTA.cpp @@ -21,7 +21,6 @@ extern "C" { #include "include/UdpContext.h" #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> #endif diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino index c657d49bdd..ec0320fdb2 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino @@ -36,22 +36,7 @@ #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <time.h> - -/* - Include the MDNSResponder (the library needs to be included also) - As LEA MDNSResponder is experimantal in the ESP8266 environment currently, the - legacy MDNSResponder is defaulted in th include file. - There are two ways to access LEA MDNSResponder: - 1. Prepend every declaration and call to global declarations or functions with the namespace, like: - 'LEAmDNS::MDNSResponder::hMDNSService hMDNSService;' - This way is used in the example. But be careful, if the namespace declaration is missing - somewhere, the call might go to the legacy implementation... - 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. - -*/ #include <PolledTimeout.h> - -//#define MDNS2_EXPERIMENTAL_V1COMPAT #include <ESP8266mDNS.h> /* diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino index 6e9e61e467..a098bcb3e1 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino @@ -37,30 +37,16 @@ #include <ESP8266WebServer.h> #include <LwipIntf.h> #include <time.h> +#include <PolledTimeout.h> // uses API MDNSApiVersion::LEAv2 - -/* - Include the clsLEAMDNSHost (the library needs also to be included) - As LEA clsLEAMDNSHost is experimantal in the ESP8266 environment currently, the - legacy clsLEAMDNSHost is defaulted in the include file. - There are two ways to access LEA clsLEAMDNSHost: - 1. Prepend every declaration and call to global declarations or functions with the namespace, like: - 'LEAmDNS::clsLEAMDNSHost::hMDNSService hMDNSService;' - This way is used in the example. But be careful, if the namespace declaration is missing - somewhere, the call might go to the legacy implementation... - 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. - -*/ #define NO_GLOBAL_MDNS // our MDNS is defined below #include <ESP8266mDNS.h> -#include <PolledTimeout.h> /* Global defines and vars */ - #define TIMEZONE_OFFSET 1 // CET #define DST_OFFSET 1 // CEST #define UPDATE_CYCLE (1 * 1000) // every second diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor/mDNS_ServiceMonitor.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor/mDNS_ServiceMonitor.ino index 98269fb48e..167a968c71 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor/mDNS_ServiceMonitor.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor/mDNS_ServiceMonitor.ino @@ -33,19 +33,6 @@ #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> - -/* - Include the MDNSResponder (the library needs to be included also) - As LEA MDNSResponder is experimantal in the ESP8266 environment currently, the - legacy MDNSResponder is defaulted in th include file. - There are two ways to access LEA MDNSResponder: - 1. Prepend every declaration and call to global declarations or functions with the namespace, like: - 'LEAmDNS:MDNSResponder::hMDNSService hMDNSService;' - This way is used in the example. But be careful, if the namespace declaration is missing - somewhere, the call might go to the legacy implementation... - 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. - -*/ #include <ESP8266mDNS.h> /* diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino index 59f213fd83..1d24990be0 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino @@ -45,18 +45,6 @@ #include <WiFiClient.h> #include <ESP8266WebServer.h> -/* - Include the clsLEAMDNSHost (the library needs to be included also) - As LEA clsLEAMDNSHost is experimental in the ESP8266 environment currently, the - legacy clsLEAMDNSHost is defaulted in th include file. - There are two ways to access LEA clsLEAMDNSHost: - 1. Prepend every declaration and call to global declarations or functions with the namespace, like: - 'LEAmDNS:clsLEAMDNSHost::hMDNSService hMDNSService;' - This way is used in the example. But be careful, if the namespace declaration is missing - somewhere, the call might go to the legacy implementation... - 2. Open 'ESP8266mDNS.h' and set LEAmDNS to default. - -*/ #define NO_GLOBAL_MDNS // our MDNS is defined below #include <ESP8266mDNS.h>