From 3b4df8c34bdd54e65a27d3cf69ae77e3245ba6f2 Mon Sep 17 00:00:00 2001 From: LaborEtArs Date: Mon, 14 Jan 2019 20:06:22 +0100 Subject: [PATCH 1/3] Fixes 1.1 - Better separation of ESP wifi thread code from user thread code - Added a flag for 'update()'-less use (disabled by default) - The too fast updates for service queries are fixed - Switched fully to PolledTimeout; LEATimeFlag not needed anymore (BTW: a const 'expired()' method would be helpful) - The device should stay visible now even after the first TTL timeout - Improved service querying (queries five times now) --- libraries/ESP8266mDNS/src/LEATimeFlag.h | 60 -- libraries/ESP8266mDNS/src/LEAmDNS.cpp | 21 +- libraries/ESP8266mDNS/src/LEAmDNS.h | 66 ++- libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp | 525 +++++++++++------- libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp | 1 + libraries/ESP8266mDNS/src/LEAmDNS_Priv.h | 19 +- libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp | 149 ++++- .../ESP8266mDNS/src/LEAmDNS_Transfer.cpp | 16 +- 8 files changed, 531 insertions(+), 326 deletions(-) delete mode 100644 libraries/ESP8266mDNS/src/LEATimeFlag.h diff --git a/libraries/ESP8266mDNS/src/LEATimeFlag.h b/libraries/ESP8266mDNS/src/LEATimeFlag.h deleted file mode 100644 index e0eb3b4cee..0000000000 --- a/libraries/ESP8266mDNS/src/LEATimeFlag.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * LEATimeFlag.h - */ -#ifndef __MDNSTIMEFLAG_H -#define __MDNSTIMEFLAG_H - - -#include -#include - - -/* Wrapper class around PolledTimeout - * MDNS requires behavior that is slightly different from the default in PolledTimeout - */ -class clsMDNSTimeFlag { -protected: - using oneShot = esp8266::polledTimeout::oneShot; - oneShot m_clsPolledTimeout; - -public: - using timeType = oneShot::timeType; - - clsMDNSTimeFlag(timeType p_Timeout) - : m_clsPolledTimeout(p_Timeout) { - } - clsMDNSTimeFlag() - : m_clsPolledTimeout(std::numeric_limits::max()) { - } - - operator bool() const { - return flagged(); - } - - bool flagged() const { - return m_clsPolledTimeout.checkExpired(millis()); - } - - void restart() { - m_clsPolledTimeout.reset(); - } - - void restart(const timeType p_Timeout) { - m_clsPolledTimeout.reset(p_Timeout); - } - - void reset() { - m_clsPolledTimeout.reset(std::numeric_limits::max()); - } - - timeType getTimeout() const { - return m_clsPolledTimeout.getTimeout(); - } - - bool hypotheticalTimeout(const timeType p_Timeout) const { - return m_clsPolledTimeout.checkExpired(p_Timeout); - } -}; - - -#endif // __MDNSTIMEFLAG_H diff --git a/libraries/ESP8266mDNS/src/LEAmDNS.cpp b/libraries/ESP8266mDNS/src/LEAmDNS.cpp index 638853388d..a88d46c6af 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS.cpp @@ -55,7 +55,12 @@ MDNSResponder::MDNSResponder(void) m_pcHostname(0), m_pServiceQueries(0), m_fnServiceTxtCallback(0), - m_pServiceTxtCallbackUserdata(0) { + m_pServiceTxtCallbackUserdata(0), +#ifdef ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE + m_bPassivModeEnabled(true) { +#else + m_bPassivModeEnabled(false) { +#endif } @@ -123,7 +128,7 @@ bool MDNSResponder::begin(const char* p_pcHostname, */ bool MDNSResponder::close(void) { - _announce(false); + _announce(false, true); _resetProbeStatus(false); // Stop probing _releaseServiceQueries(); @@ -205,6 +210,7 @@ MDNSResponder::hMDNSService MDNSResponder::addService(const char* p_pcName, } } } // else: bad arguments + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addService: %s to add '%s.%s.%s'!\n"), (hResult ? "Succeeded" : "FAILED"), (p_pcName ?: "-"), p_pcService, p_pcProtocol); ); DEBUG_EX_ERR(if (!hResult) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] addService: FAILED to add '%s.%s.%s'!\n"), (p_pcName ?: "-"), p_pcService, p_pcProtocol); } ); return hResult; } @@ -768,13 +774,17 @@ MDNSResponder::hMDNSServiceQuery MDNSResponder::installServiceQuery(const char* pServiceQuery->m_bLegacyQuery = false; if (_sendMDNSServiceQuery(*pServiceQuery)) { + pServiceQuery->m_u8SentCount = 1; + pServiceQuery->m_ResendTimeout.reset(MDNS_DYNAMIC_QUERY_RESEND_DELAY); + hResult = (hMDNSServiceQuery)pServiceQuery; } else { _removeServiceQuery(pServiceQuery); } } - DEBUG_EX_ERR(if (!hResult) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] installServiceQuery: FAILED for '%s.%s'!\n"), (p_pcService ?: "-"), (p_pcProtocol ?: "-")); } ); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] installServiceQuery: %s for '%s.%s'!\n\n"), (hResult ? "Succeeded" : "FAILED"), (p_pcService ?: "-"), (p_pcProtocol ?: "-"));); + DEBUG_EX_ERR(if (!hResult) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] installServiceQuery: FAILED for '%s.%s'!\n\n"), (p_pcService ?: "-"), (p_pcProtocol ?: "-")); } ); return hResult; } @@ -1073,6 +1083,9 @@ bool MDNSResponder::notifyAPChange(void) { */ bool MDNSResponder::update(void) { + if (m_bPassivModeEnabled) { + m_bPassivModeEnabled = false; + } return _process(true); } @@ -1083,7 +1096,7 @@ bool MDNSResponder::update(void) { */ bool MDNSResponder::announce(void) { - return (_announce()); + return (_announce(true, true)); } /* diff --git a/libraries/ESP8266mDNS/src/LEAmDNS.h b/libraries/ESP8266mDNS/src/LEAmDNS.h index fc98b541b3..f5a6702707 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS.h @@ -65,7 +65,7 @@ * Reference: * Used mDNS messages: * A (0x01): eg. esp8266.local A OP TTL 123.456.789.012 - * AAAA (01Cx): eg. esp8266.local AAAA OP TTL 1234:5678::90 + * AAAA (0x1C): eg. esp8266.local AAAA OP TTL 1234:5678::90 * PTR (0x0C, srv name): eg. _http._tcp.local PTR OP TTL MyESP._http._tcp.local * PTR (0x0C, srv type): eg. _services._dns-sd._udp.local PTR OP TTL _http._tcp.local * PTR (0x0C, IP4): eg. 012.789.456.123.in-addr.arpa PTR OP TTL esp8266.local @@ -107,7 +107,8 @@ #include "lwip/udp.h" #include "debug.h" #include "include/UdpContext.h" -#include "LEATimeFlag.h" +#include +#include #include "ESP8266WiFi.h" @@ -786,8 +787,9 @@ class MDNSResponder { */ struct stcProbeInformation { enuProbingStatus m_ProbingStatus; - uint8_t m_u8ProbesSent; - clsMDNSTimeFlag m_NextProbeTimeFlag; + uint8_t m_u8SentCount; // Used for probes and announcements + esp8266::polledTimeout::oneShot m_Timeout; // Used for probes and announcements + //clsMDNSTimeFlag m_TimeFlag; // Used for probes and announcements bool m_bConflict; bool m_bTiebreakNeeded; MDNSProbeResultCallbackFn m_fnProbeResultCallback; @@ -842,14 +844,32 @@ class MDNSResponder { * stcTTL */ struct stcTTL { - clsMDNSTimeFlag m_TTLTimeFlag; - bool m_bUpdateScheduled; + /** + * timeoutLevel_t + */ + typedef uint8_t timeoutLevel_t; + /** + * TIMEOUTLEVELs + */ + const timeoutLevel_t TIMEOUTLEVEL_UNSET = 0; + const timeoutLevel_t TIMEOUTLEVEL_BASE = 80; + const timeoutLevel_t TIMEOUTLEVEL_INTERVAL = 5; + const timeoutLevel_t TIMEOUTLEVEL_FINAL = 100; - stcTTL(uint32_t p_u32TTL = 0); + uint32_t m_u32TTL; + esp8266::polledTimeout::oneShot m_TTLTimeout; + timeoutLevel_t m_timeoutLevel; + + stcTTL(void); bool set(uint32_t p_u32TTL); - bool has80Percent(void) const; - bool isOutdated(void) const; + bool flagged(void) const; + bool restart(void); + + bool prepareDeletion(void); + bool finalTimeoutLevel(void) const; + + unsigned long timeout(void) const; }; #ifdef MDNS_IP4_SUPPORT /** @@ -861,7 +881,7 @@ class MDNSResponder { stcTTL m_TTL; stcIP4Address(IPAddress p_IPAddress, - uint32_t p_u32TTL = 0); + uint32_t p_u32TTL = 0); }; #endif #ifdef MDNS_IP6_SUPPORT @@ -872,6 +892,9 @@ class MDNSResponder { stcIP6Address* m_pNext; IP6Address m_IPAddress; stcTTL m_TTL; + + stcIP6Address(IPAddress p_IPAddress, + uint32_t p_u32TTL = 0); }; #endif @@ -932,13 +955,15 @@ class MDNSResponder { #endif }; - stcMDNSServiceQuery* m_pNext; - stcMDNS_RRDomain m_ServiceTypeDomain; // eg. _http._tcp.local - MDNSServiceQueryCallbackFn m_fnCallback; - void* m_pUserdata; - bool m_bLegacyQuery; - bool m_bAwaitingAnswers; - stcAnswer* m_pAnswers; + stcMDNSServiceQuery* m_pNext; + stcMDNS_RRDomain m_ServiceTypeDomain; // eg. _http._tcp.local + MDNSServiceQueryCallbackFn m_fnCallback; + void* m_pUserdata; + bool m_bLegacyQuery; + uint8_t m_u8SentCount; + esp8266::polledTimeout::oneShot m_ResendTimeout; + bool m_bAwaitingAnswers; + stcAnswer* m_pAnswers; stcMDNSServiceQuery(void); ~stcMDNSServiceQuery(void); @@ -1012,6 +1037,7 @@ class MDNSResponder { WiFiEventHandler m_GotIPHandler; MDNSDynamicServiceTxtCallbackFn m_fnServiceTxtCallback; void* m_pServiceTxtCallbackUserdata; + bool m_bPassivModeEnabled; stcProbeInformation m_HostProbeInformation; /** CONTROL **/ @@ -1047,7 +1073,8 @@ class MDNSResponder { bool _cancelProbingForService(stcMDNSService& p_rService); /* ANNOUNCE */ - bool _announce(bool p_bAnnounce = true); + bool _announce(bool p_bAnnounce, + bool p_bIncludeServices); bool _announceService(stcMDNSService& p_rService, bool p_bAnnounce = true); @@ -1064,7 +1091,8 @@ class MDNSResponder { IPAddress p_IPAddress); bool _sendMDNSServiceQuery(const stcMDNSServiceQuery& p_ServiceQuery); bool _sendMDNSQuery(const stcMDNS_RRDomain& p_QueryDomain, - uint16_t p_u16QueryType); + uint16_t p_u16QueryType, + stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers = 0); IPAddress _getResponseMulticastInterface(int p_iWiFiOpModes) const; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp index 1328e14892..507c43b1ec 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp @@ -59,30 +59,29 @@ namespace MDNSImplementation { /* * MDNSResponder::_process * - * Run the MDNS process. Should be called in every 'loop'. + * Run the MDNS process. + * Is called, every time the UDPContext receives data AND + * should be called in every 'loop' by calling 'MDNS::update()'. * */ bool MDNSResponder::_process(bool p_bUserContext) { bool bResult = true; - if ((m_pUDPContext) && // UDPContext available AND - (m_pUDPContext->next())) { // has content - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _update: Calling _parseMessage\n"));); + if (!p_bUserContext) { - bResult = _parseMessage(); - if (p_bUserContext) { - esp_yield(); + if ((m_pUDPContext) && // UDPContext available AND + (m_pUDPContext->next())) { // has content + + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _update: Calling _parseMessage\n"));); + bResult = _parseMessage(); + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parsePacket %s\n"), (bResult ? "succeeded" : "FAILED"));); } - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parsePacket %s\n"), (bResult ? "succeeded" : "FAILED"));); } - else if (p_bUserContext) { - if (bResult) { // Probing - bResult = _updateProbeStatus(); - } - if (bResult) { // Service query cache check - bResult = _checkServiceQueryCache(); - } + else { + bResult = ((WiFi.isConnected()) && // Has connection? + (_updateProbeStatus()) && // Probing + (_checkServiceQueryCache())); // Service query cache check } return bResult; } @@ -173,10 +172,11 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea if ((bResult = _readRRQuestion(questionRR))) { // Define host replies, BUT only answer queries after probing is done u8HostOrServiceReplies = - sendParameter.m_u8HostReplyMask = ((ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus) + sendParameter.m_u8HostReplyMask |= (((m_bPassivModeEnabled) || + (ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus)) ? _replyMaskForHost(questionRR.m_Header, 0) : 0); - DEBUG_EX_INFO(if (u8HostOrServiceReplies) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Host reply needed %u\n"), u8HostOrServiceReplies); }); + DEBUG_EX_INFO(if (u8HostOrServiceReplies) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Host reply needed 0x%X\n"), u8HostOrServiceReplies); }); // Check tiebreak need for host domain if (ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) { @@ -197,15 +197,12 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea // Define service replies for (stcMDNSService* pService=m_pServices; pService; pService=pService->m_pNext) { // Define service replies, BUT only answer queries after probing is done - uint8_t u8ReplyMaskForQuestion = ((ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus) + uint8_t u8ReplyMaskForQuestion = (((m_bPassivModeEnabled) || + (ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus)) ? _replyMaskForService(questionRR.m_Header, *pService, 0) : 0); u8HostOrServiceReplies |= (pService->m_u8ReplyMask |= u8ReplyMaskForQuestion); - DEBUG_EX_INFO(if (u8ReplyMaskForQuestion) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service reply needed for (%s.%s.%s): %u (%s)\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, u8ReplyMaskForQuestion, IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str()); } ); - /*if ((u8ReplyMaskForQuestion) && - (0 == strcmp("hap", pService->m_pcService))) { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service reply needed for (%s.%s.%s): %u (%s)\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, u8ReplyMaskForQuestion, IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str()); - }*/ + DEBUG_EX_INFO(if (u8ReplyMaskForQuestion) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Service reply needed for (%s.%s.%s): 0x%X (%s)\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, u8ReplyMaskForQuestion, IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str()); } ); // Check tiebreak need for service domain if (ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) { @@ -227,7 +224,7 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea // 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 + (questionRR.m_bUnicast)) && // Expressivly unicast query (!sendParameter.m_bUnicast)) { sendParameter.m_bUnicast = true; @@ -272,7 +269,6 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea else { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: FAILED to read question!\n"));); } - //*esp_yield(); } // for questions //DEBUG_EX_INFO(if (u8HostOrServiceReplies) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Reply needed: %u (%s: %s->%s)\n"), u8HostOrServiceReplies, clsTimeSyncer::timestr(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str(), IPAddress(m_pUDPContext->getDestAddress()).toString().c_str()); } ); @@ -386,11 +382,7 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea if ((u8ServiceMatchMask) && // The RR in the known answer matches an RR we are planning to send, AND ((MDNS_SERVICE_TTL / 2) <= pKnownRRAnswer->m_u32TTL)) { // The TTL of the known answer is longer than half of the new service TTL (4500s) - /*if ((0 == strcmp("hap", pService->m_pcService))) { - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Known answer for (%s.%s.%s): %u (%s) %u\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pKnownRRAnswer->answerType(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str(), pKnownRRAnswer->m_u32TTL); - }*/ - - if (AnswerType_PTR == pKnownRRAnswer->answerType()) { + if (AnswerType_PTR == pKnownRRAnswer->answerType()) { stcMDNS_RRDomain serviceDomain; if ((u8ServiceMatchMask & ContentFlag_PTR_TYPE) && (_buildDomainForService(*pService, false, serviceDomain)) && @@ -474,7 +466,6 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea delete pKnownRRAnswer; pKnownRRAnswer = 0; } - //*esp_yield(); } // for answers if (bResult) { @@ -482,22 +473,22 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea uint8_t u8ReplyNeeded = sendParameter.m_u8HostReplyMask; for (stcMDNSService* pService=m_pServices; pService; pService=pService->m_pNext) { u8ReplyNeeded |= pService->m_u8ReplyMask; - - if ((u8ReplyNeeded) && - (0 == strcmp("hap", pService->m_pcService))) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Sending service reply for (%s.%s.%s): %u (%s)\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, u8ReplyNeeded, IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str());); - } } if (u8ReplyNeeded) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Sending answer(%u)...\n"), u8ReplyNeeded);); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Sending answer(0x%X)...\n"), u8ReplyNeeded);); + sendParameter.m_bResponse = true; sendParameter.m_bAuthorative = true; + sendParameter.m_bCacheFlush = false; + bResult = _sendMDNSMessage(sendParameter); } - else { - //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: No reply needed\n"));); - } + DEBUG_EX_INFO( + else { + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: No reply needed\n")); + } + ); } else { DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Something FAILED!\n"));); @@ -569,7 +560,6 @@ bool MDNSResponder::_parseResponse(const MDNSResponder::stcMDNS_MsgHeader& p_Msg for (uint16_t qd=0; ((bResult) && (qdm_pNext; // Next collected answer } // while (answers) - //*esp_yield(); } while ((bFoundNewKeyAnswer) && (bResult)); } // else: No answers provided @@ -756,7 +744,7 @@ bool MDNSResponder::_processPTRAnswer(const MDNSResponder::stcMDNS_RRAnswerPTR* if ((bResult = (0 != p_pPTRAnswer))) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: Processing PTR answers...\n"));); // eg. _http._tcp.local PTR xxxx xx MyESP._http._tcp.local - // Check pending service queries for '_http._tcp' + // Check pending service queries for eg. '_http._tcp' stcMDNSServiceQuery* pServiceQuery = _findNextServiceQueryByServiceType(p_pPTRAnswer->m_Header.m_Domain, 0); while (pServiceQuery) { @@ -767,14 +755,13 @@ bool MDNSResponder::_processPTRAnswer(const MDNSResponder::stcMDNS_RRAnswerPTR* if (p_pPTRAnswer->m_u32TTL) { // Received update message pSQAnswer->m_TTLServiceDomain.set(p_pPTRAnswer->m_u32TTL); // Update TTL tag DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: Updated TTL for ")); + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: Updated TTL(%lu) for "), p_pPTRAnswer->m_u32TTL); _printRRDomain(pSQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR("\n")); ); } - else { // received goodbye-message - pSQAnswer->m_TTLServiceDomain.set(1); // See RFC 6762, 10.1 - pSQAnswer->m_TTLServiceDomain.m_bUpdateScheduled = true; // Avoid 'cache update' query + else { // received goodbye-message + pSQAnswer->m_TTLServiceDomain.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processPTRAnswer: 'Goodbye' received for ")); _printRRDomain(pSQAnswer->m_ServiceDomain); @@ -822,7 +809,7 @@ bool MDNSResponder::_processSRVAnswer(const MDNSResponder::stcMDNS_RRAnswerSRV* if (p_pSRVAnswer->m_u32TTL) { // First or update message (TTL != 0) pSQAnswer->m_TTLHostDomainAndPort.set(p_pSRVAnswer->m_u32TTL); // Update TTL tag DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: Updated TTL for ")); + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: Updated TTL(%lu) for "), p_pSRVAnswer->m_u32TTL); _printRRDomain(pSQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); ); @@ -842,8 +829,7 @@ bool MDNSResponder::_processSRVAnswer(const MDNSResponder::stcMDNS_RRAnswerSRV* } } else { // Goodby message - pSQAnswer->m_TTLHostDomainAndPort.set(1); // See RFC 6762, 10.1 - pSQAnswer->m_TTLHostDomainAndPort.m_bUpdateScheduled = true; // Avoid 'cache update' query + pSQAnswer->m_TTLHostDomainAndPort.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processSRVAnswer: 'Goodbye' received for ")); _printRRDomain(pSQAnswer->m_ServiceDomain); @@ -875,7 +861,7 @@ bool MDNSResponder::_processTXTAnswer(const MDNSResponder::stcMDNS_RRAnswerTXT* if (p_pTXTAnswer->m_u32TTL) { // First or update message pSQAnswer->m_TTLTxts.set(p_pTXTAnswer->m_u32TTL); // Update TTL tag DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: Updated TTL for ")); + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: Updated TTL(%lu) for "), p_pTXTAnswer->m_u32TTL); _printRRDomain(pSQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); ); @@ -890,8 +876,7 @@ bool MDNSResponder::_processTXTAnswer(const MDNSResponder::stcMDNS_RRAnswerTXT* } } else { // Goodby message - pSQAnswer->m_TTLTxts.set(1); // See RFC 6762, 10.1 - pSQAnswer->m_TTLTxts.m_bUpdateScheduled = true; // Avoid 'cache update' query + pSQAnswer->m_TTLTxts.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processTXTAnswer: 'Goodbye' received for ")); _printRRDomain(pSQAnswer->m_ServiceDomain); @@ -927,14 +912,13 @@ bool MDNSResponder::_processTXTAnswer(const MDNSResponder::stcMDNS_RRAnswerTXT* if (p_pAAnswer->m_u32TTL) { // Valid TTL -> Update answers TTL pIP4Address->m_TTL.set(p_pAAnswer->m_u32TTL); DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL for ")); + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL(%lu) for "), p_pAAnswer->m_u32TTL); _printRRDomain(pSQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(" IP4Address (%s)\n"), pIP4Address->m_IPAddress.toString().c_str()); ); } else { // 'Goodbye' message for known IP4 address - pIP4Address->m_TTL.set(1); // See RFC 6762, 10.1 - pIP4Address->m_TTL.m_bUpdateScheduled = true; // Avoid 'cache update' query + pIP4Address->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: 'Goodbye' received for ")); _printRRDomain(pSQAnswer->m_ServiceDomain); @@ -990,14 +974,13 @@ bool MDNSResponder::_processTXTAnswer(const MDNSResponder::stcMDNS_RRAnswerTXT* if (p_pAAAAAnswer->m_u32TTL) { // Valid TTL -> Update answers TTL pIP6Address->m_TTL.set(p_pAAAAAnswer->m_u32TTL); DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL for ")); + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: Updated TTL(%lu) for "), p_pAAAAAnswer->m_u32TTL); _printRRDomain(pSQAnswer->m_ServiceDomain); DEBUG_OUTPUT.printf_P(PSTR(" IP6 address (%s)\n"), pIP6Address->m_IPAddress.toString().c_str()); ); } else { // 'Goodbye' message for known IP6 address - pIP6Address->m_TTL.set(1); // See RFC 6762, 10.1 - pIP6Address->m_TTL.m_bUpdateScheduled = true; // Avoid 'cache update' query + pIP6Address->m_TTL.prepareDeletion(); // Prepare answer deletion according to RFC 6762, 10.1 DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _processAAnswer: 'Goodbye' received for ")); _printRRDomain(pSQAnswer->m_ServiceDomain); @@ -1061,54 +1044,73 @@ bool MDNSResponder::_updateProbeStatus(void) { DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Starting host probing...\n"));); // First probe delay SHOULD be random 0-250 ms - m_HostProbeInformation.m_NextProbeTimeFlag.restart(rand() % MDNS_PROBE_DELAY); + m_HostProbeInformation.m_Timeout.reset(rand() % MDNS_PROBE_DELAY); m_HostProbeInformation.m_ProbingStatus = ProbingStatus_InProgress; } else if ((ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing AND - (m_HostProbeInformation.m_NextProbeTimeFlag.flagged())) { // Time for next probe + (m_HostProbeInformation.m_Timeout.checkExpired(millis()))) { // Time for next probe - if (MDNS_PROBE_COUNT > m_HostProbeInformation.m_u8ProbesSent) { // Send next probe + if (MDNS_PROBE_COUNT > m_HostProbeInformation.m_u8SentCount) { // Send next probe if ((bResult = _sendHostProbe())) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Did sent host probe\n"));); - m_HostProbeInformation.m_NextProbeTimeFlag.restart(MDNS_PROBE_DELAY); - ++m_HostProbeInformation.m_u8ProbesSent; + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Did sent host probe\n\n"));); + m_HostProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); + ++m_HostProbeInformation.m_u8SentCount; } } else { // Probing finished DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done host probing.\n"));); m_HostProbeInformation.m_ProbingStatus = ProbingStatus_Done; - m_HostProbeInformation.m_NextProbeTimeFlag.reset(); + m_HostProbeInformation.m_Timeout.reset(std::numeric_limits::max()); if (m_HostProbeInformation.m_fnProbeResultCallback) { m_HostProbeInformation.m_fnProbeResultCallback(this, m_pcHostname, 0, true, m_HostProbeInformation.m_pProbeResultCallbackUserdata); } - _announce(); + // Prepare to announce host + m_HostProbeInformation.m_u8SentCount = 0; + m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Prepared host announcing.\n\n"));); } } // else: Probing already finished OR waiting for next time slot + else if ((ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus) && + (m_HostProbeInformation.m_Timeout.checkExpired(std::numeric_limits::max()))) { + + if ((bResult = _announce(true, false))) { // Don't announce services here + ++m_HostProbeInformation.m_u8SentCount; + + if (MDNS_ANNOUNCE_COUNT > m_HostProbeInformation.m_u8SentCount) { + m_HostProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing host (%lu).\n\n"), m_HostProbeInformation.m_u8SentCount);); + } + else { + m_HostProbeInformation.m_Timeout.reset(std::numeric_limits::max()); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done host announcing.\n\n"));); + } + } + } // // Probe services for (stcMDNSService* pService=m_pServices; ((bResult) && (pService)); pService=pService->m_pNext) { if (ProbingStatus_ReadyToStart == pService->m_ProbeInformation.m_ProbingStatus) { // Ready to get started - pService->m_ProbeInformation.m_NextProbeTimeFlag.restart(MDNS_PROBE_DELAY); // More or equal than first probe for host domain + pService->m_ProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); // More or equal than first probe for host domain pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_InProgress; } else if ((ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing AND - (pService->m_ProbeInformation.m_NextProbeTimeFlag.flagged())) { // Time for next probe + (pService->m_ProbeInformation.m_Timeout.checkExpired(millis()))) { // Time for next probe - if (MDNS_PROBE_COUNT > pService->m_ProbeInformation.m_u8ProbesSent) { // Send next probe + if (MDNS_PROBE_COUNT > pService->m_ProbeInformation.m_u8SentCount) { // Send next probe if ((bResult = _sendServiceProbe(*pService))) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Did sent service probe (%u)\n"), (pService->m_ProbeInformation.m_u8ProbesSent + 1));); - pService->m_ProbeInformation.m_NextProbeTimeFlag.restart(MDNS_PROBE_DELAY); - ++pService->m_ProbeInformation.m_u8ProbesSent; + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Did sent service probe (%u)\n\n"), (pService->m_ProbeInformation.m_u8SentCount + 1));); + pService->m_ProbeInformation.m_Timeout.reset(MDNS_PROBE_DELAY); + ++pService->m_ProbeInformation.m_u8SentCount; } } else { // Probing finished - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done service probing %s.%s.%s\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done service probing %s.%s.%s\n\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_Done; - pService->m_ProbeInformation.m_NextProbeTimeFlag.reset(); + pService->m_ProbeInformation.m_Timeout.reset(std::numeric_limits::max()); MDNSProbeResultCallbackFn fnProbeResultCallback = 0; void* pProbeResultCallbackUserdata = 0; @@ -1124,11 +1126,30 @@ bool MDNSResponder::_updateProbeStatus(void) { fnProbeResultCallback(this, (pService->m_pcName ?: m_pcHostname), pService, true, pProbeResultCallbackUserdata); } - //_announceService(*pService); + // Prepare to announce service + pService->m_ProbeInformation.m_u8SentCount = 0; + pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Prepared service announcing.\n\n"));); } } // else: Probing already finished OR waiting for next time slot + else if ((ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus) && + (pService->m_ProbeInformation.m_Timeout.checkExpired(millis()))) { + + if ((bResult = _announceService(*pService))) { // Announce service + ++pService->m_ProbeInformation.m_u8SentCount; + + if (MDNS_ANNOUNCE_COUNT > pService->m_ProbeInformation.m_u8SentCount) { + pService->m_ProbeInformation.m_Timeout.reset(MDNS_ANNOUNCE_DELAY); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing service %s.%s.%s (%lu)\n\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_ProbeInformation.m_u8SentCount);); + } + else { + pService->m_ProbeInformation.m_Timeout.reset(std::numeric_limits::max()); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done service announcing for %s.%s.%s\n\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol);); + } + } + } } - DEBUG_EX_ERR(if (!bResult) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: FAILED!\n")); }); + DEBUG_EX_ERR(if (!bResult) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: FAILED!\n\n")); }); return bResult; } @@ -1158,11 +1179,11 @@ bool MDNSResponder::_resetProbeStatus(bool p_bRestart /*= true*/) { bool MDNSResponder::_hasProbesWaitingForAnswers(void) const { bool bResult = ((ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing - (0 < m_HostProbeInformation.m_u8ProbesSent)); // And really probing + (0 < m_HostProbeInformation.m_u8SentCount)); // And really probing for (stcMDNSService* pService=m_pServices; ((!bResult) && (pService)); pService=pService->m_pNext) { bResult = ((ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing - (0 < pService->m_ProbeInformation.m_u8ProbesSent)); // And really probing + (0 < pService->m_ProbeInformation.m_u8SentCount)); // And really probing } return bResult; } @@ -1191,9 +1212,9 @@ bool MDNSResponder::_sendHostProbe(void) { if (((bResult = (0 != sendParameter.m_pQuestions))) && ((bResult = _buildDomainForHost(m_pcHostname, sendParameter.m_pQuestions->m_Header.m_Domain)))) { - sendParameter.m_pQuestions->m_bUnicast = true; + //sendParameter.m_pQuestions->m_bUnicast = true; sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = DNS_RRTYPE_ANY; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (/*0x8000 |*/ DNS_RRCLASS_IN); // Unicast & INternet // Add known answers #ifdef MDNS_IP4_SUPPORT @@ -1331,7 +1352,8 @@ bool MDNSResponder::_cancelProbingForService(stcMDNSService& p_rService) { * Goodbye messages are created by setting the TTL for the answer to 0, this happens * inside the '_writeXXXAnswer' procs via 'sendParameter.m_bUnannounce = true' */ -bool MDNSResponder::_announce(bool p_bAnnounce /*= true*/) { +bool MDNSResponder::_announce(bool p_bAnnounce, + bool p_bIncludeServices) { bool bResult = false; @@ -1355,27 +1377,22 @@ bool MDNSResponder::_announce(bool p_bAnnounce /*= true*/) { sendParameter.m_u8HostReplyMask |= ContentFlag_PTR_IP6; // PTR_IP6 answer #endif - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: Announcing host %s (%u)\n"), m_pcHostname, sendParameter.m_u8HostReplyMask);); - //bResult = _sendMDNSMessage(sendParameter); - //DEBUG_EX_ERR(if (!bResult) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announceService: FAILED (A)!\n")); }); - - // Announce services (service type, name, SRV (location) and TXTs) - for (stcMDNSService* pService=m_pServices; ((bResult) && (pService)); pService=pService->m_pNext) { - //bResult = _announceService(*pService, p_bAnnounce); - //DEBUG_EX_ERR(if (!bResult) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announceService: FAILED (B)!\n")); }); - + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: Announcing host %s (content 0x%X)\n"), m_pcHostname, sendParameter.m_u8HostReplyMask);); - if (ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus) { - pService->m_u8ReplyMask = (ContentFlag_PTR_TYPE | ContentFlag_PTR_NAME | ContentFlag_SRV | ContentFlag_TXT); + if (p_bIncludeServices) { + // Announce services (service type, name, SRV (location) and TXTs) + for (stcMDNSService* pService=m_pServices; ((bResult) && (pService)); pService=pService->m_pNext) { + if (ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus) { + pService->m_u8ReplyMask = (ContentFlag_PTR_TYPE | ContentFlag_PTR_NAME | ContentFlag_SRV | ContentFlag_TXT); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: Announcing service %s.%s.%s (%u)\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_u8ReplyMask);); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: Announcing service %s.%s.%s (content %u)\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_u8ReplyMask);); + } } } } - DEBUG_EX_ERR(if (!bResult) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announceService: FAILED!\n")); }); + DEBUG_EX_ERR(if (!bResult) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announce: FAILED!\n")); }); return ((bResult) && (_sendMDNSMessage(sendParameter))); - //return bResult; } /* @@ -1398,7 +1415,7 @@ bool MDNSResponder::_announceService(stcMDNSService& p_rService, // Announce services (service type, name, SRV (location) and TXTs) p_rService.m_u8ReplyMask = (ContentFlag_PTR_TYPE | ContentFlag_PTR_NAME | ContentFlag_SRV | ContentFlag_TXT); - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announceService: Announcing service %s.%s.%s (%u)\n"), (p_rService.m_pcName ?: m_pcHostname), p_rService.m_pcService, p_rService.m_pcProtocol, p_rService.m_u8ReplyMask);); + DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _announceService: Announcing service %s.%s.%s (content 0x%X)\n"), (p_rService.m_pcName ?: m_pcHostname), p_rService.m_pcService, p_rService.m_pcProtocol, p_rService.m_u8ReplyMask);); bResult = true; } @@ -1441,7 +1458,31 @@ bool MDNSResponder::_checkServiceQueryCache(void) { bool bResult = true; + DEBUG_EX_INFO( + bool printedInfo = false; + ); for (stcMDNSServiceQuery* pServiceQuery=m_pServiceQueries; ((bResult) && (pServiceQuery)); pServiceQuery=pServiceQuery->m_pNext) { + + // + // Resend dynamic service queries, if not already done often enough + if ((!pServiceQuery->m_bLegacyQuery) && + (MDNS_DYNAMIC_QUERY_RESEND_COUNT > pServiceQuery->m_u8SentCount) && + (pServiceQuery->m_ResendTimeout.checkExpired(millis()))) { + + if ((bResult = _sendMDNSServiceQuery(*pServiceQuery))) { + ++pServiceQuery->m_u8SentCount; + pServiceQuery->m_ResendTimeout.reset((MDNS_DYNAMIC_QUERY_RESEND_COUNT > pServiceQuery->m_u8SentCount) + ? (MDNS_DYNAMIC_QUERY_RESEND_DELAY * (pServiceQuery->m_u8SentCount - 1)) + : std::numeric_limits::max()); + } + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: %s to resend service query!"), (bResult ? "Succeeded" : "FAILED")); + printedInfo = true; + ); + } + + // + // Schedule updates for cached answers if (pServiceQuery->m_bAwaitingAnswers) { stcMDNSServiceQuery::stcAnswer* pSQAnswer = pServiceQuery->m_pAnswers; while ((bResult) && @@ -1450,94 +1491,121 @@ bool MDNSResponder::_checkServiceQueryCache(void) { // 1. level answer if ((bResult) && - (pSQAnswer->m_TTLServiceDomain.has80Percent())) { - - bResult = ((_sendMDNSServiceQuery(*pServiceQuery)) && - ((pSQAnswer->m_TTLServiceDomain.m_bUpdateScheduled = true))); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Update scheduled for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" %s\n"), (bResult ? "OK" : "FAILURE")); - ); - } - else if ((bResult) && - (pSQAnswer->m_TTLServiceDomain.isOutdated())) { - - // Delete - if (pServiceQuery->m_fnCallback) { - pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer)/*(uint32_t)(-1)*/, ServiceQueryAnswerType_ServiceDomain, false, pServiceQuery->m_pUserdata); + (pSQAnswer->m_TTLServiceDomain.flagged())) { + + if (!pSQAnswer->m_TTLServiceDomain.finalTimeoutLevel()) { + + bResult = ((_sendMDNSServiceQuery(*pServiceQuery)) && + (pSQAnswer->m_TTLServiceDomain.restart())); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: PTR update scheduled for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" %s\n"), (bResult ? "OK" : "FAILURE")); + printedInfo = true; + ); } - bResult = pServiceQuery->removeAnswer(pSQAnswer); - pSQAnswer = 0; - continue; // Don't use this answer anymore - } + else { + // Timed out! -> Delete + if (pServiceQuery->m_fnCallback) { + pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), ServiceQueryAnswerType_ServiceDomain, false, pServiceQuery->m_pUserdata); + } + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove PTR answer for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR("\n")); + printedInfo = true; + ); + + bResult = pServiceQuery->removeAnswer(pSQAnswer); + pSQAnswer = 0; + continue; // Don't use this answer anymore + } + } // ServiceDomain flagged // 2. level answers // HostDomain & Port (from SRV) if ((bResult) && - (pSQAnswer->m_TTLHostDomainAndPort.has80Percent())) { - - bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_SRV)) && - ((pSQAnswer->m_TTLHostDomainAndPort.m_bUpdateScheduled = true))); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Update scheduled for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" host domain and port %s\n"), (bResult ? "OK" : "FAILURE")); - ); - } - else if ((bResult) && - (pSQAnswer->m_TTLHostDomainAndPort.isOutdated())) { - - // Delete - pSQAnswer->m_HostDomain.clear(); - pSQAnswer->releaseHostDomain(); - pSQAnswer->m_u16Port = 0; - pSQAnswer->m_TTLHostDomainAndPort.set(0/*, 0*/); - uint32_t u32ContentFlags = ServiceQueryAnswerType_HostDomainAndPort; - // As the host domain is the base for the IP4- and IP6Address, remove these too -#ifdef MDNS_IP4_SUPPORT - pSQAnswer->releaseIP4Addresses(); - u32ContentFlags |= ServiceQueryAnswerType_IP4Address; -#endif -#ifdef MDNS_IP6_SUPPORT - pSQAnswer->releaseIP6Addresses(); - u32ContentFlags |= ServiceQueryAnswerType_IP6Address; -#endif + (pSQAnswer->m_TTLHostDomainAndPort.flagged())) { - // Remove content flags for deleted answer parts - pSQAnswer->m_u32ContentFlags &= ~u32ContentFlags; + if (!pSQAnswer->m_TTLHostDomainAndPort.finalTimeoutLevel()) { - if (pServiceQuery->m_fnCallback) { - pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), u32ContentFlags, false, pServiceQuery->m_pUserdata); + bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_SRV)) && + (pSQAnswer->m_TTLHostDomainAndPort.restart())); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: SRV update scheduled for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" host domain and port %s\n"), (bResult ? "OK" : "FAILURE")); + printedInfo = true; + ); } - } + else { + // Timed out! -> Delete + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove SRV answer for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" host domain and port\n")); + printedInfo = true; + ); + // Delete + pSQAnswer->m_HostDomain.clear(); + pSQAnswer->releaseHostDomain(); + pSQAnswer->m_u16Port = 0; + pSQAnswer->m_TTLHostDomainAndPort.set(0); + uint32_t u32ContentFlags = ServiceQueryAnswerType_HostDomainAndPort; + // As the host domain is the base for the IP4- and IP6Address, remove these too + #ifdef MDNS_IP4_SUPPORT + pSQAnswer->releaseIP4Addresses(); + u32ContentFlags |= ServiceQueryAnswerType_IP4Address; + #endif + #ifdef MDNS_IP6_SUPPORT + pSQAnswer->releaseIP6Addresses(); + u32ContentFlags |= ServiceQueryAnswerType_IP6Address; + #endif + + // Remove content flags for deleted answer parts + pSQAnswer->m_u32ContentFlags &= ~u32ContentFlags; + + if (pServiceQuery->m_fnCallback) { + pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), u32ContentFlags, false, pServiceQuery->m_pUserdata); + } + } + } // HostDomainAndPort flagged // Txts (from TXT) if ((bResult) && - (pSQAnswer->m_TTLTxts.has80Percent())) { - - bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_TXT)) && - ((pSQAnswer->m_TTLTxts.m_bUpdateScheduled = true))); - DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Update scheduled for ")); - _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" TXTs %s\n"), (bResult ? "OK" : "FAILURE")); - ); - } - else if ((bResult) && - (pSQAnswer->m_TTLTxts.isOutdated())) { - - // Delete - pSQAnswer->m_Txts.clear(); - pSQAnswer->m_TTLTxts.set(0/*, 0*/); - - // Remove content flags for deleted answer parts - pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_Txts; + (pSQAnswer->m_TTLTxts.flagged())) { - if (pServiceQuery->m_fnCallback) { - pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), ServiceQueryAnswerType_Txts, false, pServiceQuery->m_pUserdata); + if (!pSQAnswer->m_TTLTxts.finalTimeoutLevel()) { + + bResult = ((_sendMDNSQuery(pSQAnswer->m_ServiceDomain, DNS_RRTYPE_TXT)) && + (pSQAnswer->m_TTLTxts.restart())); + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: TXT update scheduled for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" TXTs %s\n"), (bResult ? "OK" : "FAILURE")); + printedInfo = true; + ); } - } + else { + // Timed out! -> Delete + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove TXT answer for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" TXTs\n")); + printedInfo = true; + ); + // Delete + pSQAnswer->m_Txts.clear(); + pSQAnswer->m_TTLTxts.set(0); + + // Remove content flags for deleted answer parts + pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_Txts; + + if (pServiceQuery->m_fnCallback) { + pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), ServiceQueryAnswerType_Txts, false, pServiceQuery->m_pUserdata); + } + } + } // TXTs flagged // 3. level answers #ifdef MDNS_IP4_SUPPORT @@ -1549,30 +1617,42 @@ bool MDNSResponder::_checkServiceQueryCache(void) { stcMDNSServiceQuery::stcAnswer::stcIP4Address* pNextIP4Address = pIP4Address->m_pNext; // Get 'next' early, as 'current' may be deleted at the end... - if (pIP4Address->m_TTL.has80Percent()) { // Needs update - if ((bAUpdateQuerySent) || - ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_A)))) { - - pIP4Address->m_TTL.m_bUpdateScheduled = true; - bAUpdateQuerySent = true; - + if (pIP4Address->m_TTL.flagged()) { + + if (!pIP4Address->m_TTL.finalTimeoutLevel()) { // Needs update + + if ((bAUpdateQuerySent) || + ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_A)))) { + + pIP4Address->m_TTL.restart(); + bAUpdateQuerySent = true; + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: IP4 update scheduled for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IP4 address (%s)\n"), (pIP4Address->m_IPAddress.toString().c_str())); + printedInfo = true; + ); + } + } + else { + // Timed out! -> Delete DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Update scheduled for ")); + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove IP4 answer for ")); _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP4 address (%s)\n"), (pIP4Address->m_IPAddress.toString().c_str())); + DEBUG_OUTPUT.printf_P(PSTR(" IP4 address\n")); + printedInfo = true; ); + pSQAnswer->removeIP4Address(pIP4Address); + if (!pSQAnswer->m_pIP4Addresses) { // NO IP4 address left -> remove content flag + pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_IP4Address; + } + // Notify client + if (pServiceQuery->m_fnCallback) { + pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), ServiceQueryAnswerType_IP4Address, false, pServiceQuery->m_pUserdata); + } } - } - else if (pIP4Address->m_TTL.isOutdated()) { // Outdated: can be deleted - pSQAnswer->removeIP4Address(pIP4Address); - if (!pSQAnswer->m_pIP4Addresses) { // NO IP4 address left -> remove content flag - pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_IP4Address; - } - // Notify client - if (pServiceQuery->m_fnCallback) { - pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), ServiceQueryAnswerType_IP4Address, false, pServiceQuery->m_pUserdata); - } - } + } // IP4 flagged pIP4Address = pNextIP4Address; // Next } // while @@ -1586,30 +1666,42 @@ bool MDNSResponder::_checkServiceQueryCache(void) { stcMDNSServiceQuery::stcAnswer::stcIP6Address* pNextIP6Address = pIP6Address->m_pNext; // Get 'next' early, as 'current' may be deleted at the end... - if (pIP6Address->m_TTL.has80Percent()) { // Needs update - if ((bAAAAUpdateQuerySent) || - ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) { - - pIP6Address->m_TTL.m_bUpdateScheduled = true; - bAAAAUpdateQuerySent = true; + if (pIP6Address->m_TTL.flagged()) { + + if (!pIP6Address->m_TTL.finalTimeoutLevel()) { // Needs update + if ((bAAAAUpdateQuerySent) || + ((bResult = _sendMDNSQuery(pSQAnswer->m_HostDomain, DNS_RRTYPE_AAAA)))) { + + pIP6Address->m_TTL.restart(); + bAAAAUpdateQuerySent = true; + + DEBUG_EX_INFO( + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: IP6 update scheduled for ")); + _printRRDomain(pSQAnswer->m_ServiceDomain); + DEBUG_OUTPUT.printf_P(PSTR(" IP6 address (%s)\n"), (pIP6Address->m_IPAddress.toString().c_str())); + printedInfo = true; + ); + } + } + else { + // Timed out! -> Delete DEBUG_EX_INFO( - DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Update scheduled for ")); + DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: Will remove answer for ")); _printRRDomain(pSQAnswer->m_ServiceDomain); - DEBUG_OUTPUT.printf_P(PSTR(" IP6 address (%s)\n"), (pIP6Address->m_IPAddress.toString().c_str())); + DEBUG_OUTPUT.printf_P(PSTR(" IP6Address\n")); + printedInfo = true; ); + pSQAnswer->removeIP6Address(pIP6Address); + if (!pSQAnswer->m_pIP6Addresses) { // NO IP6 address left -> remove content flag + pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_IP6Address; + } + // Notify client + if (pServiceQuery->m_fnCallback) { + pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), ServiceQueryAnswerType_IP6Address, false, pServiceQuery->m_pUserdata); + } } - } - else if (pIP6Address->m_TTL.isOutdated()) { // Outdated: can be deleted - pSQAnswer->removeIP6Address(pIP6Address); - if (!pSQAnswer->m_pIP6Addresses) { // NO IP6 address left -> remove content flag - pSQAnswer->m_u32ContentFlags &= ~ServiceQueryAnswerType_IP6Address; - } - // Notify client - if (pServiceQuery->m_fnCallback) { - pServiceQuery->m_fnCallback(this, (hMDNSServiceQuery)pServiceQuery, pServiceQuery->indexOfAnswer(pSQAnswer), ServiceQueryAnswerType_IP6Address, false, pServiceQuery->m_pUserdata); - } - } + } // IP6 flagged pIP6Address = pNextIP6Address; // Next } // while @@ -1618,6 +1710,11 @@ bool MDNSResponder::_checkServiceQueryCache(void) { } } } + DEBUG_EX_INFO( + if (printedInfo) { + DEBUG_OUTPUT.printf_P(PSTR("\n")); + } + ); DEBUG_EX_ERR(if (!bResult) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: FAILED!\n")); }); return bResult; } @@ -1683,7 +1780,7 @@ uint8_t MDNSResponder::_replyMaskForHost(const MDNSResponder::stcMDNS_RRHeader& else { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForHost: INVALID RR-class (0x%04X)!\n"), p_RRHeader.m_Attributes.m_u16Class);); } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForHost: %u\n"), u8ReplyMask);); + DEBUG_EX_INFO(if (u8ReplyMask) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForHost: 0x%X\n"), u8ReplyMask); } ); return u8ReplyMask; } @@ -1747,7 +1844,7 @@ uint8_t MDNSResponder::_replyMaskForService(const MDNSResponder::stcMDNS_RRHeade else { //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForService: INVALID RR-class (0x%04X)!\n"), p_RRHeader.m_Attributes.m_u16Class);); } - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForService(%s.%s.%s): %u\n"), p_Service.m_pcName, p_Service.m_pcService, p_Service.m_pcProtocol, u8ReplyMask);); + DEBUG_EX_INFO(if (u8ReplyMask) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _replyMaskForService(%s.%s.%s): 0x%X\n"), p_Service.m_pcName, p_Service.m_pcService, p_Service.m_pcProtocol, u8ReplyMask); } ); return u8ReplyMask; } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp index d745f0b37e..f8042ff185 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Helpers.cpp @@ -170,6 +170,7 @@ namespace MDNSImplementation { */ bool MDNSResponder::_callProcess(void) { + DEBUG_EX_INFO(DEBUG_OUTPUT.printf("[MDNSResponder] _callProcess (%lu, triggered by: %s)\n", millis(), m_pUDPContext->getRemoteAddress().toString().c_str());); return _process(false); } diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Priv.h b/libraries/ESP8266mDNS/src/LEAmDNS_Priv.h index 8abea5c31d..76ed927291 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Priv.h +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Priv.h @@ -35,16 +35,21 @@ namespace MDNSImplementation { // Enable class debug functions #define ESP_8266_MDNS_INCLUDE -// #define DEBUG_ESP_MDNS_RESPONDER +//#define DEBUG_ESP_MDNS_RESPONDER #ifndef LWIP_OPEN_SRC #define LWIP_OPEN_SRC #endif +// +// If ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE is defined, the mDNS responder ignores a successful probing +// This allows to drive the responder in a environment, where 'update()' isn't called in the loop +//#define ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE + // Enable/disable debug trace macros #ifdef DEBUG_ESP_MDNS_RESPONDER -//#define DEBUG_ESP_MDNS_INFO +#define DEBUG_ESP_MDNS_INFO #define DEBUG_ESP_MDNS_ERR #define DEBUG_ESP_MDNS_TX #define DEBUG_ESP_MDNS_RX @@ -99,8 +104,10 @@ namespace MDNSImplementation { * subnet level distance MDNS records should travel. * 1 sets the subnet distance to 'local', which is default for MDNS. * (Btw.: 255 would set it to 'as far as possible' -> internet) + * + * However, RFC 3171 seems to force 255 instead */ -#define MDNS_MULTICAST_TTL 1 +#define MDNS_MULTICAST_TTL 255/*1*/ /* * This is the MDNS record TTL @@ -127,9 +134,15 @@ namespace MDNSImplementation { /* * Delay between and number of probes for host and service domains + * Delay between and number of announces for host and service domains + * Delay between and number of service queries; the delay is multiplied by the resent number in '_checkServiceQueryCache' */ #define MDNS_PROBE_DELAY 250 #define MDNS_PROBE_COUNT 3 +#define MDNS_ANNOUNCE_DELAY 1000 +#define MDNS_ANNOUNCE_COUNT 8 +#define MDNS_DYNAMIC_QUERY_RESEND_COUNT 5 +#define MDNS_DYNAMIC_QUERY_RESEND_DELAY 5000 /* diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp index c30094f580..e41e4a08ba 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Structs.cpp @@ -1158,9 +1158,8 @@ bool MDNSResponder::stcMDNS_RRAnswerGeneric::clear(void) { */ MDNSResponder::stcProbeInformation::stcProbeInformation(void) : m_ProbingStatus(ProbingStatus_WaitingForData), - m_u8ProbesSent(0), - //m_ulNextProbeTimeout(0), - m_NextProbeTimeFlag(), + m_u8SentCount(0), + m_Timeout(std::numeric_limits::max()), m_bConflict(false), m_bTiebreakNeeded(false), m_fnProbeResultCallback(0), @@ -1173,9 +1172,8 @@ MDNSResponder::stcProbeInformation::stcProbeInformation(void) bool MDNSResponder::stcProbeInformation::clear(bool p_bClearUserdata /*= false*/) { m_ProbingStatus = ProbingStatus_WaitingForData; - m_u8ProbesSent = 0; - //m_ulNextProbeTimeout = 0; - m_NextProbeTimeFlag.reset(); + m_u8SentCount = 0; + m_Timeout.reset(std::numeric_limits::max()); m_bConflict = false; m_bTiebreakNeeded = false; if (p_bClearUserdata) { @@ -1200,8 +1198,8 @@ bool MDNSResponder::stcProbeInformation::clear(bool p_bClearUserdata /*= false*/ * MDNSResponder::stcMDNSService::stcMDNSService constructor */ MDNSResponder::stcMDNSService::stcMDNSService(const char* p_pcName /*= 0*/, - const char* p_pcService /*= 0*/, - const char* p_pcProtocol /*= 0*/) + const char* p_pcService /*= 0*/, + const char* p_pcProtocol /*= 0*/) : m_pNext(0), m_pcName(0), m_bAutoName(false), @@ -1367,20 +1365,20 @@ bool MDNSResponder::stcMDNSService::releaseProtocol(void) { * and the 'set' time (also millis). * If the answer is scheduled for an update, the corresponding flag should be set. * - */ + * / -/* +/ * * MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL constructor - */ -MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL(uint32_t p_u32TTL /*= 0*/) + * / +MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL(uint32_t p_u32TTL / *= 0* /) : m_bUpdateScheduled(false) { set(p_u32TTL * 1000); } -/* +/ * * MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set - */ + * / bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set(uint32_t p_u32TTL) { m_TTLTimeFlag.restart(p_u32TTL * 1000); @@ -1389,9 +1387,9 @@ bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set(uint32_t p_u32TT return true; } -/* +/ * * MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::has80Percent - */ + * / bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::has80Percent(void) const { return ((m_TTLTimeFlag.getTimeout()) && @@ -1399,13 +1397,119 @@ bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::has80Percent(void) c (m_TTLTimeFlag.hypotheticalTimeout((m_TTLTimeFlag.getTimeout() * 800) / 1000))); } -/* +/ * * MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::isOutdated - */ + * / bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::isOutdated(void) const { return ((m_TTLTimeFlag.getTimeout()) && (m_TTLTimeFlag.flagged())); +}*/ + + +/** + * MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL + * + * The TTL (Time-To-Live) for an specific answer content. + * The 80% and outdated states are calculated based on the current time (millis) + * and the 'set' time (also millis). + * If the answer is scheduled for an update, the corresponding flag should be set. + * + */ + +/* + * MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL constructor + */ +MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL(void) +: m_u32TTL(0), + m_TTLTimeout(std::numeric_limits::max()), + m_timeoutLevel(TIMEOUTLEVEL_UNSET) { + +} + +/* + * MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set + */ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set(uint32_t p_u32TTL) { + + m_u32TTL = p_u32TTL; + if (m_u32TTL) { + m_timeoutLevel = TIMEOUTLEVEL_BASE; // Set to 80% + m_TTLTimeout.reset(timeout()); + } + else { + m_timeoutLevel = TIMEOUTLEVEL_UNSET; // undef + m_TTLTimeout.reset(std::numeric_limits::max()); + } + return true; +} + +/* + * MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged + */ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged(void) const { + + return ((m_u32TTL) && + (TIMEOUTLEVEL_UNSET != m_timeoutLevel) && + (m_TTLTimeout.checkExpired(millis()))); +} + +/* + * MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::restart + */ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::restart(void) { + + bool bResult = true; + + if ((TIMEOUTLEVEL_BASE <= m_timeoutLevel) && // >= 80% AND + (TIMEOUTLEVEL_FINAL > m_timeoutLevel)) { // < 100% + + m_timeoutLevel += TIMEOUTLEVEL_INTERVAL; // increment by 5% + m_TTLTimeout.reset(timeout()); + } + else { + bResult = false; + m_TTLTimeout.reset(std::numeric_limits::max()); + m_timeoutLevel = TIMEOUTLEVEL_UNSET; + } + return bResult; +} + +/* + * MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::prepareDeletion + */ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::prepareDeletion(void) { + + m_timeoutLevel = TIMEOUTLEVEL_FINAL; + m_TTLTimeout.reset(1 * 1000); // See RFC 6762, 10.1 + + return true; +} + +/* + * MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::finalTimeoutLevel + */ +bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::finalTimeoutLevel(void) const { + + return (TIMEOUTLEVEL_FINAL == m_timeoutLevel); +} + +/* + * MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::timeout + */ +unsigned long MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::timeout(void) const { + + uint32_t u32Timeout = std::numeric_limits::max(); + + if (TIMEOUTLEVEL_BASE == m_timeoutLevel) { // 80% + u32Timeout = (m_u32TTL * 800); // to milliseconds + } + else if ((TIMEOUTLEVEL_BASE < m_timeoutLevel) && // >80% AND + (TIMEOUTLEVEL_FINAL >= m_timeoutLevel)) { // <= 100% + + u32Timeout = (m_u32TTL * 50); + } // else: invalid + return u32Timeout; } @@ -1421,8 +1525,9 @@ bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::isOutdated(void) con MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcIP4Address::stcIP4Address(IPAddress p_IPAddress, uint32_t p_u32TTL /*= 0*/) : m_pNext(0), - m_IPAddress(p_IPAddress), - m_TTL(p_u32TTL) { + m_IPAddress(p_IPAddress) { + + m_TTL.set(p_u32TTL); } #endif @@ -1818,6 +1923,8 @@ MDNSResponder::stcMDNSServiceQuery::stcMDNSServiceQuery(void) m_fnCallback(0), m_pUserdata(0), m_bLegacyQuery(false), + m_u8SentCount(0), + m_ResendTimeout(std::numeric_limits::max()), m_bAwaitingAnswers(true), m_pAnswers(0) { @@ -1840,6 +1947,8 @@ bool MDNSResponder::stcMDNSServiceQuery::clear(void) { m_fnCallback = 0; m_pUserdata = 0; m_bLegacyQuery = false; + m_u8SentCount = 0; + m_ResendTimeout.reset(std::numeric_limits::max()); m_bAwaitingAnswers = true; while (m_pAnswers) { stcAnswer* pNext = m_pAnswers->m_pNext; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp index e163d64daa..9554f97df1 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Transfer.cpp @@ -343,7 +343,8 @@ bool MDNSResponder::_sendMDNSServiceQuery(const MDNSResponder::stcMDNSServiceQue * */ bool MDNSResponder::_sendMDNSQuery(const MDNSResponder::stcMDNS_RRDomain& p_QueryDomain, - uint16_t p_u16QueryType) { + uint16_t p_u16QueryType, + stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers /*= 0*/) { bool bResult = false; @@ -351,9 +352,12 @@ bool MDNSResponder::_sendMDNSQuery(const MDNSResponder::stcMDNS_RRDomain& p_Quer if (0 != ((sendParameter.m_pQuestions = new stcMDNS_RRQuestion))) { sendParameter.m_pQuestions->m_Header.m_Domain = p_QueryDomain; - sendParameter.m_pQuestions->m_bUnicast = true; sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Type = p_u16QueryType; - sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (0x8000 | DNS_RRCLASS_IN); // Unicast & INternet + // It seems, that some mDNS implementations don't support 'unicast response' questions... + sendParameter.m_pQuestions->m_Header.m_Attributes.m_u16Class = (/*0x8000 |*/ DNS_RRCLASS_IN); // /*Unicast &*/ INternet + + // TODO: Add knwon answer to the query + (void)p_pKnownAnswers; bResult = _sendMDNSMessage(sendParameter); } // else: FAILED to alloc question @@ -447,7 +451,7 @@ bool MDNSResponder::_readRRQuestion(MDNSResponder::stcMDNS_RRQuestion& p_rRRQues * */ bool MDNSResponder::_readRRAnswer(MDNSResponder::stcMDNS_RRAnswer*& p_rpRRAnswer) { - DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer\n"));); + //DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer\n"));); bool bResult = false; @@ -458,11 +462,11 @@ bool MDNSResponder::_readRRAnswer(MDNSResponder::stcMDNS_RRAnswer*& p_rpRRAnswer (_udpRead32(u32TTL)) && (_udpRead16(u16RDLength))) { - DEBUG_EX_INFO( + /*DEBUG_EX_INFO( DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _readRRAnswer: Reading 0x%04X answer (class:0x%04X, TTL:%u, RDLength:%u) for "), header.m_Attributes.m_u16Type, header.m_Attributes.m_u16Class, u32TTL, u16RDLength); _printRRDomain(header.m_Domain); DEBUG_OUTPUT.printf_P(PSTR("\n")); - ); + );*/ switch (header.m_Attributes.m_u16Type & (~0x8000)) { // Topmost bit might carry 'cache flush' flag #ifdef MDNS_IP4_SUPPORT From a070d948b18c517b305ed5dcdc05f9f97155e879 Mon Sep 17 00:00:00 2001 From: LaborEtArs Date: Tue, 15 Jan 2019 18:45:15 +0100 Subject: [PATCH 2/3] Update mDNS_Clock.ino Removed references to LEATimeFlag.h --- .../examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino index ea8a60a05c..15f159e985 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino @@ -190,11 +190,13 @@ bool MDNSProbeResultCallback(MDNSResponder* p_pMDNSResponder, } } } - } else { + } + else { // Change hostname, use '-' as divider between base name and index if (MDNSResponder::indexDomain(pcHostDomain, "-", 0)) { p_pMDNSResponder->setHostname(pcHostDomain); - } else { + } + else { Serial.println("MDNSProbeResultCallback: FAILED to update hostname!"); } } @@ -249,7 +251,8 @@ void handleHTTPClient(WiFiClient& client) { // done :-) s += "\r\n\r\n"; Serial.println("Sending 200"); - } else { + } + else { s = "HTTP/1.1 404 Not Found\r\n\r\n"; Serial.println("Sending 404"); } @@ -316,17 +319,14 @@ void loop(void) { MDNS.update(); // Update time (if needed) - //static unsigned long ulNextTimeUpdate = UPDATE_CYCLE; - static clsMDNSTimeFlag timeFlag(UPDATE_CYCLE); - if (timeFlag.flagged()/*ulNextTimeUpdate < millis()*/) { + static esp8266::polledTimeout::periodic 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 MDNS.announce(); } - //ulNextTimeUpdate = (millis() + UPDATE_CYCLE); // Set update 'timer' - timeFlag.restart(); } } From e21fd47081d591b022a4ae9d8c360a9a3490eaca Mon Sep 17 00:00:00 2001 From: LaborEtArs Date: Tue, 15 Jan 2019 19:22:47 +0100 Subject: [PATCH 3/3] Update mDNS_Clock.ino Styling --- .../examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino index 15f159e985..660271b70b 100644 --- a/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino +++ b/libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino @@ -190,13 +190,11 @@ bool MDNSProbeResultCallback(MDNSResponder* p_pMDNSResponder, } } } - } - else { + } else { // Change hostname, use '-' as divider between base name and index if (MDNSResponder::indexDomain(pcHostDomain, "-", 0)) { p_pMDNSResponder->setHostname(pcHostDomain); - } - else { + } else { Serial.println("MDNSProbeResultCallback: FAILED to update hostname!"); } } @@ -251,8 +249,7 @@ void handleHTTPClient(WiFiClient& client) { // done :-) s += "\r\n\r\n"; Serial.println("Sending 200"); - } - else { + } else { s = "HTTP/1.1 404 Not Found\r\n\r\n"; Serial.println("Sending 404"); }