From 7dbef42adaaa1f21d37ea8fe1304a3540812dbb9 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Tue, 22 Dec 2020 01:29:00 +0100 Subject: [PATCH] LEAmDNS fixes (#7786) * LEAmDNS2 removed * LEAmDNSv1: fix macro name --- .../LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino | 269 -- .../mDNS_ServiceMonitor_v2.ino | 259 -- libraries/ESP8266mDNS/src/ESP8266mDNS.h | 7 - libraries/ESP8266mDNS/src/LEAmDNS.cpp | 7 +- libraries/ESP8266mDNS/src/LEAmDNS.h | 3 +- libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp | 1331 ------- libraries/ESP8266mDNS/src/LEAmDNS2Host.h | 1584 -------- .../ESP8266mDNS/src/LEAmDNS2Host_Control.cpp | 2219 ------------ .../ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp | 328 -- .../ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp | 3185 ----------------- .../ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp | 2451 ------------- .../ESP8266mDNS/src/LEAmDNS2_Backbone.cpp | 262 -- libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h | 115 - libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h | 31 - libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp | 4 +- libraries/ESP8266mDNS/src/LEAmDNS_Priv.h | 7 +- tests/host/Makefile | 6 - 17 files changed, 11 insertions(+), 12057 deletions(-) delete mode 100644 libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino delete mode 100644 libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino delete mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp delete mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2Host.h delete mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp delete mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp delete mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp delete mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp delete mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp delete mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h delete mode 100644 libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.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 deleted file mode 100644 index a098bcb3e1..0000000000 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock_v2/mDNS_Clock_v2.ino +++ /dev/null @@ -1,269 +0,0 @@ -/* - ESP8266 mDNS responder clock - - This example demonstrates two features of the LEA clsLEAMDNSHost: - 1. The host and service domain negotiation process that ensures - 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 - 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 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 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. - - 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 -#include -#include -#include -#include -#include - -// uses API MDNSApiVersion::LEAv2 -#define NO_GLOBAL_MDNS // our MDNS is defined below -#include - -/* - Global defines and vars -*/ - -#define TIMEZONE_OFFSET 1 // CET -#define DST_OFFSET 1 // CEST -#define UPDATE_CYCLE (1 * 1000) // every second - -#define START_AP_AFTER_MS 10000 // start AP after delay -#define SERVICE_PORT 80 // HTTP port - -#ifndef STASSID -#define STASSID "your-ssid" -#define STAPSK "your-password" -#endif - -#ifndef APSSID -#define APSSID "ap4mdnsClock" -#define APPSK "mdnsClock" -#endif - -const char* ssid = STASSID; -const char* password = STAPSK; - -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 - -// 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 MDNSRESP.announce(). - -*/ -void MDNSDynamicServiceTxtCallback(const clsLEAMDNSHost::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.reserve(300); - - s = "\r\nHello from "; - s += WiFi.hostname() + " at " + WiFi.localIP().toString(); - // Simple addition of the current time - s += "\r\nCurrent time is: "; - s += getTimeString(); - // done :-) - s += "\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.persistent(false); - - // useless informative callback - if (!LwipIntf::stateUpCB([](netif * nif) { - Serial.printf("New interface %c%c/%d is up\n", - nif->name[0], - nif->name[1], - netif_get_index(nif)); - })) { - Serial.println("Error: could not add informative callback\n"); - } - - 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 '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!")); - // 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 - MDNSRESP.setHostName(clsLEAMDNSHost::indexDomainName(p_pcDomainName, "-", 0)); - } - })) { - 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 - MDNSRESP.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 - Serial.printf("Announce trigger from user\n"); - MDNSRESP.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()); - } -} 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 deleted file mode 100644 index 1d24990be0..0000000000 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_ServiceMonitor_v2/mDNS_ServiceMonitor_v2.ino +++ /dev/null @@ -1,259 +0,0 @@ -/* - ESP8266 mDNS Responder Service Monitor - - 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. - - 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. - -*/ - -// THIS IS A WORK IN PROGRESS: some TODOs need completion - -#ifndef STASSID -#define STASSID "ssid" -#define STAPSK "psk" -#endif - -#ifndef APSSID -#define APSSID "esp8266" -//#define APPSK "psk" -#endif - -#include -#include -#include - -#define NO_GLOBAL_MDNS // our MDNS is defined below -#include - -/* - Global defines and vars -*/ - -#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 -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!
"; -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) { - (void)p_Query; - - String answerInfo; - switch (p_QueryAnswerTypeFlags) { - case static_cast(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain): - answerInfo = "ServiceDomain " + String(p_Answer.m_ServiceDomain.c_str()); - break; - - case static_cast(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::enuQueryAnswerType::IPv4Address): - answerInfo = "IP4Address "; - for (auto ip : p_Answer.m_IPv4Addresses) { - answerInfo += "- " + ip->m_IPAddress.toString(); - }; - break; - case static_cast(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); - - } - 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) { - (void)p_rMDNSService; - 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) { - - (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) { - // 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 - MDNS.setHostName(clsLEAMDNSHost::indexDomainName(p_pcDomainName.c_str(), "-", 0)); - } -} - -/* - 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; - s.reserve(200 /* + service listed */); - s = "\r\n

Hello from "; - s += WiFi.hostname() + ".local at " + server.client().localIP().toString() + "

"; - s += "

Local HTTP services are :

"; - s += "
    "; - - // TODO: list services - - s += "

"; - - Serial.println("Sending 200"); - server.send(200, "text/html", s); - Serial.println("Done with request"); -} - -/* - setup -*/ -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); - 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 - MDNS.setProbeResultCallback(hostProbeResult); - - // Init the (currently empty) host domain string with 'leamdnsv2' - MDNS.begin("leamdnsv2"); - 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/src/ESP8266mDNS.h b/libraries/ESP8266mDNS/src/ESP8266mDNS.h index ec12423388..7c1a1bd5d7 100644 --- a/libraries/ESP8266mDNS/src/ESP8266mDNS.h +++ b/libraries/ESP8266mDNS/src/ESP8266mDNS.h @@ -45,18 +45,11 @@ #ifndef __ESP8266MDNS_H #define __ESP8266MDNS_H -enum class MDNSApiVersion { LEA, LEAv2 }; - #include "LEAmDNS.h" // LEA -#include "LEAmDNS2Host.h" // LEAv2 - API updated - -// 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 = esp8266::MDNSImplementation::MDNSResponder; // LEA -//using MDNSResponder = clsLEAMDNSHost; // LEAv2 extern MDNSResponder MDNS; #endif diff --git a/libraries/ESP8266mDNS/src/LEAmDNS.cpp b/libraries/ESP8266mDNS/src/LEAmDNS.cpp index 828fac52e2..24e5799bb9 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS.cpp @@ -28,7 +28,8 @@ #include "ESP8266mDNS.h" #include "LEAmDNS_Priv.h" #include // LwipIntf::stateUpCB() -#include "lwip/igmp.h" +#include +#include namespace esp8266 { @@ -1304,7 +1305,7 @@ bool MDNSResponder::_joinMulticastGroups(void) { if (netif_is_up(pNetIf)) { -#ifdef MDNS_IPV4_SUPPORT +#ifdef MDNS_IP4_SUPPORT ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; if (!(pNetIf->flags & NETIF_FLAG_IGMP)) { @@ -1354,7 +1355,7 @@ bool MDNSResponder::_leaveMulticastGroups() bResult = true; // Leave multicast group(s) -#ifdef MDNS_IPV4_SUPPORT +#ifdef MDNS_IP4_SUPPORT ip_addr_t multicast_addr_V4 = DNS_MQUERY_IPV4_GROUP_INIT; if (ERR_OK != igmp_leavegroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4))) { diff --git a/libraries/ESP8266mDNS/src/LEAmDNS.h b/libraries/ESP8266mDNS/src/LEAmDNS.h index 091bebaea9..bf2f1e9832 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS.h @@ -130,8 +130,9 @@ namespace MDNSImplementation #endif #define MDNS_IP4_SUPPORT +#if LWIP_IPV6 //#define MDNS_IP6_SUPPORT - +#endif #ifdef MDNS_IP4_SUPPORT #define MDNS_IP4_SIZE 4 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp deleted file mode 100644 index 7722ea6024..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.cpp +++ /dev/null @@ -1,1331 +0,0 @@ -/* - 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 -#include // LwipIntf::stateUpCB() -#include // strrstr() - -#include "ESP8266mDNS.h" -#include "LEAmDNS2Host.h" -#include "LEAmDNS2_Priv.h" - -#ifdef MDNS_IPV4_SUPPORT -#include -#endif -#ifdef MDNS2_IPV6_SUPPORT -#include -#endif - -/** - STRINGIZE -*/ -#ifndef STRINGIZE -#define STRINGIZE(x) #x -#endif -#ifndef STRINGIZE_VALUE_OF -#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) -#endif - -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. - -*/ - -clsLEAMDNSHost::fnProbeResultCallback clsLEAMDNSHost::stProbeResultCallback = nullptr; - -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 = nullptr; - 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 = nullptr; // 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"); - 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; -} - - -/* - clsLEAmDNS2_Host::setStationHostName (static) - - Sets the staion hostname - -*/ -// static -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; -} - - -/** - 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 MDNS2_IPV6_SUPPORT -const char* clsLEAMDNSHost::clsConsts::pcReverseIPv6Domain = "ip6"; -#endif -const char* clsLEAMDNSHost::clsConsts::pcReverseTopDomain = "arpa"; - - -/* - clsLEAmDNS2_Host::clsLEAmDNS2_Host constructor - -*/ -clsLEAMDNSHost::clsLEAMDNSHost(void) - : 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, probe_callback) - - setup global mDNS (adding all netif to the multicast groups), - sets up the instance data (hostname, ...) and starts the probing process - -*/ -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 ? : "_"));); - - bool bResult = false; - - if (m_pUDPContext) - { - close(); - } - - bResult = (setHostName(p_pcHostName)) && - (_joinMulticastGroups()) && - (p_fnCallback ? setProbeResultCallback(p_fnCallback) : true) && - ((m_pUDPContext = _allocBackbone())) && - (restart()); - - if (!bResult) - { - 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 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));); - 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. - }); - - if (!bResult) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s begin: could not add netif status callback\n"), _DH())); - } - return bResult; -} - -/* - clsLEAmDNS2_Host::close - -*/ -bool clsLEAMDNSHost::close(void) -{ - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s close\n"), _DH());); - - m_pUDPContext = nullptr; - 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 = nullptr; - - 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 = nullptr; - } - } - } - 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; -} - -/* - clsLEAmDNS2_Host::removeService - -*/ -bool clsLEAMDNSHost::removeService(clsLEAMDNSHost::clsService* p_pService) -{ - bool bResult = true; - - if (p_pService && - (m_Services.end() != std::find(m_Services.begin(), m_Services.end(), p_pService))) - { - bResult = bResult && _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 = nullptr; - - 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);); - - clsLEAMDNSHost::clsQuery::clsAnswerAccessor::vector ret; - - if (_removeLegacyQuery() && - (p_pcService) && (*p_pcService) && - (p_pcProtocol) && (*p_pcProtocol) && - (p_u16Timeout)) - { - std::list queries; - - clsQuery* pQuery = nullptr; - 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()) - { - // 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 - 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 - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryService: INVALID input data!\n"), _DH());); - } - - } - return ret; -} - -/* - clsLEAmDNS2_Host::queryHost - -*/ -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);); - - if ((p_pcHostName) && (*p_pcHostName) && - (p_u16Timeout) && - (_removeLegacyQuery())) - { - std::list queries; - - clsQuery* pQuery = nullptr; - 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()) - { - // 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 - - 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 - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s queryHost: INVALID input data!\n"), _DH());); - } - } - - return ret; -} -/* - 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) const -{ - 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 = nullptr; - 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 = nullptr; - 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 = nullptr; - if ((p_pcHostName) && (*p_pcHostName)) - { - clsRRDomain domain; - if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) - ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) - : nullptr))) - { - 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 = nullptr; - if ((p_pcHostName) && (*p_pcHostName)) - { - clsRRDomain domain; - if ((pQuery = ((_buildDomainForHost(p_pcHostName, domain)) - ? _installDomainQuery(domain, clsQuery::enuQueryType::Host) - : nullptr))) - { - 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) -{ - if (!_updateProbeStatus()) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: FAILED\n"), _DH())); - return false; - } - - if (!_checkQueryCache()) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: FAILED\n"), _DH())); - return false; - } - - return true; -} - -/* - clsLEAmDNS2_Host::announce -*/ - -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); -} - -/* - 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 -} - - -/* - clsLEAMDNSHost_Legacy::enableArduino -*/ -clsLEAMDNSHost::clsService* clsLEAMDNSHost::enableArduino(uint16_t p_u16Port, - bool p_bAuthUpload /*= false*/) -{ - clsLEAMDNSHost::clsService* svc = addService(nullptr, "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 = nullptr; - } - } - return svc; -} - - -/* - P R O T E C T E D -*/ - -/* - - BACKBONE - -*/ - -/* - clsLEAmDNS2_Host::_allocBackbone - -*/ -UdpContext* clsLEAMDNSHost::_allocBackbone(void) -{ - UdpContext* pUDPContext = nullptr; - - 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 = nullptr; - } - } - 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 = 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"));); - return bResult; -} - - -/* - - MULTICAST GROUPS - -*/ - -/* - clsLEAmDNS2_Host::_joinMulticastGroups -*/ -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)) - { -#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: 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 ((ERR_OK == igmp_joingroup_netif(pNetIf, ip_2_ip4(&multicast_addr_V4)))) - { - 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 MDNS2_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))); -#endif - } - } - return bResult; -} - -/* - clsLEAmDNS2_Host::_leaveMulticastGroups -*/ -bool clsLEAMDNSHost::_leaveMulticastGroups() -{ - bool bResult = false; - - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) - { - if (netif_is_up(pNetIf)) - { - bResult = true; - - // 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(pNetIf, ip_2_ip4(&multicast_addr_V4))) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("\n"));); - } -#endif -#ifdef MDNS2_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"));); - } -#endif - } - } - 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(); - - 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] = tolower(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 = (nullptr != p_rpcDomainName))) - { - delete[] p_rpcDomainName; - p_rpcDomainName = nullptr; - } - 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) const -{ - return (p_pcInstanceName ? : (m_pcDefaultInstanceName ? : (m_pcHostName ? : nullptr))); -} - - -/* - 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 = nullptr; - return (((pLegacyQuery = _findLegacyQuery())) - ? _removeQuery(pLegacyQuery) - : true); -} - -/* - clsLEAmDNS2_Host::_findLegacyQuery - -*/ -clsLEAMDNSHost::clsQuery* clsLEAMDNSHost::_findLegacyQuery(void) const -{ - clsQuery* pLegacyQuery = nullptr; - - 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 = nullptr; - - 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 = nullptr; - - 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_u32SentCount = 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 = nullptr; - - if ((pQuery = _allocQuery(p_QueryType))) - { - pQuery->m_Domain = p_Domain; - pQuery->m_bStaticQuery = false; - - if (_sendQuery(*pQuery)) - { - pQuery->m_u32SentCount = 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 deleted file mode 100644 index 7d0c4c8de2..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host.h +++ /dev/null @@ -1,1584 +0,0 @@ -/* - 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-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 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 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)' - 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "LEAmDNS2_lwIPdefs.h" - - -#define MDNS_IPV4_SUPPORT -#if LWIP_IPV6 -#define MDNS2_IPV6_SUPPORT // If we've got IPv6 support, then we need IPv6 support :-) -#endif - -namespace esp8266 -{ - - -namespace experimental -{ - - -/** - clsLEAMDNSHost -*/ -class clsLEAMDNSHost -{ -protected: - /* - clsConsts - */ - class clsConsts - { - public: -#ifdef MDNS_IPV4_SUPPORT - static constexpr uint16_t u16IPv4Size = 4; // IPv4 address size in bytes -#endif -#ifdef MDNS2_IPV6_SUPPORT - static constexpr uint16_t u16IPv6Size = 16; // IPv6 address size in bytes -#endif - 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"; - -#ifdef MDNS_IPV4_SUPPORT - static const char* pcReverseIPv4Domain; // "in-addr"; -#endif -#ifdef MDNS2_IPV6_SUPPORT - static const char* pcReverseIPv6Domain; // "ip6"; -#endif - static const char* pcReverseTopDomain; // "arpa"; - -#ifdef DNS_RRTYPE_NSEC - static constexpr uint8_t u8DNS_RRTYPE_NSEC = DNS_RRTYPE_NSEC; -#else - static constexpr uint8_t u8DNS_RRTYPE_NSEC = 0x2F; -#endif - static constexpr uint32_t u32SendTimeoutMs = 50; // timeout (ms) for a call to `UDPContext->send()` (12ms=1460B@1Mb/s) - - }; - - /** - list - */ - //using list = std::list; - - // File: ..._Backbone - /** - clsBackbone - XXXX should be merged with holder clsLEAMDNSHost because there is no list anymore in it - */ - 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); - - clsLEAMDNSHost* getUniqueHost() const - { - return m_uniqueHost; - } - - protected: - UdpContext* m_pUDPContext; - bool m_bDelayUDPProcessing; - uint32_t m_u32DelayedDatagrams; - //list m_HostList; - 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 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 MDNS2_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; - }; - - /** - 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; - 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; - - 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; - - static fnProbeResultCallback stProbeResultCallback; - -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; - - /** - fnProbeResultCallback - */ - using fnProbeResultCallback = std::function; - - 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, - int32_t p_i32Value, - 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; - }; - using hMDNSService = clsService; // backward compatibility with LEAmDNS - -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(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, not used - https://tools.ietf.org/html/rfc6762#section-6.1 - 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 MDNS2_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(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 - HostDomainPort = 0x06, - Txts = 0x08, // TXT items -#ifdef MDNS_IPV4_SUPPORT - IPv4Address = 0x10, // IPv4 address -#endif -#ifdef MDNS2_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(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 MDNS2_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(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 MDNS2_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; - /** - clsIPAddressVector - */ - using clsIPAddressVector = std::vector; - /** - vector - */ - using vector = std::vector; - - 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 MDNS2_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; // true: Answer component set, false: component deleted - /** - QueryCallbackAccessorFn - */ - using QueryCallbackAccessorFn = std::function; // 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; - uint32_t m_u32SentCount; - esp8266::polledTimeout::oneShot m_ResendTimeout; - bool m_bAwaitingAnswers; - clsAnswer::list m_Answers; - - /** - list - */ - using list = std::list; - - 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(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, - 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) const; - - // - 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 - - /* - install*Query() creates several queries on the interfaces. - 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, - 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); - - clsService* enableArduino(uint16_t p_u16Port, bool p_bAuthUpload = false); - -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) 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) const; - 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(); - bool _parseQuery(netif* pNetIf, - const clsMsgHeader& p_Header); - - 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, - bool& p_rbFoundNewKeyAnswer); - bool _processTXTAnswer(const clsRRAnswerTXT* p_pTXTAnswer); -#ifdef MDNS_IPV4_SUPPORT - bool _processAAnswer(const clsRRAnswerA* p_pAAnswer); -#endif -#ifdef MDNS2_IPV6_SUPPORT - bool _processAAAAAnswer(const clsRRAnswerAAAA* p_pAAAAAnswer); -#endif - - // PROBING - bool _updateProbeStatus(); - bool _resetProbeStatus(bool p_bRestart = true); - bool _hasProbesWaitingForAnswers(void) const; - bool _sendHostProbe(); - 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(); - - uint32_t _replyMaskForHost(netif* pNetIf, - 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(netif* pNetIf, clsSendParameter& p_SendParameter); - bool _sendMessage(clsSendParameter& p_SendParameter); - bool _sendMessage_Multicast(netif* pNetIf, - clsSendParameter& p_rSendParameter, - uint8_t p_IPProtocolTypes); - bool _prepareMessage(netif* pNetIf, 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(netif* pNetIf, - 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 MDNS2_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 MDNS2_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 MDNS2_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 MDNS2_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: - 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/LEAmDNS2Host_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp deleted file mode 100644 index 4325df7bad..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Control.cpp +++ /dev/null @@ -1,2219 +0,0 @@ -/* - LEAmDNS2Host_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 "ESP8266mDNS.h" -#include "LEAmDNS2Host.h" -#include "LEAmDNS2_Priv.h" - -namespace esp8266 -{ - - -namespace experimental -{ - - -/* - - RECEIVING - -*/ - -/* - clsLEAmDNS2_Host::_parseMessage - -*/ -bool clsLEAMDNSHost::_parseMessage() -{ - 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_pUDPContext->getRemoteAddress().toString().c_str(), - m_pUDPContext->getDestAddress().toString().c_str()); - ); - //DEBUG_EX_INFO(_udpDump();); - netif* pNetIf = m_pUDPContext->getInputNetif(); - - bool bResult = false; - - 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"), - _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(pNetIf, 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(m_pUDPContext->getInputNetif(), header); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: Received UNEXPECTED opcode:%u. Ignoring message!\n"), _DH(), header.m_4bOpcode);); - m_pUDPContext->flush(); - } - } - else - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseMessage: FAILED to read header\n"), _DH());); - m_pUDPContext->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; -} - -/* - 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 - 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). - -*/ -bool clsLEAMDNSHost::_parseQuery(netif* pNetIf, - const clsLEAMDNSHost::clsMsgHeader& p_MsgHeader) -{ - bool bResult = true; - - clsSendParameter sendParameter; - uint32_t u32HostOrServiceReplies = 0; - bool bHostOrServiceTiebreakNeeded = false; - for (uint16_t qd = 0; ((bResult) && (qd < p_MsgHeader.m_u16QDCount)); ++qd) - { - clsRRQuestion questionRR; - if ((bResult = _readRRQuestion(questionRR))) - { - // Define host replies, BUT only answer queries after probing is done - u32HostOrServiceReplies = - sendParameter.m_u32HostReplyMask |= ((probeStatus()) - ? _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));); - - // Check tiebreak need for host domain - if (clsProbeInformation_Base::clsProbeInformation_Base::enuProbingStatus::InProgress == m_ProbeInformation.m_ProbingStatus) - { - bool bFullNameMatch = false; - if ((_replyMaskForHost(pNetIf, 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 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());); - - bHostOrServiceTiebreakNeeded = - m_ProbeInformation.m_bTiebreakNeeded = true; - } - } - - // Define service replies - 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) - : 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 (clsProbeInformation_Base::clsProbeInformation_Base::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));); - - 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_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_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_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 - { - // Local host check - // We're a match for this legacy query, BUT - // make sure, that the query comes from a local host - if ((m_pUDPContext) && -#ifdef MDNS_IPV4_SUPPORT - (m_pUDPContext->getRemoteAddress().isV4()) && - (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 - && -#ifdef MDNS2_IPV6_SUPPORT - (m_pUDPContext->getRemoteAddress().isV6()) && - (ip6_addr_islinklocal(ip_2_ip6((const ip_addr_t*)m_pUDPContext->getRemoteAddress()))) -#else - (true) -#endif - ) - { - 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; - sendParameter.m_bLegacyDNSQuery = true; - sendParameter.m_bCacheFlush = false; - clsRRQuestion* pNewRRQuestion = new clsRRQuestion; - if (pNewRRQuestion) - { - 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 DNS question!\n"), _DH());); - } - } - else - { - 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; - } - } - } - } - 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());); - //bHostOrServiceTiebreakNeeded = false; - - // Handle known answers - uint32_t u32Answers = (p_MsgHeader.m_u16ANCount + p_MsgHeader.m_u16NSCount + p_MsgHeader.m_u16ARCount); - 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) - { - 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 - { - /* - 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(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) - { - - // 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(enuContentFlag::PTR_IPv4)) - { - // IPv4 PTR was asked for, but is already known -> skipping - 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(enuContentFlag::PTR_IPv4); - } - #endif - #ifdef MDNS2_IPV6_SUPPORT - if (u32HostMatchMask & static_cast(enuContentFlag::PTR_IPv6)) - { - // IPv6 PTR was asked for, but is already known -> skipping - 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(enuContentFlag::PTR_IPv6); - } - #endif - } - } - else if (u32HostMatchMask & static_cast(enuContentFlag::A)) - { - // IPv4 address was asked for - #ifdef MDNS_IPV4_SUPPORT - if ((enuAnswerType::A == pKnownRRAnswer->answerType()) && - (((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);); - sendParameter.m_u32HostReplyMask &= ~static_cast(enuContentFlag::A); - } // else: RData NOT IPv4 length !! - #endif - } - else if (u32HostMatchMask & static_cast(enuContentFlag::AAAA)) - { - // IPv6 address was asked for - #ifdef MDNS2_IPV6_SUPPORT - if ((enuAnswerType::AAAA == pKnownRRAnswer->answerType()) && - (((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());); - sendParameter.m_u32HostReplyMask &= ~static_cast(enuContentFlag::AAAA); - } // else: RData NOT IPv6 length !! - #endif - } - } // Host match and TTL - */ - - // - // Check host tiebreak possibility - if (m_ProbeInformation.m_bTiebreakNeeded) - { - clsRRDomain 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(pNetIf, enuIPProtocolType::V4)); - 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_ProbeInformation.m_bTiebreakNeeded = false; - } - else - { - 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 IPv4)!\n"), _DH());); - _cancelProbingForHost(); - m_ProbeInformation.m_bTiebreakNeeded = false; - } - else - { - // WON tiebreak - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv4) WON (higher IPv4)!\n"), _DH());); - m_ProbeInformation.m_bTiebreakNeeded = false; - } - } - } -#endif -#ifdef MDNS2_IPV6_SUPPORT - if (enuAnswerType::AAAA == pKnownRRAnswer->answerType()) - { - 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) - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv6) WON (was an old message)!\n"), _DH());); - m_ProbeInformation.m_bTiebreakNeeded = false; - } - else - { - // 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 IPv6)!\n"), _DH());); - _cancelProbingForHost(); - m_ProbeInformation.m_bTiebreakNeeded = false; - } - else - { - // WON tiebreak - DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: Tiebreak (IPv6) WON (higher IPv6)!\n"), _DH());); - m_ProbeInformation.m_bTiebreakNeeded = false; - } - } - } -#endif - } - } // Host tiebreak possibility - - // Check service answers - 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 - ((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(enuContentFlag::PTR_TYPE)) && - (_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(enuContentFlag::PTR_TYPE); - } - if ((u32ServiceMatchMask & static_cast(enuContentFlag::PTR_NAME)) && - (_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(enuContentFlag::PTR_NAME); - } - } - /* - RFC6762 7.1 Suppression only for 'Shared Records' - else if (u32ServiceMatchMask & static_cast(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 ((Consts::u16SRVPriority == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_u16Priority) && - (Consts::u16SRVWeight == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_u16Weight) && - (pService->m_u16Port == ((stcRRAnswerSRV*)pKnownRRAnswer)->m_u16Port)) - { - - 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(enuContentFlag::SRV); - } // else: Small differences -> send update message - } - }*/ - /* - RFC6762 7.1 Suppression only for 'Shared Records' - else if (u32ServiceMatchMask & static_cast(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_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(enuContentFlag::TXT); - } - _releaseTempServiceTxts(*pService); - }*/ - } // Service match and enough TTL - - // - // Check service tiebreak possibility - if (pService->m_ProbeInformation.m_bTiebreakNeeded) - { - clsRRDomain serviceDomain; - if ((_buildDomainForService(*pService, true, 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 - { - // 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));); - pService->m_ProbeInformation.m_bTiebreakNeeded = false; - } - else - { - 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(pService));); - _cancelProbingForService(*pService); - pService->m_ProbeInformation.m_bTiebreakNeeded = false; - } - else - { - // 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; - } - } - } - } - } // 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_pUDPContext->flush(); - } - - if (bResult) - { - // Check, if a reply is needed - uint32_t u32ReplyNeeded = sendParameter.m_u32HostReplyMask; - for (const clsService* pService : m_Services) - { - u32ReplyNeeded |= pService->m_u32ReplyMask; - } - - if (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 = clsSendParameter::enuResponseType::Response; - sendParameter.m_bAuthorative = true; - - bResult = _sendMessage(pNetIf, 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_pUDPContext->flush(); - } - - // - // Check and reset tiebreak-states - if (m_ProbeInformation.m_bTiebreakNeeded) - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseQuery: UNSOLVED tiebreak-need for host domain!\n"), _DH());); - m_ProbeInformation.m_bTiebreakNeeded = false; - } - for (clsService* pService : m_Services) - { - 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; -} - -/* - clsLEAmDNS2_Host::_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 clsLEAMDNSHost::_parseResponse(netif* pNetIf, const clsLEAMDNSHost::clsMsgHeader& 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 - 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());); - bResult = _readRRQuestion(dummyRRQ); - } // for queries - - // - // Read and collect answers - 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) - { - clsRRAnswer* 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(pNetIf, pCollectedRRAnswers))); - } - else // Some failure while reading answers - { - DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: FAILED to read answers!\n"), _DH());); - m_pUDPContext->flush(); - } - - // Delete collected answers - while (pCollectedRRAnswers) - { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: DELETING answer!\n"), _DH());); - clsRRAnswer* 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) && (qdflush(); - bResult = true; - } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _parseResponse: FAILED!\n"), _DH());); - return bResult; -} - -/* - 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 - 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 clsLEAMDNSHost::_processAnswers(netif* pNetIf, const clsLEAMDNSHost::clsRRAnswer* 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 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((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((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((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((clsRRAnswerA*)pRRAnswer); - } -#endif -#ifdef MDNS2_IPV6_SUPPORT - // AAAA -> IPv6Address - else if (enuAnswerType::AAAA == pRRAnswer->answerType()) - { - // eg. esp8266.local AAAA xxxx xx 09cf::0c - bResult = _processAAAAAnswer((clsRRAnswerAAAA*)pRRAnswer); - } -#endif - - // Finally check for probing conflicts - // Host domain - if ((clsProbeInformation_Base::enuProbingStatus::InProgress == m_ProbeInformation.m_ProbingStatus) && - ((enuAnswerType::A == pRRAnswer->answerType()) || - (enuAnswerType::AAAA == pRRAnswer->answerType()))) - { - 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()) && - (((clsRRAnswerA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(pNetIf, enuIPProtocolType::V4))) - { - bPossibleEcho = true; - } -#endif -#ifdef MDNS2_IPV6_SUPPORT - if ((enuAnswerType::AAAA == pRRAnswer->answerType()) && - (((clsRRAnswerAAAA*)pRRAnswer)->m_IPAddress == _getResponderIPAddress(pNetIf, 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(); - } - 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 (clsService* pService : m_Services) - { - if ((clsProbeInformation_Base::enuProbingStatus::InProgress == pService->m_ProbeInformation.m_ProbingStatus) && - ((enuAnswerType::TXT == pRRAnswer->answerType()) || - (enuAnswerType::SRV == pRRAnswer->answerType()))) - { - 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); - } - } - } - - 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; -} - -/* - clsLEAmDNS2_Host::_processPTRAnswer (level 1) -*/ -bool clsLEAMDNSHost::_processPTRAnswer(const clsLEAMDNSHost::clsRRAnswerPTR* 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' - - 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) - 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); - _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 clsQuery::clsAnswer))) // Not yet included -> add answer - { - pSQAnswer->m_ServiceDomain = p_pPTRAnswer->m_PTRDomain; - pSQAnswer->m_QueryAnswerFlags |= static_cast(clsQuery::clsAnswer::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(clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain), true); - } - } - 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());); - return bResult; -} - -/* - clsLEAmDNS2_Host::_processSRVAnswer (level 2) -*/ -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 - for (clsQuery::list::iterator it = m_Queries.begin(); ((bResult) && (it != m_Queries.end())); it++) - { - clsQuery* pQuery = *it; - - if (pQuery->m_bAwaitingAnswers) - { - clsQuery::clsAnswer* 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(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain) | static_cast(clsQuery::clsAnswer::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(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain) | static_cast(clsQuery::clsAnswer::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 - } // for(queries) - } // else: No p_pSRVAnswer - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _processSRVAnswer: FAILED!\n"), _DH());); - return bResult; -} - -/* - clsLEAmDNS2_Host::_processTXTAnswer (level 2) -*/ -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 - for (clsQuery::list::iterator it = m_Queries.begin(); ((bResult) && (it != m_Queries.end())); it++) - { - clsQuery* pQuery = *it; - - if (pQuery->m_bAwaitingAnswers) - { - 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); - _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(clsQuery::clsAnswer::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(clsQuery::clsAnswer::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 - } // for(queries) - } // 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 -/* - clsLEAmDNS2_Host::_processAAnswer (level 3) -*/ -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 - 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 - (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->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(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain); - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain), true); - } - } - - // 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 - 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 - 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 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(clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address); - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast(clsQuery::clsAnswer::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 - } // for(queries) - } // else: No p_pAAnswer - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _processAAnswer: FAILED!\n"), _DH());); - return bResult; -} -#endif - -#ifdef MDNS2_IPV6_SUPPORT -/* - clsLEAmDNS2_Host::_processAAAAAnswer (level 3) -*/ -bool clsLEAMDNSHost::_processAAAAAnswer(const clsLEAMDNSHost::clsRRAnswerAAAA* p_pAAAAAnswer) -{ - bool bResult = false; - - if ((bResult = (0 != p_pAAAAAnswer))) - { - // eg. esp8266.local AAAA xxxx xx 0bf3::0c - 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 - (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->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(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain); - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain), true); - } - } - - // Look for answers to service queries - clsQuery::clsAnswer* pSQAnswer = pQuery->findAnswerForHostDomain(p_pAAAAAnswer->m_Header.m_Domain); - if (pSQAnswer) // Answer for this host domain (eg. esp8266.local) available - { - 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 - 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 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(clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address); - _executeQueryCallback(*pQuery, *pSQAnswer, static_cast(clsQuery::clsAnswer::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 - } // for(queries) - } // else: No p_pAAAAAnswer - - return bResult; -} -#endif - - -/* - - PROBING - -*/ - -/* - 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 - 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 clsLEAMDNSHost::_updateProbeStatus() -{ - bool bResult = true; - - // - // 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 MDNS2_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());); - - // First probe delay SHOULD be random 0-250 ms - m_ProbeInformation.m_Timeout.reset(rand() % clsConsts::u32ProbeDelay); - m_ProbeInformation.m_ProbingStatus = clsProbeInformation_Base::enuProbingStatus::InProgress; - } - 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_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_u32SentCount; - } - } - 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_ProbeInformation.m_ProbingStatus = clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce; - m_ProbeInformation.m_Timeout.reset(esp8266::polledTimeout::oneShot::neverExpires); - - _callHostProbeResultCallback(true); - - // Prepare to announce host - 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());); - } - } // else: Probing already finished OR waiting for next time slot - 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 - ++m_ProbeInformation.m_u32SentCount; // 1.. - - if (clsConsts::u32AnnounceCount > m_ProbeInformation.m_u32SentCount) - { - 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 - { - 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 (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) - { - clsService* pService = *it; - - 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 ((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_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_u32SentCount + 1));); - pService->m_ProbeInformation.m_Timeout.reset(clsConsts::u32ProbeDelay); - ++pService->m_ProbeInformation.m_u32SentCount; - } - } - else - { - // Probing finished - 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); - - _callServiceProbeResultCallback(*pService, true); - - // Prepare to announce service - 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());); - } - } - else if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == pService->m_ProbeInformation.m_ProbingStatus) && - (pService->m_ProbeInformation.m_Timeout.expired())) - { - // Probing already finished OR waiting for next time slot - if ((bResult = _announceService(*pService))) - { - // Announce service - ++pService->m_ProbeInformation.m_u32SentCount; // 1.. - - if (clsConsts::u32AnnounceCount > pService->m_ProbeInformation.m_u32SentCount) - { - 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 - { - 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)); - } - } - } - } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _updateProbeStatus: FAILED!\n\n"), _DH());); - return bResult; -} - -/* - 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 clsLEAMDNSHost::_resetProbeStatus(bool p_bRestart /*= true*/) -{ - m_ProbeInformation.clear(false); - m_ProbeInformation.m_ProbingStatus = (p_bRestart ? clsProbeInformation_Base::enuProbingStatus::ReadyToStart : clsProbeInformation_Base::enuProbingStatus::DoneFinally); - - for (clsService* pService : m_Services) - { - pService->m_ProbeInformation.clear(false); - pService->m_ProbeInformation.m_ProbingStatus = m_ProbeInformation.m_ProbingStatus; - } - return true; -} - -/* - clsLEAmDNS2_Host::_hasProbesWaitingForAnswers - -*/ -bool clsLEAMDNSHost::_hasProbesWaitingForAnswers(void) const -{ - bool bResult = ((clsProbeInformation_Base::enuProbingStatus::InProgress == m_ProbeInformation.m_ProbingStatus) && // 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_u32SentCount)); // And really probing - } - return bResult; -} - -/* - clsLEAmDNS2_Host::_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 'known answers' section of the query. - Host domain: - - A/AAAA (eg. esp8266.esp -> 192.168.2.120) - -*/ -bool clsLEAMDNSHost::_sendHostProbe() -{ - 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 - clsSendParameter sendParameter; - sendParameter.m_bCacheFlush = false; // RFC 6762 10.2 - - clsRRQuestion* pNewRRQuestion = new clsRRQuestion; - if (((bResult = (0 != pNewRRQuestion))) && - ((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; - 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(enuContentFlag::A); // Add A answer -#endif -#ifdef MDNS2_IPV6_SUPPORT - sendParameter.m_u32HostReplyMask |= static_cast(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 (pNewRRQuestion) - { - delete pNewRRQuestion; - pNewRRQuestion = 0; - } - } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendHostProbe: FAILED!\n"), _DH());); - return ((bResult) && - (_sendMessage(sendParameter))); -} - -/* - clsLEAmDNS2_Host::_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 '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) - -*/ -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 - clsSendParameter sendParameter; - sendParameter.m_bCacheFlush = false; // RFC 6762 10.2 - - 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_RRQuestions.push_back(pNewRRQuestion); - - // Add known answers - p_rService.m_u32ReplyMask = (static_cast(enuContentFlag::SRV) | static_cast(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 (pNewRRQuestion) - { - delete pNewRRQuestion; - pNewRRQuestion = 0; - } - } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendServiceProbe: FAILED!\n"), _DH());); - return ((bResult) && - (_sendMessage(sendParameter))); -} - -/* - clsLEAmDNS2_Host::_cancelProbingForHost - -*/ -bool clsLEAMDNSHost::_cancelProbingForHost(void) -{ - bool bResult; - - m_ProbeInformation.clear(false); - - // Send host notification - bResult = _callHostProbeResultCallback(false); - - for (clsService* pService : m_Services) - { - bResult = bResult && _cancelProbingForService(*pService); - } - return bResult; -} - -/* - clsLEAmDNS2_Host::_cancelProbingForService - -*/ -bool clsLEAMDNSHost::_cancelProbingForService(clsService& p_rService) -{ - p_rService.m_ProbeInformation.clear(false); - - // Send notification - return _callServiceProbeResultCallback(p_rService, false); -} - -/* - clsLEAmDNS2_Host::_callHostProbeResultCallback - -*/ -bool clsLEAMDNSHost::_callHostProbeResultCallback(bool p_bResult) -{ - if (m_ProbeInformation.m_fnProbeResultCallback) - { - 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 - indexHostName(); - DEBUG_EX_INFO2(DEBUG_OUTPUT.printf_P(PSTR("%s _callHostProbeResultCallback: Changed Host Name: %s\n"), _DH(), (m_pcHostName ? : ""))); - } - return true; -} - -/* - clsLEAmDNS2_Host::_callServiceProbeResultCallback - -*/ -bool clsLEAMDNSHost::_callServiceProbeResultCallback(clsLEAMDNSHost::clsService& p_rService, - bool p_bResult) -{ - if (p_rService.m_ProbeInformation.m_fnProbeResultCallback) - { - 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 - 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 - -*/ - -/* - clsLEAmDNS2_Host::_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 clsLEAMDNSHost::_announce(bool p_bAnnounce, - bool p_bIncludeServices) -{ - bool bResult = false; - - 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);); - - if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == m_ProbeInformation.m_ProbingStatus) || - (clsProbeInformation_Base::enuProbingStatus::DoneFinally == m_ProbeInformation.m_ProbingStatus)) - { - bResult = true; - - 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 - - // Announce host - sendParameter.m_u32HostReplyMask = 0; -#ifdef MDNS_IPV4_SUPPORT - sendParameter.m_u32HostReplyMask |= static_cast(enuContentFlag::A); // A answer - sendParameter.m_u32HostReplyMask |= static_cast(enuContentFlag::PTR_IPv4); // PTR_IPv4 answer -#endif -#ifdef MDNS2_IPV6_SUPPORT - sendParameter.m_u32HostReplyMask |= static_cast(enuContentFlag::AAAA); // AAAA answer - sendParameter.m_u32HostReplyMask |= static_cast(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 (clsService* pService : m_Services) - { - if ((clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == pService->m_ProbeInformation.m_ProbingStatus) || - (clsProbeInformation_Base::enuProbingStatus::DoneFinally == pService->m_ProbeInformation.m_ProbingStatus)) - { - pService->m_u32ReplyMask = (static_cast(enuContentFlag::PTR_TYPE) | - static_cast(enuContentFlag::PTR_NAME) | - static_cast(enuContentFlag::SRV) | - static_cast(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\n"), _DH());); - return ((bResult) && - (_sendMessage(sendParameter))); -} - -/* - clsLEAmDNS2_Host::_announceService - -*/ -bool clsLEAMDNSHost::_announceService(clsLEAMDNSHost::clsService& p_rService, - bool p_bAnnounce /*= true*/) -{ - bool bResult = false; - - clsSendParameter sendParameter; - if (clsProbeInformation_Base::enuProbingStatus::ReadyToAnnounce == p_rService.m_ProbeInformation.m_ProbingStatus) - { - 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 - - // DON'T announce host - sendParameter.m_u32HostReplyMask = 0; - - // Announce services (service type, name, SRV (location) and TXTs) - p_rService.m_u32ReplyMask = (static_cast(enuContentFlag::PTR_TYPE) | - static_cast(enuContentFlag::PTR_NAME) | - static_cast(enuContentFlag::SRV) | - static_cast(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) && - (_sendMessage(sendParameter))); -} - - -/* - - QUERY CACHE - -*/ - -/* - 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. - 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 clsLEAMDNSHost::_checkQueryCache() -{ - bool bResult = true; - - DEBUG_EX_INFO( - bool printedInfo = false; - ); - 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_bStaticQuery) && - (pQuery->m_ResendTimeout.expired())) - { - if ((bResult = _sendQuery(*pQuery))) - { - // The re-query rate is increased to more than one hour (RFC 6762 5.2) - ++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); - } - else - { - break; - } - 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) - { - clsQuery::clsAnswer::list expiredAnswers; - for (clsQuery::clsAnswer::list::iterator itQA = pQuery->m_Answers.begin(); ((bResult) && (itQA != pQuery->m_Answers.end())); itQA++) - { - clsQuery::clsAnswer* pQAnswer = *itQA; - - // 1. level answer - if ((bResult) && - (pQAnswer->m_TTLServiceDomain.flagged())) - { - if (!pQAnswer->m_TTLServiceDomain.finalTimeoutLevel()) - { - bResult = ((_sendQuery(*pQuery)) && - (pQAnswer->m_TTLServiceDomain.restart())); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: PTR update scheduled for "), _DH()); - _printRRDomain(pQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" %s\n"), (bResult ? "OK" : "FAILURE")); - printedInfo = true; - ); - } - else - { - // Timed out! -> Delete - _executeQueryCallback(*pQuery, *pQAnswer, static_cast(clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain), false); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("%s _checkQueryCache: Will remove PTR answer for "), _DH()); - _printRRDomain(pQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR("\n")); - printedInfo = true; - ); - - expiredAnswers.push_back(pQAnswer); - continue; // Don't use this answer anymore - } - } // ServiceDomain flagged - - // 2. level answers - // HostDomain & Port (from SRV) - if ((bResult) && - (pQAnswer->m_TTLHostDomainAndPort.flagged())) - { - if (!pQAnswer->m_TTLHostDomainAndPort.finalTimeoutLevel()) - { - 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(pQAnswer->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(pQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); - printedInfo = true; - ); - // Delete - pQAnswer->m_HostDomain.clear(); - //pSQAnswer->releaseHostDomain(); - pQAnswer->m_u16Port = 0; - pQAnswer->m_TTLHostDomainAndPort.set(0); - clsQuery::clsAnswer::typeQueryAnswerType queryAnswerContentFlags = (static_cast(clsQuery::clsAnswer::enuQueryAnswerType::HostDomain) | static_cast(clsQuery::clsAnswer::enuQueryAnswerType::Port)); - // As the host domain is the base for the IPv4- and IPv6Address, remove these too -#ifdef MDNS_IPV4_SUPPORT - pQAnswer->releaseIPv4Addresses(); - queryAnswerContentFlags |= static_cast(clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address); -#endif -#ifdef MDNS2_IPV6_SUPPORT - pQAnswer->releaseIPv6Addresses(); - queryAnswerContentFlags |= static_cast(clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address); -#endif - - // Remove content flags for deleted answer parts - pQAnswer->m_QueryAnswerFlags &= ~queryAnswerContentFlags; - _executeQueryCallback(*pQuery, *pQAnswer, queryAnswerContentFlags, false); - } - } // HostDomainAndPort flagged - - // Txts (from TXT) - if ((bResult) && - (pQAnswer->m_TTLTxts.flagged())) - { - if (!pQAnswer->m_TTLTxts.finalTimeoutLevel()) - { - 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(pQAnswer->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(pQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); - printedInfo = true; - ); - // Delete - pQAnswer->m_Txts.clear(); - pQAnswer->m_TTLTxts.set(0); - - // Remove content flags for deleted answer parts - pQAnswer->m_QueryAnswerFlags &= ~static_cast(clsQuery::clsAnswer::enuQueryAnswerType::Txts); - _executeQueryCallback(*pQuery, *pQAnswer, static_cast(clsQuery::clsAnswer::enuQueryAnswerType::Txts), false); - } - } // TXTs flagged - - // 3. level answers -#ifdef MDNS_IPV4_SUPPORT - // IPv4Address (from A) - clsQuery::clsAnswer::clsIPAddressWithTTL::list expiredIPv4Addresses; - bool bAUpdateQuerySent = false; - for (clsQuery::clsAnswer::clsIPAddressWithTTL::list::iterator itQAIPv4 = pQAnswer->m_IPv4Addresses.begin(); ((bResult) && (itQAIPv4 != pQAnswer->m_IPv4Addresses.end())); itQAIPv4++) - { - clsQuery::clsAnswer::clsIPAddressWithTTL* pIPv4Address = *itQAIPv4; - - if (pIPv4Address->m_TTL.flagged()) - { - if (!pIPv4Address->m_TTL.finalTimeoutLevel()) - { - // Needs update - if ((bAUpdateQuerySent) || - ((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(pQAnswer->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(pQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IPv4 address\n")); - printedInfo = true; - ); - if (1 == pQAnswer->m_IPv4Addresses.size()) - { - // NO IPv4 address left after this -> remove content flag - pQAnswer->m_QueryAnswerFlags &= ~static_cast(clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address); - } - // Notify client - _executeQueryCallback(*pQuery, *pQAnswer, static_cast(clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address), false); - expiredIPv4Addresses.push_back(pIPv4Address); - } - } // IPv4 flagged - } // for - // Finally remove expired IPv4 addresses - for (clsQuery::clsAnswer::clsIPAddressWithTTL* pIPv4Address : expiredIPv4Addresses) - { - pQAnswer->removeIPv4Address(pIPv4Address); - } -#endif -#ifdef MDNS2_IPV6_SUPPORT - // IPv6Address (from AAAA) - clsQuery::clsAnswer::clsIPAddressWithTTL::list expiredIPv6Addresses; - bool bAAAAUpdateQuerySent = false; - for (clsQuery::clsAnswer::clsIPAddressWithTTL::list::iterator itQAIPv6 = pQAnswer->m_IPv6Addresses.begin(); ((bResult) && (itQAIPv6 != pQAnswer->m_IPv6Addresses.end())); itQAIPv6++) - { - clsQuery::clsAnswer::clsIPAddressWithTTL* pIPv6Address = *itQAIPv6; - - if (pIPv6Address->m_TTL.flagged()) - { - if (!pIPv6Address->m_TTL.finalTimeoutLevel()) - { - // Needs update - if ((bAAAAUpdateQuerySent) || - ((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(pQAnswer->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(pQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IPv6 address\n")); - printedInfo = true; - ); - if (1 == pQAnswer->m_IPv6Addresses.size()) - { - // NO IPv6 address left after this -> remove content flag - pQAnswer->m_QueryAnswerFlags &= ~static_cast(clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address); - } - // Notify client - _executeQueryCallback(*pQuery, *pQAnswer, static_cast(clsQuery::clsAnswer::enuQueryAnswerType::IPv6Address), false); - expiredIPv6Addresses.push_back(pIPv6Address); - } - } // IPv6 flagged - // Finally remove expired IPv6 addresses - for (clsQuery::clsAnswer::clsIPAddressWithTTL* pIPv6Address : expiredIPv6Addresses) - { - pQAnswer->removeIPv6Address(pIPv6Address); - } - } // while -#endif - } - - // Finally remove expired answers - for (clsQuery::clsAnswer* pAnswer : expiredAnswers) - { - pQuery->removeAnswer(pAnswer); - } - } - } - 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; -} - - -/* - clsLEAmDNS2_Host::_replyMaskForHost - - 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. - - In addition, a full name match (question domain == host domain) is marked. -*/ -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"));); - - 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 - clsRRDomain reverseIPv4Domain; - if ((_getResponderIPAddress(pNetIf, enuIPProtocolType::V4).isSet()) && - (_buildDomainForReverseIPv4(_getResponderIPAddress(pNetIf, enuIPProtocolType::V4), reverseIPv4Domain)) && - (p_RRHeader.m_Domain == reverseIPv4Domain)) - { - // Reverse domain match - u32ReplyMask |= static_cast(enuContentFlag::PTR_IPv4); - } -#endif -#ifdef MDNS2_IPV6_SUPPORT - clsRRDomain reverseIPv6Domain; - if ((_getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet()) && - (_buildDomainForReverseIPv6(_getResponderIPAddress(pNetIf, enuIPProtocolType::V6), reverseIPv6Domain)) && - (p_RRHeader.m_Domain == reverseIPv6Domain)) - { - // Reverse domain match - u32ReplyMask |= static_cast(enuContentFlag::PTR_IPv6); - } -#endif - } // Address qeuest - - 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 - 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(enuContentFlag::A); - } -#endif -#ifdef MDNS2_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(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; -} - -/* - 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 - - 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 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); - - if ((DNS_RRCLASS_IN == (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))) - { - // Common service info requested - u32ReplyMask |= static_cast(enuContentFlag::PTR_TYPE); - } - - 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))) - { - // Special service info requested - u32ReplyMask |= static_cast(enuContentFlag::PTR_NAME); - } - - 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) || - (DNS_RRTYPE_ANY == p_RRHeader.m_Attributes.m_u16Type)) - { - // Instance info SRV requested - u32ReplyMask |= static_cast(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(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_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/LEAmDNS2Host_Debug.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp deleted file mode 100644 index 9e584e48d1..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Debug.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/* - LEAmDNS2Host_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 "ESP8266mDNS.h" -#include "LEAmDNS2Host.h" -#include "LEAmDNS2_Priv.h" - -namespace esp8266 -{ - - -namespace experimental -{ - - -#ifdef DEBUG_ESP_PORT - -/* - clsLEAmDNS2_Host::_DH - -*/ -const char* clsLEAMDNSHost::_DH(const clsLEAMDNSHost::clsService* p_pService /*= 0*/) const -{ - static char acBuffer[16 + 64]; - - *acBuffer = 0; - sprintf_P(acBuffer, PSTR("[mDNS]")); - if (p_pService) - { - strcat_P(acBuffer, PSTR(">")); - strcat(acBuffer, _service2String(p_pService)); - } - return acBuffer; -} - -/* - clsLEAmDNS2_Host::_service2String - -*/ -const char* clsLEAMDNSHost::_service2String(const clsLEAMDNSHost::clsService* p_pService) const -{ - static char acBuffer[64]; - - *acBuffer = 0; - if (p_pService) - { - sprintf_P(acBuffer, PSTR("%s.%s%s.%s%s.local"), - (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; -} - -/* - clsLEAmDNS2_Host::_printRRDomain - -*/ -bool clsLEAMDNSHost::_printRRDomain(const clsLEAMDNSHost::clsRRDomain& 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; -} - -/* - clsLEAmDNS2_Host::_printRRAnswer - -*/ -bool clsLEAMDNSHost::_printRRAnswer(const clsLEAMDNSHost::clsRRAnswer& 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 clsRRAnswerA*)&p_RRAnswer)->m_IPAddress.toString().c_str()); - break; -#endif - case DNS_RRTYPE_PTR: - DEBUG_OUTPUT.printf_P(PSTR("PTR ")); - _printRRDomain(((const clsRRAnswerPTR*)&p_RRAnswer)->m_PTRDomain); - break; - case DNS_RRTYPE_TXT: - { - size_t stTxtLength = ((const clsRRAnswerTXT*)&p_RRAnswer)->m_Txts.c_strLength(); - char* pTxts = new char[stTxtLength]; - if (pTxts) - { - ((/*const c_str()!!*/clsRRAnswerTXT*)&p_RRAnswer)->m_Txts.c_str(pTxts); - DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts); - delete[] pTxts; - } - break; - } -#ifdef MDNS2_IPV6_SUPPORT - case DNS_RRTYPE_AAAA: - 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 clsRRAnswerSRV*)&p_RRAnswer)->m_u16Port); - _printRRDomain(((const clsRRAnswerSRV*)&p_RRAnswer)->m_SRVDomain); - break; - default: - DEBUG_OUTPUT.printf_P(PSTR("generic ")); - break; - } - DEBUG_OUTPUT.printf_P(PSTR("\n")); - - return true; -} - -/* - clsLEAmDNS2_Host::_RRType2Name - -*/ -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 - { -#ifdef MDNS_IPV4_SUPPORT - case DNS_RRTYPE_A: strcpy_P(acRRName, PSTR("A")); break; -#endif - case DNS_RRTYPE_PTR: strcpy_P(acRRName, PSTR("PTR")); break; - case DNS_RRTYPE_TXT: strcpy_P(acRRName, PSTR("TXT")); break; -#ifdef MDNS2_IPV6_SUPPORT - case DNS_RRTYPE_AAAA: strcpy_P(acRRName, PSTR("AAAA")); break; -#endif - 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; -} - -/* - clsLEAmDNS2_Host::_RRClass2String - -*/ -const char* clsLEAMDNSHost::_RRClass2String(uint16_t p_u16RRClass, - bool p_bIsQuery) const -{ - static char acClassString[16]; - *acClassString = 0; - - if (p_u16RRClass & 0x0001) - { - strcat_P(acClassString, PSTR("IN ")); // 3 - } - if (p_u16RRClass & 0x8000) - { - strcat_P(acClassString, (p_bIsQuery ? PSTR("UNICAST ") : PSTR("FLUSH "))); // 8/6 - } - - return acClassString; // 11 -} - -/* - clsLEAmDNS2_Host::_replyFlags2String - -*/ -const char* clsLEAMDNSHost::_replyFlags2String(uint32_t p_u32ReplyFlags) const -{ - static char acFlagsString[64]; - - *acFlagsString = 0; - if (p_u32ReplyFlags & static_cast(enuContentFlag::A)) - { - strcat_P(acFlagsString, PSTR("A ")); // 2 - } - if (p_u32ReplyFlags & static_cast(enuContentFlag::PTR_IPv4)) - { - strcat_P(acFlagsString, PSTR("PTR_IPv4 ")); // 7 - } - if (p_u32ReplyFlags & static_cast(enuContentFlag::PTR_IPv6)) - { - strcat_P(acFlagsString, PSTR("PTR_IPv6 ")); // 7 - } - if (p_u32ReplyFlags & static_cast(enuContentFlag::AAAA)) - { - strcat_P(acFlagsString, PSTR("AAAA ")); // 5 - } - if (p_u32ReplyFlags & static_cast(enuContentFlag::PTR_TYPE)) - { - strcat_P(acFlagsString, PSTR("PTR_TYPE ")); // 9 - } - if (p_u32ReplyFlags & static_cast(enuContentFlag::PTR_NAME)) - { - strcat_P(acFlagsString, PSTR("PTR_NAME ")); // 9 - } - if (p_u32ReplyFlags & static_cast(enuContentFlag::TXT)) - { - strcat_P(acFlagsString, PSTR("TXT ")); // 4 - } - if (p_u32ReplyFlags & static_cast(enuContentFlag::SRV)) - { - strcat_P(acFlagsString, PSTR("SRV ")); // 4 - } - if (p_u32ReplyFlags & static_cast(enuContentFlag::NSEC)) - { - strcat_P(acFlagsString, PSTR("NSEC ")); // 5 - } - - if (0 == p_u32ReplyFlags) - { - strcpy_P(acFlagsString, PSTR("none")); - } - - // Remove trailing spaces - while ((*acFlagsString) && - (' ' == acFlagsString[strlen(acFlagsString) - 1])) - { - acFlagsString[strlen(acFlagsString) - 1] = 0; - } - - return acFlagsString; // 63 -} - -/* - clsLEAmDNS2_Host::_NSECBitmap2String - -*/ -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_P(acFlagsString, PSTR("A ")); // 2 - } -#endif - if (p_pNSECBitmap->getBit(DNS_RRTYPE_PTR)) - { - strcat_P(acFlagsString, PSTR("PTR ")); // 4 - } -#ifdef MDNS2_IPV6_SUPPORT - if (p_pNSECBitmap->getBit(DNS_RRTYPE_AAAA)) - { - strcat_P(acFlagsString, PSTR("AAAA ")); // 5 - } -#endif - if (p_pNSECBitmap->getBit(DNS_RRTYPE_TXT)) - { - strcat_P(acFlagsString, PSTR("TXT ")); // 4 - } - if (p_pNSECBitmap->getBit(DNS_RRTYPE_SRV)) - { - strcat_P(acFlagsString, PSTR("SRV ")); // 4 - } - if (p_pNSECBitmap->getBit(clsConsts::u8DNS_RRTYPE_NSEC)) - { - strcat_P(acFlagsString, PSTR("NSEC ")); // 5 - } - - if (!*acFlagsString) - { - strcpy_P(acFlagsString, PSTR("none")); - } - - return acFlagsString; // 31 -} - -#endif // DEBUG_ESP_PORT - - -} // namespace MDNSImplementation - - -} // namespace esp8266 - - - - diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp deleted file mode 100644 index 9c323bc32c..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Structs.cpp +++ /dev/null @@ -1,3185 +0,0 @@ -/* - 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 - -#include "ESP8266mDNS.h" -#include "LEAmDNS2Host.h" -#include "LEAmDNS2_Priv.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 + 1); - 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 + 1); - 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++ = ';'; - } - strcpy(pcCursor, pTxt->m_pcKey); - pcCursor += stLength; - *pcCursor++ = '='; - if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) - { - strcpy(pcCursor, pTxt->m_pcValue); - pcCursor += stLength; - } - } - else - { - break; - } - } - } - 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::buffer - -*/ -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))))) - { - strcpy(p_pcBuffer, pTxt->m_pcKey); - p_pcBuffer += stLength; - *p_pcBuffer++ = '='; - if ((stLength = (pTxt->m_pcValue ? strlen(pTxt->m_pcValue) : 0))) - { - strcpy(p_pcBuffer, pTxt->m_pcValue); - p_pcBuffer += stLength; - } - } - else - { - break; - } - } - } - 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) && - (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) && - (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_u32SentCount(0), - m_Timeout(std::numeric_limits::max()), - m_bConflict(false), - m_bTiebreakNeeded(false) -{ -} - -/* - clsLEAMDNSHost::clsProbeInformation_Base::clear -*/ -bool clsLEAMDNSHost::clsProbeInformation_Base::clear(void) -{ - m_ProbingStatus = enuProbingStatus::WaitingForData; - m_u32SentCount = 0; - m_Timeout.reset(std::numeric_limits::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])))) - { - strcpy(m_pcInstanceName, p_pcInstanceName); - _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])))) - { - strcpy(m_pcType, p_pcType); - _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])))) - { - strcpy(m_pcProtocol, p_pcProtocol); - _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 (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::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; - } - strcpy(&(m_acName[m_u16NameLength]), p_pcLabel); - 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 length - 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 MDNS2_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::max()), - m_TimeoutLevel(static_cast(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(enuTimeoutLevel::Base); // Set to 80% - m_TTLTimeout.reset(timeout()); - } - else - { - m_TimeoutLevel = static_cast(enuTimeoutLevel::None); // undef - m_TTLTimeout.reset(std::numeric_limits::max()); - } - return true; -} - -/* - clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::flagged - -*/ -bool clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::flagged(void) const -{ - return ((m_u32TTL) && - (static_cast(enuTimeoutLevel::None) != m_TimeoutLevel) && - (((esp8266::polledTimeout::timeoutTemplate*)&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(enuTimeoutLevel::Base) <= m_TimeoutLevel) && // >= 80% AND - (static_cast(enuTimeoutLevel::Final) > m_TimeoutLevel)) // < 100% - { - m_TimeoutLevel += static_cast(enuTimeoutLevel::Interval); // increment by 5% - m_TTLTimeout.reset(timeout()); - } - else - { - bResult = false; - m_TTLTimeout.reset(std::numeric_limits::max()); - m_TimeoutLevel = static_cast(enuTimeoutLevel::None); - } - return bResult; -} - -/* - clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::prepareDeletion - -*/ -bool clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::prepareDeletion(void) -{ - m_TimeoutLevel = static_cast(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(enuTimeoutLevel::Final) == m_TimeoutLevel); -} - -/* - clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::timeout - -*/ -unsigned long clsLEAMDNSHost::clsQuery::clsAnswer::clsTTL::timeout(void) const -{ - uint32_t u32Timeout = std::numeric_limits::max(); - - if (static_cast(enuTimeoutLevel::Base) == m_TimeoutLevel) // 80% - { - u32Timeout = (m_u32TTL * 800); // to milliseconds - } - else if ((static_cast(enuTimeoutLevel::Base) < m_TimeoutLevel) && // >80% AND - (static_cast(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 MDNS2_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 MDNS2_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(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::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::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::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::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 MDNS2_IPV6_SUPPORT -/* - clsLEAMDNSHost::clsQuery::clsAnswerAccessor::IPv6AddressAvailable - -*/ -bool clsLEAMDNSHost::clsQuery::clsAnswerAccessor::IPv6AddressAvailable(void) const -{ - return ((m_pAnswer) && - (m_pAnswer->m_QueryAnswerFlags & static_cast(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::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 MDNS2_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_u32SentCount(0), - m_ResendTimeout(std::numeric_limits::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_u32SentCount = 0; - m_ResendTimeout.reset(std::numeric_limits::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/LEAmDNS2Host_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp deleted file mode 100644 index 0d719da36e..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2Host_Transfer.cpp +++ /dev/null @@ -1,2451 +0,0 @@ -/* - LEAmDNS2Host_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. - -*/ - -#include // for can_yield() -#include "ESP8266mDNS.h" -#include "LEAmDNS2Host.h" -#include "LEAmDNS2_Priv.h" - -namespace esp8266 -{ - - -namespace experimental -{ - - -/* - - SENDING - -*/ - -/* - MDNSResponder::_sendMessage - - Unicast responses are prepared and sent directly to the querier. - Multicast responses or queries are transferred to _sendMessage_Multicast - - Any reply flags in installed services are removed at the end! - -*/ -bool clsLEAMDNSHost::_sendMessage(clsLEAMDNSHost::clsSendParameter& p_rSendParameter) -{ - bool bResult = true; - for (netif* pNetIf = netif_list; pNetIf; pNetIf = pNetIf->next) - if (netif_is_up(pNetIf)) - { - bResult = bResult && _sendMessage(pNetIf, p_rSendParameter); - } - - // Finally clear service reply masks - for (clsService* pService : m_Services) - { - pService->m_u32ReplyMask = 0; - } - return bResult; -} -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()) - { - u8AvailableProtocols |= static_cast(enuIPProtocolType::V4); - } - DEBUG_EX_INFO(else - { - DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage: No IPv4 address available!\n"), _DH()); - }); -#endif -#ifdef MDNS2_IPV6_SUPPORT - // Only send out IPv6 messages, if we've got an IPv6 address - if (_getResponderIPAddress(pNetIf, enuIPProtocolType::V6).isSet()) - { - u8AvailableProtocols |= static_cast(enuIPProtocolType::V6); - } - DEBUG_EX_INFO(else - { - DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage: No IPv6 address available!\n"), _DH()); - }); -#endif - - if (clsBackbone::sm_pBackbone->setDelayUDPProcessing(true)) - { - // Avoid 're-entry-like problems because delay() is called! - if (clsSendParameter::enuResponseType::None != p_rSendParameter.m_Response) - { - IPAddress ipRemote = ((clsSendParameter::enuResponseType::Response == p_rSendParameter.m_Response) - ? m_pUDPContext->getRemoteAddress() - : IPAddress()); - - if (p_rSendParameter.m_bUnicast) - { - // 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(pNetIf, p_rSendParameter)) && - (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());); - } - 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(enuIPProtocolType::V4))) // AND IPv4 protocol available - { - bResult = _sendMessage_Multicast(pNetIf, p_rSendParameter, static_cast(enuIPProtocolType::V4)); - } -#endif -#ifdef MDNS2_IPV6_SUPPORT - if (((!ipRemote.isSet()) || // NO remote IP - (ipRemote.isV6())) && // OR IPv6 - (u8AvailableProtocols & static_cast(enuIPProtocolType::V6))) // AND IPv6 protocol available - { - bResult = _sendMessage_Multicast(pNetIf, p_rSendParameter, static_cast(enuIPProtocolType::V6)); - } -#endif - } - } - else - { - // Multicast query -> Send by all available protocols - bResult = ((u8AvailableProtocols) && - (_sendMessage_Multicast(pNetIf, p_rSendParameter, u8AvailableProtocols))); - } - - clsBackbone::sm_pBackbone->setDelayUDPProcessing(false); - } - - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendMessage: FAILED!\n"), _DH());); - return bResult; -} - -/* - MDNSResponder::_sendMessage_Multicast - - Fills the UDP output buffer (via _prepareMessage) and sends the buffer - via the selected WiFi protocols -*/ -bool clsLEAMDNSHost::_sendMessage_Multicast(netif* pNetIf, clsLEAMDNSHost::clsSendParameter& p_rSendParameter, - uint8_t p_IPProtocolTypes) -{ - 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(enuIPProtocolType::V4)) - { - 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(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->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());); - } -#endif - -#ifdef MDNS2_IPV6_SUPPORT - if (p_IPProtocolTypes & static_cast(enuIPProtocolType::V6)) - { - 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(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(pNetIf, p_rSendParameter)) && - (m_pUDPContext->setMulticastInterface(pNetIf), true) && - (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"));); - } -#endif - - 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::_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, - while in the second loop, the header and all queries and answers are written to the UDP - output buffer. - -*/ -bool clsLEAMDNSHost::_prepareMessage(netif* pNetIf, clsLEAMDNSHost::clsSendParameter& 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 - clsMsgHeader msgHeader(p_rSendParameter.m_u16ID, - (static_cast(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 = ((clsSendParameter::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(enuSequence::Count); ((bResult) && (sequence <= static_cast(enuSequence::Send))); ++sequence) - { - /* - DEBUG_EX_INFO( - if (static_cast(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(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 (clsRRQuestion::list::iterator it = p_rSendParameter.m_RRQuestions.begin(); ((bResult) && (it != p_rSendParameter.m_RRQuestions.end())); it++) - { - clsRRQuestion* pQuestion = *it; - - ((static_cast(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(enuContentFlag::A)) && - (_getResponderIPAddress(pNetIf, enuIPProtocolType::V4).isSet())) - { - - u32NSECContent |= static_cast(enuContentFlag::A); - ((static_cast(enuSequence::Count) == sequence) - ? ++ru16Answers - : (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(enuContentFlag::PTR_IPv4)) && - (_getResponderIPAddress(pNetIf, enuIPProtocolType::V4).isSet())) - { - - u32NSECContent |= static_cast(enuContentFlag::PTR_IPv4); - ((static_cast(enuSequence::Count) == sequence) - ? ++ru16Answers - : (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 -#ifdef MDNS2_IPV6_SUPPORT - // AAAA - if ((bResult) && - (p_rSendParameter.m_u32HostReplyMask & static_cast(enuContentFlag::AAAA)) && - (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)).isSet())) - { - - u32NSECContent |= static_cast(enuContentFlag::AAAA); - ((static_cast(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());); - } - // PTR_IPv6 - if ((bResult) && - (p_rSendParameter.m_u32HostReplyMask & static_cast(enuContentFlag::PTR_IPv6)) && - (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)).isSet())) - { - - u32NSECContent |= static_cast(enuContentFlag::PTR_IPv6); - ((static_cast(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());); - } -#endif - - 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(enuContentFlag::PTR_TYPE))) - { - ((static_cast(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(enuContentFlag::PTR_NAME))) - { - ((static_cast(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(enuContentFlag::SRV))) - { - ((static_cast(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(enuContentFlag::TXT))) - { - ((static_cast(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 MDNS2_IPV6_SUPPORT - bool bNeedsAdditionalAnswerAAAA = false; -#endif - for (clsService::list::iterator it = m_Services.begin(); ((bResult) && (it != m_Services.end())); it++) - { - clsService* pService = *it; - - if ((bResult) && - (pService->m_u32ReplyMask & static_cast(enuContentFlag::PTR_NAME)) && // If PTR_NAME is requested, AND - (!(pService->m_u32ReplyMask & static_cast(enuContentFlag::SRV)))) // NOT SRV -> add SRV as additional answer - { - - ((static_cast(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(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(enuContentFlag::PTR_NAME) | static_cast(enuContentFlag::SRV))) || // If service instance name or SRV OR - (p_rSendParameter.m_u32HostReplyMask & (static_cast(enuContentFlag::A) | static_cast(enuContentFlag::AAAA)))) // any host IP address is requested - { -#ifdef MDNS_IPV4_SUPPORT - if ((bResult) && - (!(p_rSendParameter.m_u32HostReplyMask & static_cast(enuContentFlag::A)))) // Add IPv4 address - { - bNeedsAdditionalAnswerA = true; - } -#endif -#ifdef MDNS2_IPV6_SUPPORT - if ((bResult) && - (!(p_rSendParameter.m_u32HostReplyMask & static_cast(enuContentFlag::AAAA)))) // Add IPv6 address - { - bNeedsAdditionalAnswerAAAA = true; - } -#endif - } - // NSEC record for service - if ((bResult) && - (pService->m_u32ReplyMask) && - ((clsSendParameter::enuResponseType::None != p_rSendParameter.m_Response))) - { - ((static_cast(enuSequence::Count) == sequence) - ? ++ru16AdditionalAnswers - : (bResult = _writeMDNSAnswer_NSEC(*pService, (static_cast(enuContentFlag::TXT) | static_cast(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(pNetIf, (enuIPProtocolType::V4)).isSet())) - { - // Additional A - u32NSECContent |= static_cast(enuContentFlag::A); - ((static_cast(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());); - } -#endif -#ifdef MDNS2_IPV6_SUPPORT - // Answer AAAA needed? - if ((bResult) && - (bNeedsAdditionalAnswerAAAA) && - (_getResponderIPAddress(pNetIf, (enuIPProtocolType::V6)).isSet())) - { - // Additional AAAA - u32NSECContent |= static_cast(enuContentFlag::AAAA); - ((static_cast(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());); - } -#endif - - // 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 -#ifdef MDNS_IPV4_SUPPORT - uint32_t u32NSECContent_PTR_IPv4 = (u32NSECContent & static_cast(enuContentFlag::PTR_IPv4)); - u32NSECContent &= ~static_cast(enuContentFlag::PTR_IPv4); -#endif -#ifdef MDNS2_IPV6_SUPPORT - uint32_t u32NSECContent_PTR_IPv6 = (u32NSECContent & static_cast(enuContentFlag::PTR_IPv6)); - u32NSECContent &= ~static_cast(enuContentFlag::PTR_IPv6); -#endif - - ((static_cast(enuSequence::Count) == sequence) - ? (ru16AdditionalAnswers += ((u32NSECContent ? 1 : 0) -#ifdef MDNS_IPV4_SUPPORT - + (u32NSECContent_PTR_IPv4 ? 1 : 0) -#endif -#ifdef MDNS2_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(pNetIf, (enuIPProtocolType::V4)).isSet()) || - (_writeMDNSAnswer_NSEC_PTR_IPv4(_getResponderIPAddress(pNetIf, (enuIPProtocolType::V4)), p_rSendParameter)))) -#endif -#ifdef MDNS2_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)))) -#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::_addQueryRecord - - 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 bResult = false; - - clsRRQuestion* pNewRRQuestion = new clsRRQuestion; - if ((bResult = (0 != pNewRRQuestion))) - { - // Link to list of questions - p_rSendParameter.m_RRQuestions.push_back(pNewRRQuestion); - - pNewRRQuestion->m_Header.m_Domain = p_QueryDomain; - - pNewRRQuestion->m_Header.m_Attributes.m_u16Type = p_u16RecordType; - // It seems, that some mDNS implementations don't support 'unicast response' questions... - pNewRRQuestion->m_Header.m_Attributes.m_u16Class = (/*0x8000 |*/ DNS_RRCLASS_IN); // /*Unicast &*/ INternet - } - return bResult; -} - -/* - MDNSResponder::_sendQuery - - Creates and sends a query for the given domain and query type. - -*/ -bool clsLEAMDNSHost::_sendQuery(const clsLEAMDNSHost::clsQuery& p_Query, - clsLEAMDNSHost::clsQuery::clsAnswer::list* p_pKnownAnswers /*= 0*/) -{ - bool bResult = false; - - clsSendParameter sendParameter; - switch (p_Query.m_QueryType) - { - case clsQuery::enuQueryType::Host: -#ifdef MDNS_IPV4_SUPPORT - bResult = _addQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_A); -#endif -#ifdef MDNS2_IPV6_SUPPORT - bResult = _addQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_AAAA); -#endif - break; - - case clsQuery::enuQueryType::Service: - bResult = _addQueryRecord(sendParameter, p_Query.m_Domain, DNS_RRTYPE_PTR); - break; - - case clsQuery::enuQueryType::None: - default: - break; - } - - // TODO: Add known answers to query - (void)p_pKnownAnswers; - bResult = ((bResult) && - (_sendMessage(sendParameter))); - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _sendQuery: FAILED!\n"), _DH());); - return bResult; -} - -/* - MDNSResponder::_sendQuery - - Creates and sends a query for the given domain and record type. - -*/ -bool clsLEAMDNSHost::_sendQuery(const clsLEAMDNSHost::clsRRDomain& p_QueryDomain, - uint16_t p_u16RecordType, - clsLEAMDNSHost::clsQuery::clsAnswer::list* p_pKnownAnswers /*= 0*/) -{ - bool bResult = false; - - 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 _sendQuery: FAILED!\n"), _DH());); - return bResult; -} - -/* - MDNSResponder::_getResponderIPAddress -*/ -IPAddress clsLEAMDNSHost::_getResponderIPAddress(netif* pNetIf, enuIPProtocolType p_IPProtocolType) const -{ - IPAddress ipResponder; -#ifdef MDNS_IPV4_SUPPORT - if (enuIPProtocolType::V4 == p_IPProtocolType) - { - ipResponder = netif_ip_addr4(pNetIf); - } -#endif -#ifdef MDNS2_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(&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(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; - } - } - 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 clsLEAMDNSHost::_readRRQuestion(clsLEAMDNSHost::clsRRQuestion& 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 clsLEAMDNSHost::_readRRAnswer(clsLEAMDNSHost::clsRRAnswer*& p_rpRRAnswer) -{ - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer\n"));); - - bool bResult = false; - - 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); - 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 clsRRAnswerA(header, u32TTL); - bResult = _readRRAnswerA(*(clsRRAnswerA*&)p_rpRRAnswer, u16RDLength); - break; -#endif - case DNS_RRTYPE_PTR: - p_rpRRAnswer = new clsRRAnswerPTR(header, u32TTL); - bResult = _readRRAnswerPTR(*(clsRRAnswerPTR*&)p_rpRRAnswer, u16RDLength); - break; - case DNS_RRTYPE_TXT: - p_rpRRAnswer = new clsRRAnswerTXT(header, u32TTL); - bResult = _readRRAnswerTXT(*(clsRRAnswerTXT*&)p_rpRRAnswer, u16RDLength); - break; -#ifdef MDNS2_IPV6_SUPPORT - case DNS_RRTYPE_AAAA: - p_rpRRAnswer = new clsRRAnswerAAAA(header, u32TTL); - bResult = _readRRAnswerAAAA(*(clsRRAnswerAAAA*&)p_rpRRAnswer, u16RDLength); - break; -#endif - case DNS_RRTYPE_SRV: - p_rpRRAnswer = new clsRRAnswerSRV(header, u32TTL); - bResult = _readRRAnswerSRV(*(clsRRAnswerSRV*&)p_rpRRAnswer, u16RDLength); - break; - default: - p_rpRRAnswer = new clsRRAnswerGeneric(header, u32TTL); - bResult = _readRRAnswerGeneric(*(clsRRAnswerGeneric*&)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"), ((clsRRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str()); - break; -#endif - case DNS_RRTYPE_PTR: - DEBUG_OUTPUT.printf_P(PSTR("PTR ")); - _printRRDomain(((clsRRAnswerPTR*&)p_rpRRAnswer)->m_PTRDomain); - break; - case DNS_RRTYPE_TXT: - { - size_t stTxtLength = ((clsRRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_strLength(); - char* pTxts = new char[stTxtLength]; - if (pTxts) - { - ((clsRRAnswerTXT*&)p_rpRRAnswer)->m_Txts.c_str(pTxts); - DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts); - delete[] pTxts; - } - break; - } -#ifdef MDNS2_IPV6_SUPPORT - case DNS_RRTYPE_AAAA: - 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 "), ((clsRRAnswerSRV*&)p_rpRRAnswer)->m_u16Port); - _printRRDomain(((clsRRAnswerSRV*&)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")); - }); // 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_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswer: FAILED!\n"), _DH());); - return bResult; -} - -#ifdef MDNS_IPV4_SUPPORT -/* - MDNSResponder::_readRRAnswerA -*/ -bool clsLEAMDNSHost::_readRRAnswerA(clsLEAMDNSHost::clsRRAnswerA& p_rRRAnswerA, - uint16_t p_u16RDLength) -{ - uint32_t u32IPv4Address; - 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; -} -#endif - -/* - MDNSResponder::_readRRAnswerPTR -*/ -bool clsLEAMDNSHost::_readRRAnswerPTR(clsLEAMDNSHost::clsRRAnswerPTR& 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 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; - - 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; - - clsServiceTxt* pTxt = 0; - unsigned char ucLength = *pucCursor++; // Length of the next txt item - if (ucLength) - { - DEBUG_EX_INFO( - char sacBuffer[64]; - *sacBuffer = 0; - uint8_t u8MaxLength = ((ucLength > (sizeof(sacBuffer) - 1)) ? (sizeof(sacBuffer) - 1) : ucLength); - 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); - ); - - 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 clsServiceTxt)) && - (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: INFO! TXT answer contains no items.\n"), _DH());); - bResult = true; - } - - if ((bResult) && - (pTxt)) - { - // Everythings fine so far - // Link TXT item to answer TXTs - p_rRRAnswerTXT.m_Txts.add(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_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("%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 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 MDNS2_IPV6_SUPPORT -bool clsLEAMDNSHost::_readRRAnswerAAAA(clsLEAMDNSHost::clsRRAnswerAAAA& p_rRRAnswerAAAA, - uint16_t p_u16RDLength) -{ - bool bResult = false; - - uint32_t au32IPv6Address[4]; // 16 bytes - 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); - } - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _readRRAnswerAAAA: FAILED!\n"), _DH());); - return bResult; -} -#endif - -/* - MDNSResponder::_readRRAnswerSRV -*/ -bool clsLEAMDNSHost::_readRRAnswerSRV(clsLEAMDNSHost::clsRRAnswerSRV& 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 clsLEAMDNSHost::_readRRAnswerGeneric(clsLEAMDNSHost::clsRRAnswerGeneric& 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 clsLEAMDNSHost::_readRRHeader(clsLEAMDNSHost::clsRRHeader& 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 clsLEAMDNSHost::_readRRDomain(clsLEAMDNSHost::clsRRDomain& 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 clsConsts::u8DomainMaxRedirections. - -*/ -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 (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_pUDPContext->tell(), m_pUDPContext->peek());); - _udpRead8(u8Len); - - if (u8Len & clsConsts::u8DomainCompressMark) - { - // Compressed label(s) - uint16_t u16Offset = ((u8Len & ~clsConsts::u8DomainCompressMark) << 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("%s _readRRDomain_Loop(%u): Redirecting from %u to %u!\n"), _DH(), 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("%s _readRRDomain_Loop(%u): Succeeded to read redirected label! Returning to %u\n"), _DH(), p_u8Depth, stCurrentPosition);); - m_pUDPContext->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 (clsConsts::stDomainMaxLength > (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_pUDPContext->tell(), m_pUDPContext->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 clsLEAMDNSHost::_readRRAttributes(clsLEAMDNSHost::clsRRAttributes& 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 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(clsConsts::pcLocal)) && - (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 clsLEAMDNSHost::_buildDomainForDNSSD(clsLEAMDNSHost::clsRRDomain& p_rDNSSDDomain) const -{ - p_rDNSSDDomain.clear(); - 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; -} - -/* - MDNSResponder::_buildDomainForService - - Builds the domain for the given service (eg. _http._tcp.local or - MyESP._http._tcp.local (if p_bIncludeName is set)). - -*/ -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.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; -} - -/* - 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 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(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; -} - -#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 clsLEAMDNSHost::_buildDomainForReverseIPv4(IPAddress p_IPv4Address, - clsLEAMDNSHost::clsRRDomain& p_rReverseIPv4Domain) const -{ - bool bResult = ((p_IPv4Address.isSet()) && - (p_IPv4Address.isV4())); - - p_rReverseIPv4Domain.clear(); - - char acBuffer[32]; - 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(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; -} -#endif - -#ifdef MDNS2_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 clsLEAMDNSHost::_buildDomainForReverseIPv6(IPAddress p_IPv6Address, - clsLEAMDNSHost::clsRRDomain& 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 = (clsConsts::u16IPv6Size / 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(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; -} -#endif - - -/* - - UDP - -*/ - -/* - MDNSResponder::_udpReadBuffer - -*/ -bool clsLEAMDNSHost::_udpReadBuffer(unsigned char* p_pBuffer, - size_t p_stLength) -{ - bool bResult = ((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("%s _udpReadBuffer: FAILED!\n"), _DH());); - return bResult; -} - -/* - MDNSResponder::_udpRead8 - -*/ -bool clsLEAMDNSHost::_udpRead8(uint8_t& p_ru8Value) -{ - return _udpReadBuffer((unsigned char*)&p_ru8Value, sizeof(p_ru8Value)); -} - -/* - MDNSResponder::_udpRead16 - -*/ -bool clsLEAMDNSHost::_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 clsLEAMDNSHost::_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 clsLEAMDNSHost::_udpAppendBuffer(const unsigned char* p_pcBuffer, - size_t p_stLength) -{ - bool bResult = ((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 clsLEAMDNSHost::_udpAppend8(uint8_t p_u8Value) -{ - return (_udpAppendBuffer((unsigned char*)&p_u8Value, sizeof(p_u8Value))); -} - -/* - MDNSResponder::_udpAppend16 - -*/ -bool clsLEAMDNSHost::_udpAppend16(uint16_t p_u16Value) -{ - p_u16Value = lwip_htons(p_u16Value); - return (_udpAppendBuffer((unsigned char*)&p_u16Value, sizeof(p_u16Value))); -} - -/* - MDNSResponder::_udpAppend32 - -*/ -bool clsLEAMDNSHost::_udpAppend32(uint32_t p_u32Value) -{ - p_u32Value = lwip_htonl(p_u32Value); - return (_udpAppendBuffer((unsigned char*)&p_u32Value, sizeof(p_u32Value))); -} - -#ifdef DEBUG_ESP_PORT -/* - MDNSResponder::_udpDump - -*/ -bool clsLEAMDNSHost::_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 clsLEAMDNSHost::_udpDump(unsigned p_uOffset, - unsigned p_uLength) -{ - if (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 // DEBUG_ESP_PORT - - -/** - 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 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 - -*/ -bool clsLEAMDNSHost::_readMDNSMsgHeader(clsLEAMDNSHost::clsMsgHeader& 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/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 - 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 clsLEAMDNSHost::_write8(uint8_t p_u8Value, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) -{ - return ((_udpAppend8(p_u8Value)) && - (p_rSendParameter.shiftOffset(sizeof(p_u8Value)))); -} - -/* - MDNSResponder::_write16 - -*/ -bool clsLEAMDNSHost::_write16(uint16_t p_u16Value, - clsLEAMDNSHost::clsSendParameter& p_rSendParameter) -{ - return ((_udpAppend16(p_u16Value)) && - (p_rSendParameter.shiftOffset(sizeof(p_u16Value)))); -} - -/* - MDNSResponder::_write32 - -*/ -bool clsLEAMDNSHost::_write32(uint32_t p_u32Value, - clsLEAMDNSHost::clsSendParameter& 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 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 - -*/ -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(), - (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 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))); - - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSRRAttributes: FAILED!\n"), _DH());); - return bResult; -} - -/* - MDNSResponder::_writeMDNSRRDomain - -*/ -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))); - - 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 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); - - clsRRDomain hostDomain; - bool bResult = (u16CachedDomainOffset - // Found cached domain -> mark as compressed domain - ? ((clsConsts::u8DomainCompressMark > ((u16CachedDomainOffset >> 8) & ~clsConsts::u8DomainCompressMark)) && // Valid offset - ((!p_bPrependRDLength) || - (_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 - ((!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 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); - - clsRRDomain serviceDomain; - bool bResult = (u16CachedDomainOffset - // Found cached domain -> mark as compressed domain - ? ((clsConsts::u8DomainCompressMark > ((u16CachedDomainOffset >> 8) & ~clsConsts::u8DomainCompressMark)) && // Valid offset - ((!p_bPrependRDLength) || - (_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 - ((!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 clsLEAMDNSHost::_writeMDNSQuestion(clsLEAMDNSHost::clsRRQuestion& p_Question, - clsLEAMDNSHost::clsSendParameter& 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 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"));); - - clsRRAttributes attributes(DNS_RRTYPE_A, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - 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_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"), - _DH(), - m_pcHostName, - _RRType2Name(attributes.m_u16Type), - attributes.m_u16Class, - (p_rSendParameter.m_bUnannounce - ? 0 - : (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());); - 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 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"));); - - clsRRDomain reverseIPv4Domain; - clsRRAttributes attributes(DNS_RRTYPE_PTR, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - 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_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) - 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_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), - 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 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"));); - - 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_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) - 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_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());); - 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 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());); - - 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_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_pcType, - p_rService.m_pcProtocol, - _RRType2Name(attributes.m_u16Type), - 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); - ); - 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 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; - - clsRRAttributes 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_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 - if (p_rService.m_Txts.count()) - { - 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_pcInstanceName, - p_rService.m_pcType, - p_rService.m_pcProtocol, - _RRType2Name(attributes.m_u16Type), - attributes.m_u16Class, - (p_rSendParameter.m_bUnannounce - ? 0 - : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL))); - ); - - _releaseTempServiceTxts(p_rService); - - DEBUG_EX_ERR(if (!bResult) DEBUG_OUTPUT.printf_P(PSTR("%s _writeMDNSAnswer_TXT: FAILED!\n"), _DH());); - return bResult; -} - -#ifdef MDNS2_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 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"));); - - 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_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"), - _DH(), - m_pcHostName, - _RRType2Name(attributes.m_u16Type), - attributes.m_u16Class, - (p_rSendParameter.m_bUnannounce - ? 0 - : (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());); - 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 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"));); - - 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 - (_writeMDNSRRDomain(reverseIPv6Domain, p_rSendParameter)) && - (_writeMDNSRRAttributes(attributes, p_rSendParameter)) && // TYPE & CLASS - (_write32((p_rSendParameter.m_bUnannounce - ? 0 - : (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) - 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_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), - 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 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_bLegacyDNSQuery - ? 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 - 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_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL/*Consts::u32ServiceTTL*/)), 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(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 - : ((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(clsConsts::u16SRVPriority, p_rSendParameter)) && // Priority - (_write16(clsConsts::u16SRVWeight, p_rSendParameter)) && // Weight - (_write16(p_rService.m_u16Port, p_rSendParameter)) && // Port - (_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_pcInstanceName, - p_rService.m_pcType, - p_rService.m_pcProtocol, - _RRType2Name(attributes.m_u16Type), - attributes.m_u16Class, - (p_rSendParameter.m_bUnannounce - ? 0 - : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), - clsConsts::u16SRVPriority, - clsConsts::u16SRVWeight, - 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 - -*/ -clsLEAMDNSHost::clsNSECBitmap* clsLEAMDNSHost::_createNSECBitmap(uint32_t p_u32NSECContent) -{ - // Currently 6 bytes (6*8 -> 0..47) are long enough, and only this is implemented - clsNSECBitmap* pNSECBitmap = new clsNSECBitmap; - if (pNSECBitmap) - { -#ifdef MDNS_IPV4_SUPPORT - if (p_u32NSECContent & static_cast(enuContentFlag::A)) - { - pNSECBitmap->setBit(DNS_RRTYPE_A); // 01/0x01 - } -#endif - if ((p_u32NSECContent & static_cast(enuContentFlag::PTR_IPv4)) || - (p_u32NSECContent & static_cast(enuContentFlag::PTR_IPv6))) - { - pNSECBitmap->setBit(DNS_RRTYPE_PTR); // 12/0x0C - } -#ifdef MDNS2_IPV6_SUPPORT - if (p_u32NSECContent & static_cast(enuContentFlag::AAAA)) - { - pNSECBitmap->setBit(DNS_RRTYPE_AAAA); // 28/0x1C - } -#endif - if (p_u32NSECContent & static_cast(enuContentFlag::TXT)) - { - pNSECBitmap->setBit(DNS_RRTYPE_TXT); // 16/0x10 - } - if (p_u32NSECContent & static_cast(enuContentFlag::SRV)) - { - pNSECBitmap->setBit(DNS_RRTYPE_SRV); // 33/0x21 - } - if (p_u32NSECContent & static_cast(enuContentFlag::NSEC)) - { - pNSECBitmap->setBit(clsConsts::u8DNS_RRTYPE_NSEC); // 47/0x2F - } - } - return pNSECBitmap; -} - -/* - MDNSResponder::_writeMDNSNSECBitmap - -*/ -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; ulength()), 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_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32HostTTL)), - 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 xyz - http://www.zytrax.com/books/dns/ch8/nsec.html - -*/ -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"));); - - clsRRAttributes attributes(clsConsts::u8DNS_RRTYPE_NSEC, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - clsNSECBitmap* pNSECBitmap = _createNSECBitmap(static_cast(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 - (_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_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 - - 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_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL))); - _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 MDNS2_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 xyz - http://www.zytrax.com/books/dns/ch8/nsec.html - -*/ -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"));); - - clsRRAttributes attributes(clsConsts::u8DNS_RRTYPE_NSEC, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - clsNSECBitmap* pNSECBitmap = _createNSECBitmap(static_cast(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 - (_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_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 - - 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_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL))); - _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 xyz - http://www.zytrax.com/books/dns/ch8/nsec.html - -*/ -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));); - - clsRRAttributes attributes(clsConsts::u8DNS_RRTYPE_NSEC, - ((p_rSendParameter.m_bCacheFlush ? 0x8000 : 0) | DNS_RRCLASS_IN)); // Cache flush? & INternet - 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_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_pcInstanceName, - p_rService.m_pcType, - p_rService.m_pcProtocol, - _RRType2Name(attributes.m_u16Type), - attributes.m_u16Class, - (p_rSendParameter.m_bUnannounce - ? 0 - : (p_rSendParameter.m_bLegacyDNSQuery ? clsConsts::u32LegacyTTL : clsConsts::u32ServiceTTL)), - _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_Backbone.cpp b/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp deleted file mode 100644 index 87f263eff5..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Backbone.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* - 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 "ESP8266mDNS.h" -#include "LEAmDNS2Host.h" -#include "LEAmDNS2_Priv.h" - -namespace esp8266 -{ - - -namespace experimental -{ - - -/* - clsLEAmDNS2_Host::clsBackbone::clsBackbone constructor - -*/ -clsLEAMDNSHost::clsBackbone::clsBackbone(void) - : m_pUDPContext(0), - m_bDelayUDPProcessing(false), - m_u32DelayedDatagrams(0), - m_uniqueHost(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 = nullptr; - - if ((m_pUDPContext) && (p_pHost) && (m_uniqueHost == nullptr)) - { - 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"));); - return pUDPContext; -} - -/* - clsLEAmDNS2_Host::clsBackbone::removeHost - -*/ -bool clsLEAMDNSHost::clsBackbone::removeHost(clsLEAMDNSHost* p_pHost) -{ - bool bResult = false; - - if ((p_pHost) && (m_uniqueHost == 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"));); - return bResult; -} - - -/* - clsLEAmDNS2_Host::clsBackbone::hostCount - -*/ -size_t clsLEAMDNSHost::clsBackbone::hostCount(void) const -{ - return m_uniqueHost == nullptr ? 0 : 1; -} - -/* - 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 = nullptr; - } - 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) - { - while ((m_pUDPContext) && - (m_pUDPContext->next())) - { - clsLEAMDNSHost* pHost = _findHost(); - - 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(); - } - } - else - { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Delaying datagram!\n"), _DH());); - ++m_u32DelayedDatagrams; - } - return bResult; -} - -/* - MISC -*/ - -#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_PORT - -/* - clsLEAmDNS2_Host::clsBackbone::_DH -*/ -const char* clsLEAMDNSHost::clsBackbone::_DH(void) const -{ - static char acBuffer[20] = { 0, }; - if (!acBuffer[0]) - { - strcpy_P(acBuffer, PSTR("[mDNS::backbone]")); - } - return acBuffer; -} - -#endif - -} // namespace MDNSImplementation - - -} // namespace esp8266 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h b/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h deleted file mode 100644 index 312a03d045..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_Priv.h +++ /dev/null @@ -1,115 +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 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 // force debug, arduino IDE uses DEBUG_ESP_MDNS - -/* - 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) || 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_PORT -#define DEBUG_OUTPUT DEBUG_ESP_PORT -#else -#define DEBUG_OUTPUT Serialx -#endif - -#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) 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 - -/* - 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 diff --git a/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h b/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h deleted file mode 100644 index a24cf62ba1..0000000000 --- a/libraries/ESP8266mDNS/src/LEAmDNS2_lwIPdefs.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - 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 -#include // DNS_RRTYPE_xxx, DNS_MQUERY_PORT - -#endif // LEAMDNS2_LWIPDEFS_H diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp index bc8cb3a698..677456fcc5 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp @@ -97,8 +97,8 @@ bool MDNSResponder::_process(bool p_bUserContext) bool MDNSResponder::_restart(void) { - return ((_resetProbeStatus(true)) && // Stop and restart probing - (_allocUDPContext())); // Restart UDP + return ((_resetProbeStatus(true/*restart*/)) && // Stop and restart probing + (_allocUDPContext())); // Restart UDP } /** diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Priv.h b/libraries/ESP8266mDNS/src/LEAmDNS_Priv.h index 4750669d38..a7d8a8f998 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Priv.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Priv.h @@ -94,13 +94,12 @@ namespace MDNSImplementation #define DEBUG_EX_RX(A) do { (void)0; } while (0) #endif - -/* Replaced by 'lwip/prot/dns.h' definitions +/* already defined in lwIP ('lwip/prot/dns.h') #ifdef MDNS_IP4_SUPPORT - #define MDNS_MULTICAST_ADDR_IP4 (IPAddress(224, 0, 0, 251)) // ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT + #define DNS_MQUERY_IPV4_GROUP_INIT (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 + #define DNS_MQUERY_IPV6_GROUP_INIT IPADDR6_INIT_HOST(0xFF020000,0,0,0xFB) // ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT #endif*/ //#define MDNS_MULTICAST_PORT 5353 diff --git a/tests/host/Makefile b/tests/host/Makefile index b7314a6d41..45b87522fc 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -329,12 +329,6 @@ OPT_ARDUINO_LIBS ?= \ 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 \