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 \ pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy